发布于 2026-01-06 7 阅读
0

Go Survey prompter promptui 中的交互式 CLI 提示

Go 语言交互式 CLI 提示符

民意调查

提词器

promptui

潮汐迁移💓 CLI应用程序

你喜欢命令行应用吗?我们超爱!在 Tidal Migrations,我们使用功能齐全的图形界面集成开发环境 (GUI IDE) 和编辑器,例如 VS Code 和 Emacs,但也vim经常git在终端中运行命令行工具。我们每天都会使用bash各种命令行工具和应用,无论是工作还是娱乐。此外,我们也喜欢开发awk命令行应用。在这篇文章中,我们将向你展示如何为用 Go 编写的命令行应用实现不同的交互式提示。sed

将数据传递给 CLI 应用程序

很多时候,CLI 应用程序本身并不能独立运行,而是需要对信息或数据进行一些处理或操作。

向命令行应用程序传递数据的方式有很多种。使用标志、环境变量、文件名作为命令行参数,或者从标准输入读取数据都是很常见的做法,而且使用标准的 Go 库就能轻松实现。使用交互式提示符可以丰富你的命令行应用程序,并改善整体用户体验。

我们开始吧!

如何实现文本输入提示

基本的文本输入提示很容易实现。只需从标准输入读取直到遇到换行符\n):

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

// StringPrompt asks for a string value using the label
func StringPrompt(label string) string {
    var s string
    r := bufio.NewReader(os.Stdin)
    for {
        fmt.Fprint(os.Stderr, label+" ")
        s, _ = r.ReadString('\n')
        if s != "" {
            break
        }
    }
    return strings.TrimSpace(s)
}

func main() {
    name := StringPrompt("What is your name?")
    fmt.Printf("Hello, %s!\n", name)
}
Enter fullscreen mode Exit fullscreen mode

如何实现密码输入提示

密码提示与文本输入提示类似,区别在于用户输入的内容应该被隐藏:

package main

import (
    "fmt"
    "os"
    "syscall"

    "golang.org/x/term"
)

// PasswordPrompt asks for a string value using the label.
// The entered value will not be displayed on the screen
// while typing.
func PasswordPrompt(label string) string {
    var s string
    for {
        fmt.Fprint(os.Stderr, label+" ")
        b, _ := term.ReadPassword(int(syscall.Stdin))
        s = string(b)
        if s != "" {
            break
        }
    }
    fmt.Println()
    return s
}

func main() {
    password := PasswordPrompt("What is your password?")
    fmt.Printf("Oh, I see! Your password is %q\n", password)
}
Enter fullscreen mode Exit fullscreen mode

如何实现“是/否”提示

对于“是/否”提示,我们将创建一个无限循环,不断询问直到用户回答“是”或“否”为止:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strings"
)

// YesNoPrompt asks yes/no questions using the label.
func YesNoPrompt(label string, def bool) bool {
    choices := "Y/n"
    if !def {
        choices = "y/N"
    }

    r := bufio.NewReader(os.Stdin)
    var s string

    for {
        fmt.Fprintf(os.Stderr, "%s (%s) ", label, choices)
        s, _ = r.ReadString('\n')
        s = strings.TrimSpace(s)
        if s == "" {
            return def
        }
        s = strings.ToLower(s)
        if s == "y" || s == "yes" {
            return true
        }
        if s == "n" || s == "no" {
            return false
        }
    }
}

func main() {
    ok := YesNoPrompt("Dev.to is awesome!", true)
    if ok {
        fmt.Println("Agree!")
    } else {
        fmt.Println("Huh?")
    }
}
Enter fullscreen mode Exit fullscreen mode

如何实现交互式复选框

为了创建一个交互式多选提示框,我们将使用一个非常棒的survey软件包:

package main

import (
    "fmt"
    "strings"

    "github.com/AlecAivazis/survey/v2"
)

func Checkboxes(label string, opts []string) []string {
    res := []string{}
    prompt := &survey.MultiSelect{
        Message: label,
        Options: opts,
    }
    survey.AskOne(prompt, &res)

    return res
}

func main() {
    answers := Checkboxes(
        "Which are your favourite programming languages?",
        []string{
            "C",
            "Python",
            "Java",
            "C++",
            "C#",
            "Visual Basic",
            "JavaScript",
            "PHP",
            "Assembly Language",
            "SQL",
            "Groovy",
            "Classic Visual Basic",
            "Fortran",
            "R",
            "Ruby",
            "Swift",
            "MATLAB",
            "Go",
            "Prolog",
            "Perl",
        },
    )
    s := strings.Join(answers, ", ")
    fmt.Println("Oh, I see! You like", s)
}
Enter fullscreen mode Exit fullscreen mode

