我正在开发一个用 Go 编写的 CLI 工具,最近使用了 Cobra 工具,我有一个用例,我需要其中一个命令的嵌套提示。我使用 Promptui 作为提示,但找不到直接的方法来执行此操作。这篇短文将展示如何使用promptui 创建嵌套提示。完整的代码可以在这里找到。
我们首先需要创建一个空的 Go 项目。我们将其称为嵌套提示:
$ mkdir nested-prompt && cd nested-prompt $ go mod init github.com/Thwani47/nested-prompt
然后我们将安装 cobra、cobra-cli 和promptui 软件包:
$ go get -u github.com/spf13/cobra@latest $ go install github.com/spf13/cobra-cli@latest $ go get -u github.com/manifoldco/promptui
我们可以使用 cobra-cli 初始化一个新的 CLI 应用程序并向我们的 CLI 添加命令
$ cobra-cli init # initializes a new CLI application $ cobra-cli add config # adds a new command to the CLI named 'config'
我们可以清理cmd/config.go文件并删除所有注释。应该是这样的:
// cmd/config.go package cmd import ( "fmt" "github.com/spf13/cobra" ) var configCmd = &cobra.Command{ Use: "config", Short: "Configure settings for the application", Long: `Configure settings for the application`, Run: func(cmd *cobra.Command, args []string) { fmt.Println("config called") }, } func init() { rootCmd.AddCommand(configCmd) }
我们首先需要为我们的提示创建一个自定义类型。我们通过定义一个提示项目结构来做到这一点,如下
type PromptType int const ( TextPrompt PromptType = 0 PasswordPrompt PromptType = 1 SelectPrompt PromptType = 2 ) type promptItem struct { ID string Label string Value string SelectOptions []string promptType PromptType }
PromptType 枚举允许我们从提示中收集不同类型的输入,我们可以提示用户输入文本或敏感值(例如密码或 API 密钥),或者提示用户从定义值列表中进行选择
然后我们定义一个promptInput函数来提示用户输入。该函数返回用户输入的字符串值,如果提示失败则返回错误。
func promptInput(item promptItem) (string, error) { prompt := promptui.Prompt{ Label: item.Label, HideEntered: true, } if item.promptType == PasswordPrompt { prompt.Mask = '*' } res, err := prompt.Run() if err != nil { fmt.Printf("Prompt failed %v\n", err) return "", err } return res, nil }
然后我们定义一个 PromptSelect 函数,该函数将允许用户从选项列表中进行选择。函数返回用户选择的字符串值,如果提示失败则返回错误。
func promptSelect(item selectItem) (string, error) { prompt := promptui.Select{ Label: item.Label, Items: item.SelectValues, HideSelected: true, } _, result, err := prompt.Run() if err != nil { fmt.Printf("Prompt failed %v\n", err) return "", err } return result, nil }
为了模拟嵌套提示,我们将创建一个 PromptNested 函数,该函数将允许我们提示用户输入值,并且提示将保持活动状态,直到用户选择“完成”。该函数返回一个布尔值,表示提示成功。
函数中的注释解释了每个主要代码块的职责
func promptNested(promptLabel string, startingIndex int, items []*promptItem) bool { // Add a "Done" option to the prompt if it does not exist doneID := "Done" if len(items) > 0 && items[0].ID != doneID { items = append([]*promptItem{{ID: doneID, Label: "Done"}}, items...) } templates := &promptui.SelectTemplates{ Label: "{{ . }}?", Active: "\U0001F336 {{ .Label | cyan }}", Inactive: "{{ .Label | cyan }}", Selected: "\U0001F336 {{ .Label | red | cyan }}", } prompt := promptui.Select{ Label: promptLabel, Items: items, Templates: templates, Size: 3, HideSelected: true, CursorPos: startingIndex, // Set the cursor to the last selected item } idx, _, err := prompt.Run() if err != nil { fmt.Printf("Error occurred when running prompt: %v\n", err) return false } selectedItem := items[idx] // if the user selects "Done", return true and exit from the function if selectedItem.ID == doneID { return true } var promptResponse string // if the prompt type is Text or Password, prompt the user for input if selectedItem.promptType == TextPrompt || selectedItem.promptType == PasswordPrompt { promptResponse, err = promptInput(*selectedItem) if err != nil { fmt.Printf("Error occurred when running prompt: %v\n", err) return false } items[idx].Value = promptResponse } // if the prompt type is Select, prompt the user to select from a list of options if selectedItem.promptType == SelectPrompt { promptResponse, err = promptSelect(*selectedItem) if err != nil { fmt.Printf("Error occurred when running prompt: %v\n", err) return false } items[idx].Value = promptResponse } if err != nil { fmt.Printf("Error occurred when running prompt: %v\n", err) return false } // recursively call the promptNested function to allow the user to select another option return promptNested(idx, items) }
现在我们已经有了我们需要的所有方法,我们需要测试它们。在configCmd命令的Run函数中,我们将创建一个promptItem列表并调用promptNested函数来提示用户输入。 Run 函数应如下所示:
// create a list of prompt items items := []*promptItem{ { ID: "APIKey", Label: "API Key", promptType: PasswordPrompt, }, { ID: "Theme", Label: "Theme", promptType: SelectPrompt, SelectOptions: []string{"Dark", "Light"}, }, { ID: "Language", Label: "Preferred Language", promptType: SelectPrompt, SelectOptions: []string{"English", "Spanish", "French", "German", "Chinese", "Japanese"}, }, } // set the starting index to 0 to start at the first item in the list promptNested("Configuration Items", 0, items) for _, v := range items { fmt.Printf("Saving configuration (%s) with value (%s)...\n", v.ID, v.Value) }
按如下方式构建并测试应用程序
$ go build . $ ./nested-prompt config
结果如下
以上是使用promptui 在 Go 中嵌套提示的详细内容。更多信息请关注PHP中文网其他相关文章!