この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
とある調査にてインタラクティブにターミナルから入力や選択できるインストーラのようなものを作れるかを調べる機会がありました。 使用している言語がGolangであったため、Golangでライブラリがあるかを調べたところ、survey というライブラリがありました。
surveyのサイトを見れば何ができるかは分かりますが、自分のユースケースに合うかを検証するため、インストーラ風の入力のサンプルを作ってみました。今回はこのサンプルについて書いてみたいと思います。
作ったプログラムのターミナル入力
先にどのようなターミナル入力ができたかを書きたいと思います。何かのインストールやシステム設定する処理を想定し
- ユーザ名
- パスワード
- OSを選択
- インストールするオプションを複数選択
- 詳細コメントを入力するかを yes/no で選択
- (yesを選択時)複数行の詳細コメントを入力
- インストールするかを yes/no で確認
の入力や選択を行うサンプルとなります。ターミナル上での入力は以下のようになります(分かりやすいように一部改行を入れるなど加工をしております)。
? Please input user name. testname
? Please type your system password.: *****
? Please select install OS.: [Use arrows to move, type to filter]
Windows
Linux
> Mac
? Please select install options: [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
[x] data backup
[ ] log backup
> [x] alert email
? Input detail?: (y/N) y
? Please input detail comment. [Enter 2 empty lines to finish]this is a sample.
something.
? Would you like to insatll now?: (y/N) y
インストールやシステム設定でよくありそうな入力や選択、yes/no での処理の分岐は実現できそうでした。
作ったサンプルプログラム
上記のターミナル入力を行なった、今回作成したサンプルプログラムは以下となります。
package main
import (
"fmt"
"github.com/AlecAivazis/survey/v2"
)
var questions = []*survey.Question{
{
Name: "userName",
Prompt: &survey.Input{Message: "Please input user name."},
Validate: survey.Required,
},
{
Name: "password",
Prompt: &survey.Password{
Message: "Please type your system password.:",
},
Validate: survey.Required,
},
{
Name: "os",
Prompt: &survey.Select{
Message: "Please select install OS.:",
Options: []string{"Windows", "Linux", "Mac"},
Default: "Mac",
},
Validate: survey.Required,
},
{
Name: "options",
Prompt: &survey.MultiSelect{
Message: "Please select install options:",
Options: []string{"data backup", "log backup", "alert email"},
},
},
{
Name: "inputDetail",
Prompt: &survey.Confirm{
Message: "Input detail?:",
},
Validate: survey.Required,
},
}
var answers struct {
UserName string `survey:"userName"`
Passowrd string `survey:"password"`
OS string `survey:"os"`
Options []string `survey:"options"`
InputDetail bool `survey:"inputDetail"`
}
func main() {
err := survey.Ask(questions, &answers)
if err != nil {
panic(err)
}
var detail string
if answers.InputDetail {
prompt := &survey.Multiline{
Message: "Please input detail comment.",
}
survey.AskOne(prompt, &detail)
}
var install bool
prompt := &survey.Confirm{
Message: "Would you like to insatll now?:",
}
survey.AskOne(prompt, &install)
if !install {
fmt.Println("not install. finish.")
return
}
fmt.Println("install start ...")
fmt.Println(answers.UserName, answers.OS, answers.Options)
fmt.Printf("detail comment:\n%s\n", detail)
}
動かすには、Golangの実行環境と、「$ go get github.com/AlecAivazis/survey/v2」でのインストールを行う必要があります。
ユーザー名の入力〜詳細を入力するかのyes/no の選択までの連続した質問は、「questions」に格納して一括で出力しています(56行目)。
詳細を入力するかでyesを選択した場合の入力やインストールをするかの確認については、独立して出力し(66行目、73行目)、入力値によって処理を分岐させています。
まとめ
このような感じで、インストーラ風のターミナル入力を実現できることが分かりました。何かの役に立てば幸いです。