喜歡命令行應用程序嗎?也不要錯過 cowsay 教程!
我正在尋找一些終端應用程序來尋找靈感,結果我偶然發現了 lolcat。
原始碼在 https://github.com/busyloop/lolcat,並且已經有了一些Go的實現:
- https://github.com/cezarsa/glolcat
- https://github.com/latotty/lolcat
- https://github.com/lalyos/lolcat
- https://github.com/vbatts/gogololcat
看起來是一個完全沒有用的東西,所以讓我們來實現它!
首先,讓我們在屏幕上打印一些值,然後我們將為它們上色,然後我們將研究如何接受用戶輸入以作為管道工作。
我使用 https://github.com/enodata/faker 生成假的輸出。
go get -u github.com/enodata/faker
該程序輸出了一些短語:
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[:], "; "))
}
不幸的是,這都是無聊的黑白。讓我們添加一些顏色。我們可以通過在 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 // 金色
for j := 0; j < len(output); j++ {
fmt.Printf("\033[38;2;%d;%d;%dm%c\033[0m", r, g, b, output[j])
}
}
現在我們有了一個字符串,以及讓每個字符以不同的方式上色的基礎,現在是時候加入彩虹了。
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()
}
這就是我們想要的效果!
彩虹顏色是使用 rgb()
函數生成的,原始的Ruby代碼在 https://github.com/busyloop/lolcat/blob/master/lib/lolcat/lol.rb 中實現了這個功能。
現在讓我們編輯程序,不再提供自己的輸出,改為讓它作為管道的一部分工作。它將從 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("該命令旨在與管道一起使用。")
fmt.Println("用法: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)
}
它從 os.Stdin
逐個字符地讀取並將它們添加到 output
這個字符切片中。
將輸出的渲染操作提取到 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("該命令旨在與管道一起使用。")
fmt.Println("用法: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++
}
}
這與之前的版本相同。
現在,我們可以用 fortune 和 cowsay 玩耍了。
讓我們通過運行 go build
和 go install
將其變成全局命令。命令將被稱為 gololcat
,因為我們使用這個文件夾名稱。