Go 为CLI应用程序实现自动完成
我正在考虑在Go中编写CLI应用程序 其中一个要求是自动完成。不是命令本身,而是可能的选项 假设我想使用CLI添加一个新条目。每个条目都可以有一个类别。 这些类别在一个切片中可用。我现在要做的是,当输入Go 为CLI应用程序实现自动完成,go,command-line-interface,Go,Command Line Interface,我正在考虑在Go中编写CLI应用程序 其中一个要求是自动完成。不是命令本身,而是可能的选项 假设我想使用CLI添加一个新条目。每个条目都可以有一个类别。 这些类别在一个切片中可用。我现在要做的是,当输入add时,使用户能够在可用类别之间进行制表 我知道像和这样的库,但找不到它们是否或如何支持这一点。谢谢@ain和@JimB为我指明了正确的方向 基于在上提供的示例,我能够实现所需的功能 以下代码必须包含主命令newEntry和newCategory。如果用户键入newEntry,然后按TAB键,则
add
时,使用户能够在可用类别之间进行制表
我知道像和这样的库,但找不到它们是否或如何支持这一点。谢谢@ain和@JimB为我指明了正确的方向 基于在上提供的示例,我能够实现所需的功能 以下代码必须包含主命令
newEntry
和newCategory
。如果用户键入newEntry
,然后按TAB键,则可以从可用类别中进行选择。newCategory
命令允许添加新的自定义类别,该类别在下次执行newEntry
时立即可用
package main
import (
"io"
"log"
"strconv"
"strings"
"github.com/chzyer/readline"
)
// completer defines which commands the user can use
var completer = readline.NewPrefixCompleter()
// categories holding the initial default categories. The user can add categories.
var categories = []string{"Category A", "Category B", "Category C"}
var l *readline.Instance
func main() {
// Initialize config
config := readline.Config{
Prompt: "\033[31m»\033[0m ",
HistoryFile: "/tmp/readline.tmp",
AutoComplete: completer,
InterruptPrompt: "^C",
EOFPrompt: "exit",
HistorySearchFold: true,
}
var err error
// Create instance
l, err = readline.NewEx(&config)
if err != nil {
panic(err)
}
defer l.Close()
// Initial initialization of the completer
updateCompleter(categories)
log.SetOutput(l.Stderr())
// This loop watches for user input and process it
for {
line, err := l.Readline()
if err == readline.ErrInterrupt {
if len(line) == 0 {
break
} else {
continue
}
} else if err == io.EOF {
break
}
line = strings.TrimSpace(line)
// Checking which command the user typed
switch {
// Add new category
case strings.HasPrefix(line, "newCategory"):
// Remove the "newCategory " prefix (including space)
if len(line) <= 12 {
log.Println("newCategory <NameOfCategory>")
break
}
// Append everything that comes behind the command as the name of the new category
categories = append(categories, line[12:])
// Update the completer to make the new category available in the cmd
updateCompleter(categories)
// Program is closed when user types "exit"
case line == "exit":
goto exit
// Log all commands we don't know
default:
log.Println("Unknown command:", strconv.Quote(line))
}
}
exit:
}
// updateCompleter is updates the completer allowing to add new command during runtime. The completer is recreated
// and the configuration of the instance update.
func updateCompleter(categories []string) {
var items []readline.PrefixCompleterInterface
for _, category := range categories {
items = append(items, readline.PcItem(category))
}
completer = readline.NewPrefixCompleter(
readline.PcItem("newEntry",
items...,
),
readline.PcItem("newCategory"),
)
l.Config.AutoComplete = completer
}
主程序包
进口(
“io”
“日志”
“strconv”
“字符串”
“github.com/chzyer/readline”
)
//完成符定义用户可以使用的命令
var completer=readline.NewPrefixCompleter()
//保留初始默认类别的类别。用户可以添加类别。
var categories=[]字符串{“类别A”、“类别B”、“类别C”}
var l*readline.Instance
func main(){
//初始化配置
config:=readline.config{
提示:“\033[31m»\033[0m”,
历史文件:“/tmp/readline.tmp”,
自动完成:完成器,
中断提示:“^C”,
EOFPrompt:“退出”,
历史研究:没错,
}
变量错误
//创建实例
l、 err=readline.NewEx(&config)
如果错误!=零{
恐慌(错误)
}
延迟l.关闭()
//完成程序的初始初始化
更新完成器(类别)
log.SetOutput(l.Stderr())
//此循环监视用户输入并对其进行处理
为了{
行,错误:=l.Readline()
如果err==readline.ErrInterrupt{
如果len(line)==0{
打破
}否则{
持续
}
}如果err==io.EOF,则为else{
打破
}
行=字符串。修剪空间(行)
//检查用户键入的命令
开关{
//添加新类别
case strings.HasPrefix(第行,“newCategory”):
//删除“newCategory”前缀(包括空格)
如果len(line)你所说的“CLI”是什么意思?即用户会启动你的程序,然后在“intercive shell”中工作吗还是用户在系统外壳中输入完整的命令,然后你的程序执行该操作并退出?@这是一个好问题。我没有考虑过这一点。这与用例无关。因此:最好实现什么。你提到的两个示例非常不同,一个是readline实现,另一个使用autocompletion bash的功能(它使用不同的readline实现)。@JimB您能进一步解释readline的含义吗?它是否读取实际的行(在CLI上键入的内容的意义上),或者我能提供它应该执行的值吗?readline是交互式CLI使用的标准库: