golang创建交互式命令行提示链插件库strumt的使用

Golang创建交互式命令行提示链插件库strumt的使用

Strumt是一个用于创建提示链的库。它提供以下功能:

  • 多行提示
  • 输入验证
  • 出错重试
  • 创建类型安全的提示
  • 自定义提示和错误显示
  • 记录提示会话
  • 轻松测试提示场景

示例代码

下面是一个完整的示例,展示如何使用strumt创建一个交互式命令行提示链来收集用户信息:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"

    "github.com/antham/strumt"
)

func main() {
    user := User{}

    // 创建prompt实例,从标准输入读取,输出到标准输出
    p := strumt.NewPromptsFromReaderAndWriter(bufio.NewReader(os.Stdin), os.Stdout)
    
    // 添加三个提示器
    p.AddLinePrompter(&StringPrompt{&user.FirstName, "Enter your first name", "userName", "lastName", "userName"})
    p.AddLinePrompter(&StringPrompt{&user.LastName, "Enter your last name", "lastName", "age", "lastName"})
    p.AddLinePrompter(&IntPrompt{&user.Age, "Enter your age", "age", "", "age"})
    
    // 设置第一个提示的ID
    p.SetFirst("userName")
    
    // 运行提示链
    p.Run()

    // 打印会话记录
    for _, step := range p.Scenario() {
        fmt.Println(step.PromptString())
        fmt.Println(step.Inputs()[0])

        if step.Error() != nil {
            fmt.Println(step.Error())
        }
    }

    fmt.Println()
    fmt.Printf("User datas : %#v", user)
}

// 字符串提示器结构体
type StringPrompt struct {
    store             *string  // 存储用户输入的指针
    prompt            string   // 提示文本
    currentID         string   // 当前提示ID
    nextPrompt        string   // 成功后的下一个提示ID
    nextPromptOnError string   // 出错后的下一个提示ID
}

func (s *StringPrompt) ID() string {
    return s.currentID
}

func (s *StringPrompt) PromptString() string {
    return s.prompt
}

// 解析用户输入
func (s *StringPrompt) Parse(value string) error {
    if value == "" {
        return fmt.Errorf("Empty value given")
    }

    *(s.store) = value
    return nil
}

func (s *StringPrompt) NextOnSuccess(value string) string {
    return s.nextPrompt
}

func (s *StringPrompt) NextOnError(err error) string {
    return s.nextPromptOnError
}

// 整数提示器结构体
type IntPrompt struct {
    store             *int
    prompt            string
    currentID         string
    nextPrompt        string
    nextPromptOnError string
}

func (i *IntPrompt) ID() string {
    return i.currentID
}

func (i *IntPrompt) PromptString() string {
    return i.prompt
}

// 解析用户输入
func (i *IntPrompt) Parse(value string) error {
    age, err := strconv.Atoi(value)

    if err != nil {
        return fmt.Errorf("%s is not a valid number", value)
    }

    if age <= 0 {
        return fmt.Errorf("Give a valid age")
    }

    *(i.store) = age
    return nil
}

func (i *IntPrompt) NextOnSuccess(value string) string {
    return i.nextPrompt
}

func (i *IntPrompt) NextOnError(err error) string {
    return i.nextPromptOnError
}

// 用户数据结构体
type User struct {
    FirstName string
    LastName  string
    Age       int
}

代码说明

  1. 初始化:

    • 创建strumt.Prompts实例,指定输入输出
    • 添加三个提示器:两个字符串输入(姓名),一个整数输入(年龄)
  2. 提示器结构:

    • StringPrompt处理字符串输入
    • IntPrompt处理整数输入并验证有效性
    • 每个提示器实现strumt.LinePrompter接口
  3. 流程控制:

    • NextOnSuccess定义成功后的下一个提示
    • NextOnError定义出错后的处理(通常是重试当前提示)
    • SetFirst设置起始提示ID
  4. 运行和结果:

    • Run()启动提示链
    • Scenario()获取会话记录
    • 最后打印收集到的用户数据

这个示例展示了strumt的核心功能,包括输入验证、错误处理和提示链控制。你可以根据需要扩展更多的提示类型和验证逻辑。


更多关于golang创建交互式命令行提示链插件库strumt的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang创建交互式命令行提示链插件库strumt的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用 strumt 创建交互式命令行工具

strumt 是一个 Go 语言的库,用于创建交互式命令行提示链工具。它允许你构建多步骤的交互式命令行界面,非常适合需要用户逐步输入信息的复杂 CLI 应用。

基本概念

strumt 的核心概念包括:

  • Prompt:单个提示步骤
  • Line:用户输入的一行内容
  • Pipeline:将多个 Prompt 串联起来形成工作流

安装

go get github.com/antham/strumt

基础示例

下面是一个简单的交互式 CLI 示例:

package main

import (
	"fmt"
	"os"

	"github.com/antham/strumt"
)