注意事项和变通方法

如果您将一些输入数据通过管道传递给交互式 CLI 应用程序,提示符将读取这些数据:

$ echo "Petr" | go run main.go
What is your name? Hello, Petr!
Enter fullscreen mode Exit fullscreen mode

有时这种行为是可以接受的,但有时则不行。要检查终端是否具有交互性,我们使用term.IsTerminal以下函数:

package main

import (
    "fmt"
    "syscall"

    "golang.org/x/term"
)

func main() {
    if term.IsTerminal(int(syscall.Stdin)) {
        fmt.Println("Terminal is interactive! You're good to use prompts!")
    } else {
        fmt.Println("Terminal is not interactive! Consider using flags or environment variables!")
    }
}
Enter fullscreen mode Exit fullscreen mode
$ echo "Hello" | go run main.go
Terminal is not interactive! Consider using flags or environment variables!

$ go run main.go
Terminal is interactive! You're good to use prompts!
Enter fullscreen mode Exit fullscreen mode

图书馆

如您所见,实现基本的交互式提示非常容易,但对于复杂的提示,最好使用社区提供的一些 Go 包:

GitHub 标志 AlecAivazis /调查

一个用于构建交互式和易于访问的提示符的 golang 库,完全支持 Windows 和 posix 终端。

民意调查

GoDoc

一个用于在支持 ANSI 转义序列的终端上构建交互式和易于访问的提示的库。

⚠️ 此项目已停止维护。如需替代方案,请访问:https://github.com/charmbracelet/bubbletea ⚠️

大家好!我最终不得不接受自己无法再投入足够的时间来维护这个库的事实。这个项目的发展远远超出了我的预期,也给我带来了非常棒的经历。如果有人愿意接手维护工作,请联系我。

package main
import (
    "fmt"
    "github.com/AlecAivazis/survey/v2"
)

// the questions to ask
var qs = []*survey.Question{
    {
        Name:     "name",
        Prompt:   &survey.Input{Message: "What is your name?"},
        Validate: survey.Required,
        Transform: survey.Title,
    },
    {
        Name: "color",
        Prompt: &survey.Select{
            Message: "Choose a color:",
            Options: []string{"red"
Enter fullscreen mode Exit fullscreen mode

GitHub 标志 宋姆/提词器

用于轻松提示的 golang 工具

提词器

测试状态 覆盖范围状态 MIT许可证 GoDev

描述

用于在 Golang 中轻松提示的实用程序

概要

twitterID := prompter.Prompt("Enter your twitter ID", "")
lang := prompter.Choose("Which language do you like the most?", []string{"Perl", "Golang", "Scala", "Ruby"}, "Perl")
passwd := prompter.Password("Enter your password")
var likeSushi bool = prompter.YN("Do you like sushi?", true)
var likeBeer bool = prompter.YesNo("Do you like beer?", false)
Enter fullscreen mode Exit fullscreen mode

特征

  • 便于使用
  • 护理非交互式(非tty)环境
    • Default已使用,且该进程未被阻塞
  • 没有 howeyc/gopass(它使用 cgo)依赖项
    • 交叉构建友好
  • &prompter.Prompter{}直接使用可自定义提示设置

执照

麻省理工学院

作者

松木





GitHub 标志 manifoldco / promptui

命令行应用程序的交互式提示符

promptui

命令行应用程序的交互式提示符。

我们创建 Promptui 的初衷是希望让用户能够轻松愉快地使用Manifold CLI探索云服务。

行为准则|贡献指南

GitHub 发布 GoDoc 特拉维斯 成绩单 执照

概述

promptui

Promptui 是一个库,它提供了一个简单的接口,用于创建 Go 命令行提示符。它可以轻松集成到spf13/cobra urfave/cli或任何命令行 Go 应用程序中。

Promptui 有两种主要输入模式:

  • Prompt提供单行用户输入。提示符支持可选的实时验证、确认和输入屏蔽功能。

  • Select提供一系列选项供您选择。选择功能支持分页、搜索、详细视图和自定义模板。

如需查看完整选项列表,请查看GoDoc

基本用法

迅速的

package main
import (
    "errors"
    "fmt"
    "strconv"

    "github.com/manifoldco/promptui"
)

func main() {
    validate := func(input string) error {
        _, err := strconv.ParseFloat(input, 64)
        if
Enter fullscreen mode Exit fullscreen mode

结论

就是这样!希望您喜欢!代码示例可在GitHub上找到。

如果您对使用 Go 语言进行 CLI 应用程序开发感兴趣,并且我们Tidal Migrations正在招聘,请查看我们的招聘页面!

命令行万岁!

文章来源:https://dev.to/tidalcloud/interactive-cli-prompts-in-go-3bj9