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

まとめ

  • ラインエディタに必要な物は大体揃っている
    • 入力中の左右移動
    • 履歴
    • 補完
  • 日本語入力はちょっとおかしい
    • 日本語を入れて左右移動すると表示がおかしい
    • ターミナルの問題の可能性も