dougan1205 2017-01-27 13:36
浏览 47

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

I am looking into writing a CLI application in Go.

One of the requirements is auto complete. Not of the command itself but of possible options.

Imagine I want to add a new entry using the CLI. Each entry can have a category. The categories are available in a slice. What I want to do now is to enable the user to tab through the available categories when typing in add.

I am aware of libraries like https://github.com/chzyer/readline and https://github.com/spf13/cobra but could not find if or how they support this.

  • 写回答

1条回答 默认 最新

  • dongtao9887 2017-01-27 17:50
    关注

    Thank you @ain and @JimB for pointing me in the right direction.

    Based on the example provided at https://github.com/chzyer/readline/tree/master/example/readline-demo I was able to achieve the desired functionality.

    The following code has to main commands newEntry and newCategory. If the user types newEntry and than presses TAB he can choose from the available categories. The newCategory command allow to add a new custom category which is immediately available the next time newEntry is executed.

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

报告相同问题?

悬赏问题

  • ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
  • ¥20 怎么用dlib库的算法识别小麦病虫害
  • ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
  • ¥15 java写代码遇到问题,求帮助
  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?