前書き
busyloop/lolcat: Rainbows and unicorns!
に惚れ惚れしながら色々カラフルにしていたのですが、Rubyをインストールするのにちと時間がかかる。
また、短い文字列に色合いを固定してカラフルにするのは少し面倒。
chalk/chalk: 🖍 Terminal string styling done right
にもグラデーションできそうなものがあるが、モジュール式でちょいと面倒そう。
ということでバイナリだけで似たことができるものはないかなと調べたら、
Code-Hex/Neo-cowsay: 🐮 cowsay written in Go
がなかなか良さそうだった。
ただし牛は余計なので、コードを盗みつつ牛をドナドナするように頑張ってみた。
toiletはよくわからなかった。
スクリーンショット
パイプとファイル指定が出来れば個人的によし。
ついでに引数渡しも。
完成品
khsk/golor: Rainbows as lolcat
zip落として解凍すれば使えるのは嬉しい。
go get -u github.com/khsk/golor
でも取れる…はず…。
肝心なところはここぐらい
func rainbow(text string, c *cli.Context) string {
const (
red = iota + 31
green
yellow
blue
magenta
cyan
)
rainbow := []int{magenta, red, yellow, green, cyan, blue}
buf := make([]rune, 0, len(text))
var line int
attribute := getVisualDistinction(c)
i := 0
for _, char := range text {
if char == '\n' {
if c.Int("deviation") != 0 {
line++
i = line * c.Int("deviation")
} else {
i = 0
}
buf = append(buf, char)
continue
}
buf = append(buf, []rune(fmt.Sprintf("\x1b[%d%sm%c\x1b[0m", rainbow[i%6], attribute, char))...)
i++
}
return string(buf)
}
func aurora(text string, c *cli.Context) string {
buf := make([]rune, 0, len(text))
attribute := getVisualDistinction(c)
if c.Int64("seed") == 0 {
rand.Seed(time.Now().UnixNano())
} else {
rand.Seed(c.Int64("seed"))
}
i := rand.Intn(256)
freq := c.Float64("freq")
spread := c.Float64("spread")
for _, char := range text {
if char == '\n' {
buf = append(buf, char)
continue
}
buf = append(buf, []rune(fmt.Sprintf("\033[38;5;%d%sm%c\033[0m", rgb(float64(i)/spread, freq), attribute, char))...)
i++
}
return string(buf)
}
func rgb(i float64, freq float64) int {
red := int(6*((math.Sin(freq*i+0)*127+128)/256)) * 36
green := int(6*((math.Sin(freq*i+2*math.Pi/3)*127+128)/256)) * 6
blue := int(6*((math.Sin(freq*i+4*math.Pi/3)*127+128)/256)) * 1
return 16 + red + green + blue
}
(コピペミックスなので式の意味するところがあまりわかっていない)
Goのいいところ
簡単
並列1処理使っていないのでなぜGoと言われそうですが、単純に書きやすい。
A Tour of Go
は最初のHello Worldで面倒になってやめたんですが、
見よう見まねと
golang チートシート - Qiita
などを見てなんとかかんとか動くレベルまで行くのは良かった。
go コマンド
便利
go run
はまあ普通として、
go fmt
のおかげで2スペースインデントとか自由にガシガシ書けた。
特にgo get
がよくて、簡単にgithubなどから引っ張ってこれる。
これがパッケージ管理のnpmなど別コマンドじゃなくてgo
でできるのが良かったと思った。
…しかしpackage.jsonらしきものはできないので依存パッケージはgo get
では管理不可?
開発者じゃなくて利用者として便利?なのかな?
追記:
Go & Versioning(vgo)を読んで大きな変更が入ったなと思った - Qiita
でバージョン管理できそう。
ただし、vgo
とコマンド名が変わっちゃうのはちょっと残念?npm
みたいな感じに落ち着くのだろうか。
リリース環境整っている
作ったは良いけれど、環境毎のビルドが標準方法ではかなり不便そうだった。
いちいち環境変数設定するなんてうへーとなったけど、良いものがあった。
mitchellh/gox: A dead simple, no frills Go cross compile tool
golangでクロスコンパイルするならgoxライブラリを使うと便利! - エンジニアはこわくない
自動で全部作ってくれるすごいやつだよ。
…いやいやでもでもGithubのリリース作るの面倒だしな…と凄い不精じみていると、
tcnksm/ghr: Upload multiple artifacts to GitHub Release in parallel
高速に自作パッケージをGithubにリリースするghrというツールをつくった | SOTA
自動でリリースしてアップロードもしてくれるすごいやつだよ。
…いやいやいやいやでもでもでも2つのツール使うなんて面倒だしー!zip化も手動でしなきゃいけないしなー!
gox して ghr するツール ggallin 作った - Qiita
すごい
どんなに面倒くさがりでもこれならリリースできると思います。
できました。
ありがとうございます。
CLIもテンプレがある
これもGoならではではないですが、
urfave/cli: A simple, fast, and fun package for building command line apps in Go
で簡単にCLIが作れるのが良い。
面倒なヘルプも自動で作ってくれる。楽。
Goは面倒くさがりの利用者に優しく、
Goは面倒くさがりの開発者に優しい、
言語・環境なのかなと感じました。
Goのわるいところ(別方法あるのかも)
しっかり触っていないのでなんともですが…
String型から一文字取り出すとRuneになってしまって、Stringを受け付ける処理に(キャストしても)渡せないことが困りました。
最初は一文字ずつ切り取って
GoでANSIエスケープコードを扱うライブラリを作った(色付け・カーソル移動等) - Qiita
を使い色付けしようと考えていたのですが、それで断念。
手動でコードをつけていく方式(それでもコピペ)になりました。
Qiitaのタグ
Go言語の悪いところではないのですが
Goとgolangの2つのタグがある…
Goが良さそうですが、2つともつけている記事が多そうです。
参考
-
urfave/cli: A simple, fast, and fun package for building command line apps in Go
-
Goでコマンドラインツールを簡単に作成する方法 - Qiita
コマンドのヘルプはgreet [command] help
としないと表示されないので、greet help
で全部出てほしかったり。 -
urfave/cli(旧github.com/codegangsta/cli)でのヘルプ表示で追加テンプレートパラメータを使う - Qiita
-
mitchellh/gox: A dead simple, no frills Go cross compile tool
バイナリファイル名は恐らくディレクトリ名が使われるので注意。
ggallinは設定したバージョンのプレフィックスとしてv
が付くので、バージョンにv
を含めるとvv1.0.0
となっちゃう。
課題
- lolcatのようにヘルプに色付け
カスタマイズしようにもそのまま出力してるっぽいので標準出力をバッファしないといけない? - ライブラリ化
他のコード書くときの出力にも使えたら便利そう - もっと楽しいカラフルさの表現
オマケ
function fish_prompt
#set_color $fish_color_cwd
#echo -n (prompt_pwd)
#set_color normal
echo -n (prompt_pwd) | golor
echo -n ' > '
end
余談
Neo Cowsayという偉大なお手本があったのでGoにしましたが、Nimもなかなか良さそうでした。
-
並行? ↩