lolcat
Like CLI apps? Don’t miss the cowsay tutorial as well!
喜欢CLI应用程序吗? 也不要错过Cowsay教程!
I was looking for some terminal applications for inspiration and I stumbled on lolcat.
我一直在寻找一些终端应用程序来寻求灵感,但偶然发现了lolcat 。
The original is https://github.com/busyloop/lolcat and there are quite a few Go implementations already:
原始版本是https://github.com/busyloop/lolcat,并且已经有很多Go实现:
Looks like a completely useless thing to build, so let’s do it!
看起来好像是一件完全没用的东西 ,让我们开始吧!
Let’s start by printing some values on the screen, then we’ll move to coloring them, and then we’ll look into accepting user input to work as a pipe.
让我们从在屏幕上打印一些值开始,然后为它们着色,然后研究接受用户输入以充当管道。
I use https://github.com/enodata/faker to generate fake output.
我使用https://github.com/enodata/faker生成假输出。
go get -u github.com/enodata/faker
This program outputs a number of phrases:
该程序输出许多短语:
package main
import (
"fmt"
"strings"
"github.com/enodata/faker"
)
func main() {
var phrases []string
for i := 1; i < 3; i++ {
phrases = append(phrases, faker.Hacker().Phrases()...)
}
fmt.Println(strings.Join(phrases[:], "; "))
}
Unfortunately, this is all boring B/W. Let’s add some color. We can do this by prepending an escape character sequence in fmt.Printf
. This prints all the strings in the gold color #FFD700, whose RGB color code is (255,215,0):
不幸的是,这真是无聊的黑白。 让我们添加一些颜色。 我们可以通过在fmt.Printf
添加一个转义字符序列来做到这fmt.Printf
。 这将以金色#FFD700打印所有字符串,其RGB颜色代码为(255,215,0):
package main
import (
"fmt"
"strings"
"github.com/enodata/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])
}
}
Now that we have a string, and the groundwork for making each character colored in a different way, it’s time to introduce the rainbow.
既然我们有了一个字符串,并且使每个字符以不同的方式着色的基础工作,该介绍彩虹了。
package main
import (
"fmt"
"math"
"strings"
"github.com/enodata/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()
}
That’s style!
那是风格!
The rainbow color is generated using the rgb()
function, as implemented in the original Ruby source code in https://github.com/busyloop/lolcat/blob/master/lib/lolcat/lol.rb
彩虹色是使用rgb()
函数生成的,如在https://github.com/busyloop/lolcat/blob/master/lib/lolcat/lol.rb中的原始Ruby源代码中所实现的那样
Let’s now edit the program and instead of providing its own output, let it work as a pipe for other programs. It will read the content from os.Stdin
and rainbowize it.
现在让我们编辑程序,而不是提供自己的输出,而让它充当其他程序的管道 。 它将从os.Stdin
读取内容并将其彩虹化。
package main
import (
"bufio"
"fmt"
"io"
"math"
"os"
)
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()
}
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)
}
It reads one rune at a time from os.Stdin
and adds it to the output
slice of runes.
它一次从os.Stdin
读取一个符文,并将其添加到output
符文中。
The output rendering has been extracted to print(), but we could also pipe “just in time” each rune as it’s scanned:
输出渲染已提取到print()中,但是我们也可以在扫描每个符文时“及时”传递它:
package main
import (
"bufio"
"fmt"
"io"
"math"
"os"
)
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() {
info, _ := os.Stdin.Stat()
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)
j := 0
for {
input, _, err := reader.ReadRune()
if err != nil && err == io.EOF {
break
}
r, g, b := rgb(j)
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, input)
j++
}
}
This works same as before.
这和以前一样。
We can now entertain ourselves with fortune and cowsay
我们现在可以用财富和求知欲来娱乐自己
Let’s make this a system-wide command by running go build
and go install
. The command will be run as gololcat
, since we used that as the folder name.
通过运行go build
和go install
使它成为系统范围的命令。 该命令将以gololcat
运行,因为我们将其用作文件夹名称。
lolcat