Go interesting projects有趣的项目(lolcat命令)

166 阅读2分钟

介绍

本文将用Go实现lolcat命令。

lolcat命令起源于GitHub仓库lolcat,指在一幅家猫的照片上加上了字幕的图片。图中的字幕通常会以特异的方式串出,或是以不符合文法和幽默的方式书写。

仓库的介绍更简洁,一副lolcat的图片以及命令使用截图:

image.png

image.png

这个看似无聊的命令究竟是怎么使用的呢?看一个具体的例子,在Ubuntu命令行中输入:

echo I love cat

输出如下:

image.png

lolcat命令以管道的形式接受参数,即:

echo I love cat | lolcat

会将改变字体颜色,就如图仓库中那张猫咪图片一样。

image.png

当输入fortune | cowsay | lolcat时就会出现:

image.png

注:前两个命令都需要用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[:], "; "))
}

image.png

当然,这种默认的白色肯定不是我们的预期,因此需要通过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])
}

image.png

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)
}

为每个字符随机初始化颜色后,输出看起来就更像彩虹:

image.png

Step 3:接收管道输出

接下来的工作是,让Go程序不直接打印字符,而是接收其他管道的输出作为输入。我们使用os.Stdin读取内容并将其彩虹化。

源码

本文的源码见Github仓库go-store中的gololcat