golangのラインエディタはlinerが便利
peterh/liner
golangでCLIを作る際に活用できるラインエディタです。
使い方
liner.NewLinerで作成し、Prompt関数で入力を待機します。
入力があると関数が入力を返してくるため、それによって処理を分岐します。
なお、Ctrl+cの場合は普通に入力になりますが、Ctrl+dの場合はEOFとしてエラーを返してくるため、
エラー時に終了するようにしておくことでCtrl+dで終了できます。
package main
import (
"fmt"
"github.com/peterh/liner"
)
func main() {
line := liner.NewLiner()
defer line.Close()
for {
l, err := line.Prompt("Input: ")
if err != nil {
fmt.Println("error: ", err)
} else {
fmt.Println("get: ", l)
if l == "exit" {
break
}
}
}
}
入力履歴を使う
AppendHistory関数に文字列を渡すことで、上下キーで入力履歴をたどれます。
State.AppendHistory
また、WriteHistory関数でファイルへの書き込みを、ReadHistory関数でファイルからの読み込みを行えます。
package main
import (
"fmt"
"github.com/peterh/liner"
"os"
)
func main() {
line := liner.NewLiner()
defer line.Close()
f, err := os.Open("inputs.log")
if err == nil {
n, _ := line.ReadHistory(f)
fmt.Println("load", n, "history")
f.Close()
}
for {
l, err := line.Prompt("Input: ")
if err != nil {
fmt.Println("error: ", err)
} else {
fmt.Println("get: ", l)
line.AppendHistory(l)
if l == "exit" {
break
}
}
}
f, err = os.Create("inputs.log")
if err == nil {
fmt.Println("write history")
line.WriteHistory(f)
f.Close()
} else {
fmt.Println("write history error: ", err)
}
}
タブ補完を使う
SetCompleter関数に補完用の関数を登録することで、タブ補完も使えます。
State.SetCompleter
引数として、現在入力中のstringを受け取り、tab候補をstringの配列で返す関数を渡します。
入力中の文字が配列のはじめの要素で置き換えられ、以降tabを押すごとに次の要素と置き換えられます。
package main
import (
"fmt"
"github.com/peterh/liner"
"strings"
)
func main() {
inputs := make([]string, 0)
line := liner.NewLiner()
defer line.Close()
line.SetCompleter(func(line string) (c []string) {
for _, n := range inputs {
if strings.HasPrefix(n, strings.ToLower(line)) {
c = append(c, n)
}
}
return
})
for {
l, err := line.Prompt("Input: ")
if err != nil {
fmt.Println("error: ", err)
} else {
fmt.Println("get: ", l)
inputs = append(inputs, l)
if l == "exit" {
break
}
}
}
}
まとめ
- ラインエディタに必要な物は大体揃っている
- 入力中の左右移動
- 履歴
- 補完
- 日本語入力はちょっとおかしい
- 日本語を入れて左右移動すると表示がおかしい
- ターミナルの問題の可能性も