介绍
本文将用Go实现lolcat命令。
lolcat命令起源于GitHub仓库lolcat,指在一幅家猫的照片上加上了字幕的图片。图中的字幕通常会以特异的方式串出,或是以不符合文法和幽默的方式书写。
仓库的介绍更简洁,一副lolcat的图片以及命令使用截图:
这个看似无聊的命令究竟是怎么使用的呢?看一个具体的例子,在Ubuntu命令行中输入:
echo I love cat
输出如下:
lolcat命令以管道的形式接受参数,即:
echo I love cat | lolcat
会将改变字体颜色,就如图仓库中那张猫咪图片一样。
当输入fortune | cowsay | lolcat
时就会出现:
注:前两个命令都需要用apt去安装
实现
了解完命令的作用后,我们就可以开始去实现这个命令了。首先在屏幕上打印一些值,然后为它们着色,然后再研究接受用户输入以作为管道工作。
Step 1:输出,染色
下面是一个简单的Go程序,编译运行后会在命令行中输出三句话。
package main
import (
"fmt"
"strings"
)
var (
phrase1 = "Day of inquiry. You will be subpoenaed."
phrase2 = "Your business will assume vast proportions."
phrase3 = "Reply hazy, ask again later."
)
func main() {
var phrases []string
phrases = append(phrases, phrase1)
phrases = append(phrases, phrase2)
phrases = append(phrases, phrase3)
fmt.Println(strings.Join(phrases[:], "; "))
}
当然,这种默认的白色肯定不是我们的预期,因此需要通过fmt.Printf方法添加转义字符来为输出字符换一个颜色,修改之前的打印逻辑:
output := strings.Join(phrases[:], "; ")
r, g, b := 188, 166, 32
for i := 0; i < len(output); i++ {
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, output[i])
}
Step 2:渐变颜色
接下来,尝试为每个字符染上不同的颜色,让输出看起来有彩虹的样子。在上面的代码中,rgb的值初始化后不在改变,如果想要每个字符颜色不同,则需要对每个字符随机初始化颜色,我们定义一个rgb初始化方法。
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)
}
为每个字符随机初始化颜色后,输出看起来就更像彩虹:
Step 3:接收管道输出
接下来的工作是,让Go程序不直接打印字符,而是接收其他管道的输出作为输入。我们使用os.Stdin读取内容并将其彩虹化。