概要
Vim を起動する際に以下のように標準入力をファイルにすると警告が出ます。
$ vim < test.txt
Vim: Warning: Input is not from a terminal
...
...
テキストエディタやコマンドラインツールを作っていると標準入力がファイルかターミナルか知りたい場合があります。
今回はGoにおいてそれをどうやって実現するか書きます。
実践
まずは完成形から。
コードの仕様は以下の通りです。
- 標準入力がターミナルの場合、固定文と引数を出力する。
- 標準入力がファイルの場合、固定文とファイルの中身を出力する。
例)
$ go run main.go hoge fuga
from terminal
[hoge fuga]
$ go run main.go < test.txt
from not terminal
111
222
333
package main
import (
"fmt"
"io/ioutil"
"os"
"syscall"
"golang.org/x/crypto/ssh/terminal"
)
func main() {
if terminal.IsTerminal(syscall.Stdin) {
fmt.Println("from terminal")
fmt.Println(os.Args[1:])
} else {
fmt.Println("from not terminal")
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
fmt.Println(err)
os.Exit(0)
}
fmt.Println(string(b))
}
}
今回、標準入力がターミナルかどうかを判定する肝となるのはterminal.IsTerminal(syscall.Stdin)
の部分です(GoDoc)。
引数に対象となるファイルディスクリプタの番号をしていることによりファイルディスクリプタがターミナルかどうか判定してくれます。
標準入力のファイルディスクリプタの数値は固定で0なのでそれを指定します。
終わりに
過去に以下のような記事も投稿しています。一つ一つは簡単なことですが、これらの要素を組み合わせることにより自らの望むツールの実現に繋がるのでごましお程度に覚えといてください。
Goでエスケープシーケンスを扱う(文字色、カーソル移動)
Goでターミナルのサイズに合わせて枠を表示し続ける