func main() {
	p := strumt.NewPromptsFromReaderAndWriter(os.Stdin, os.Stdout)

	// 添加第一个提示
	p.AddLinePrompter(&strumt.BaseLinePrompter{
		PromptString: "请输入您的名字: ",
		Validator: func(input string) error {
			if input == "" {
				return fmt.Errorf("名字不能为空")
			}
			return nil
		},
		Next: func(answer string) strumt.Prompter {
			// 存储用户输入
			userName := answer
			
			// 返回下一个提示
			return &strumt.BaseLinePrompter{
				PromptString: fmt.Sprintf("你好 %s! 请输入您的年龄: ", userName),
				Validator: func(input string) error {
					if input == "" {
						return fmt.Errorf("年龄不能为空")
					}
					return nil
				},
				Next: func(answer string) strumt.Prompter {
					fmt.Printf("感谢您的输入,%s (%s岁)!\n", userName, answer)
					return nil // 返回nil结束流程
				},
			}
		},
	})

	p.Run()
}

更复杂的示例

下面是一个更复杂的示例,模拟一个用户注册流程:

package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/antham/strumt"
)

func main() {
	p := strumt.NewPromptsFromReaderAndWriter(os.Stdin, os.Stdout)

	// 用户数据存储
	var user struct {
		Username string
		Email    string
		Password string
		Plan     string
	}

	// 用户名提示
	p.AddLinePrompter(&strumt.BaseLinePrompter{
		PromptString: "请输入用户名: ",
		Validator: func(input string) error {
			if len(input) < 3 {
				return fmt.Errorf("用户名至少需要3个字符")
			}
			return nil
		},
		Next: func(answer string) strumt.Prompter {
			user.Username = answer
			return &strumt.BaseLinePrompter{
				PromptString: "请输入邮箱地址: ",
				Validator: func(input string) error {
					if !strings.Contains(input, "@") {
						return fmt.Errorf("请输入有效的邮箱地址")
					}
					return nil
				},
				Next: func(answer string) strumt.Prompter {
					user.Email = answer
					return &strumt.BaseLinePrompter{
						PromptString: "请输入密码: ",
						MaskInput:   true, // 隐藏输入
						Validator: func(input string) error {
							if len(input) < 6 {
								return fmt.Errorf("密码至少需要6个字符")
							}
							return nil
						},
						Next: func(answer string) strumt.Prompter {
							user.Password = answer
							return &strumt.BaseLinePrompter{
								PromptString: "请选择套餐 (basic/premium/vip): ",
								Validator: func(input string) error {
									switch input {
									case "basic", "premium", "vip":
										return nil
									default:
										return fmt.Errorf("无效的套餐选择")
									}
								},
								Next: func(answer string) strumt.Prompter {
									user.Plan = answer
									
									// 确认步骤
									return &strumt.BaseLinePrompter{
										PromptString: fmt.Sprintf(
											"确认注册信息:\n用户名: %s\n邮箱: %s\n套餐: %s\n确认? (y/n): ",
											user.Username, user.Email, user.Plan,
										),
										Validator: func(input string) error {
											if input != "y" && input != "n" {
												return fmt.Errorf("请输入 y 或 n")
											}
											return nil
										},
										Next: func(answer string) strumt.Prompter {
											if answer == "y" {
												fmt.Println("注册成功!")
												// 这里可以添加实际注册逻辑
											} else {
												fmt.Println("注册已取消")
											}
											return nil // 结束流程
										},
									}
								},
							}
						},
					}
				},
			}
		},
	})

	p.Run()
}

高级功能

多选提示

p.AddLinePrompter(&strumt.BaseLinePrompter{
	PromptString: "选择您感兴趣的主题 (多个选项用逗号分隔):\n1. Go\n2. Python\n3. Rust\n4. JavaScript\n",
	Validator: func(input string) error {
		if input == "" {
			return fmt.Errorf("请至少选择一个主题")
		}
		return nil
	},
	Next: func(answer string) strumt.Prompter {
		topics := strings.Split(answer, ",")
		fmt.Printf("您选择了: %v\n", topics)
		return nil
	},
})

默认值和帮助信息

p.AddLinePrompter(&strumt.BaseLinePrompter{
	PromptString: "请输入服务器端口 [默认: 8080]: ",
	Default:     "8080",
	Help:        "这是服务器监听的端口号",
	Validator: func(input string) error {
		if input == "" {
			return nil // 使用默认值
		}
		// 验证端口号
		return nil
	},
	Next: func(answer string) strumt.Prompter {
		if answer == "" {
			answer = "8080"
		}
		fmt.Printf("将使用端口: %s\n", answer)
		return nil
	},
})

最佳实践

  1. 清晰的提示信息:确保每个提示都清楚地说明需要输入什么
  2. 输入验证:对每个输入进行验证,提供有用的错误信息
  3. 模块化设计:将复杂的提示链分解为多个函数
  4. 提供默认值:在适当的地方提供默认值简化用户输入
  5. 添加帮助信息:为复杂提示添加帮助信息

strumt 是一个强大而灵活的工具,可以帮助你构建复杂的交互式命令行界面。通过合理设计提示链,你可以创建出用户体验良好的 CLI 工具。

回到顶部