Go 为CLI应用程序实现自动完成

Go 为CLI应用程序实现自动完成,go,command-line-interface,Go,Command Line Interface,我正在考虑在Go中编写CLI应用程序 其中一个要求是自动完成。不是命令本身,而是可能的选项 假设我想使用CLI添加一个新条目。每个条目都可以有一个类别。 这些类别在一个切片中可用。我现在要做的是,当输入add时,使用户能够在可用类别之间进行制表 我知道像和这样的库,但找不到它们是否或如何支持这一点。谢谢@ain和@JimB为我指明了正确的方向 基于在上提供的示例,我能够实现所需的功能 以下代码必须包含主命令newEntry和newCategory。如果用户键入newEntry,然后按TAB键,则

我正在考虑在Go中编写CLI应用程序

其中一个要求是自动完成。不是命令本身,而是可能的选项

假设我想使用CLI添加一个新条目。每个条目都可以有一个类别。 这些类别在一个切片中可用。我现在要做的是,当输入
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使用的标准库: