前言

本文是参考Build a Command Line app with Go: lolcat所实现的一个 toy-demo ,主要用于本人的一个留档记录。

开始实践

获取测试文本

这里我们导入syreclabs.com/go/faker用于获取测试文本,使用如下语句导入:

1
go get -u syreclabs.com/go/faker

该部分代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"strings"

"syreclabs.com/go/faker"
)

func main() {
var phrases []string

for i := 1; i < 3; i++ {
phrases = append(phrases, faker.Hacker().Phrases()...)
}

fmt.Println(strings.Join(phrases[:], "; "))
}

输出效果如下:
faker text

改变输出文本颜色

我们可以通过在输出语句中添加转义字符序列来实现这一点。这里将所有输出的字符串转为金色,其 RGB 颜色代码为 (255,215,0):
代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"strings"

"syreclabs.com/go/faker"
)

func main() {
var phrases []string

for i := 1; i < 3; i++ {
phrases = append(phrases, faker.Hacker().Phrases()...)
}

output := strings.Join(phrases[:], "; ")
r, g, b := 255, 215, 0 //gold color

for j := 0; j < len(output); j++ {
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, output[j])
}
}

效果图:
gold text

实现彩虹输出

接下来我们在金色的基础上,通过调整 RGB 的不同值,去实现彩虹输出,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package main

import (
"fmt"
"math"
"strings"

"syreclabs.com/go/faker"
)

func rgb(i int) (int, int, int) {
var f = 0.1
return int(math.Sin(f*float64(i)+0)*127 + 128),
int(math.Sin(f*float64(i)+2*math.Pi/3)*127 + 128),
int(math.Sin(f*float64(i)+4*math.Pi/3)*127 + 128)
}

func main() {
var phrases []string

for i := 1; i < 3; i++ {
phrases = append(phrases, faker.Hacker().Phrases()...)
}

output := strings.Join(phrases[:], "; ")

for j := 0; j < len(output); j++ {
r, g, b := rgb(j)
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, output[j])
}
fmt.Println()
}

效果图如下:
rainbow

读取其他程序的输出

在前面的基础上,我们让这个程序不再提供自己的输出,而是作为其他程序的管道,它将读取内容 os.Stdin 并将其彩虹化,使其真正成为一个可用的命令行工具。
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main

import (
"bufio"
"fmt"
"io"
"math"
"os"
)

func main() {
info, _ := os.Stdin.Stat()
var output []rune

if info.Mode()&os.ModeCharDevice != 0 {
fmt.Println("The command is intended to work with pipes.")
fmt.Println("Usage: fortune | gorainbow")
}

reader := bufio.NewReader(os.Stdin)
for {
input, _, err := reader.ReadRune()
if err != nil && err == io.EOF {
break
}
output = append(output, input)
}

print(output)
}

func rgb(i int) (int, int, int) {
var f = 0.1
return int(math.Sin(f*float64(i)+0)*127 + 128),
int(math.Sin(f*float64(i)+2*math.Pi/3)*127 + 128),
int(math.Sin(f*float64(i)+4*math.Pi/3)*127 + 128)
}

func print(output []rune) {
for j := 0; j < len(output); j++ {
r, g, b := rgb(j)
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, output[j])
}
fmt.Println()
}

效果图如下:
rainbow

作为命令行工具使用

对项目进行编译后就可以作为一个命令行工具正常使用啦,示例如下:
build