golang构建强大交互式命令行工具插件库go-prompt的使用

Golang构建强大交互式命令行工具插件库go-prompt的使用

go-prompt是一个受python-prompt-toolkit启发的库,用于构建强大的交互式提示,使使用Go构建跨平台命令行工具变得更加容易。

基本使用示例

下面是一个使用go-prompt的基本示例:

package main

import (
	"fmt"
	"github.com/c-bata/go-prompt"
)

// completer函数提供自动补全建议
func completer(d prompt.Document) []prompt.Suggest {
	s := []prompt.Suggest{
		{Text: "users", Description: "Store the username and age"},
		{Text: "articles", Description: "Store the article text posted by user"},
		{Text: "comments", Description: "Store the text commented to articles"},
	}
	return prompt.FilterHasPrefix(s, d.GetWordBeforeCursor(), true)
}

func main() {
	fmt.Println("Please select table.")
	// 启动prompt,显示"> "提示符,并使用completer提供补全
	t := prompt.Input("> ", completer)
	fmt.Println("You selected " + t)
}

主要特性

强大的自动补全功能

go-prompt提供了强大的自动补全功能,可以轻松实现命令、参数等的智能提示。

灵活的选项配置

go-prompt提供了许多配置选项,可以自定义提示符的行为和外观。

键盘快捷键支持

默认支持以下Emacs风格的键盘快捷键(这些也是Bash shell中的默认快捷键):

快捷键 描述
Ctrl + A 移动到行首(Home)
Ctrl + E 移动到行尾(End)
Ctrl + P 上一条命令(上箭头)
Ctrl + N 下一条命令(下箭头)
Ctrl + F 向前移动一个字符
Ctrl + B 向后移动一个字符
Ctrl + D 删除光标下的字符
Ctrl + H 删除光标前的字符(Backspace)
Ctrl + W 剪切光标前的单词到剪贴板
Ctrl + K 剪切光标后的行到剪贴板
Ctrl + U 剪切光标前的行到剪贴板
Ctrl + L 清屏

命令历史记录

可以使用上箭头和下箭头键浏览和执行过的命令历史。

多平台支持

go-prompt已在以下终端中测试通过:

  • iTerm2 (macOS)
  • Terminal.app (macOS)
  • Command Prompt (Windows)
  • gnome-terminal (Ubuntu)

使用go-prompt的项目

一些使用go-prompt的项目包括:

  • kube-prompt:交互式Kubernetes客户端
  • rancher/cli:Rancher命令行界面
  • kubicorn/kubicorn:Kubernetes的云原生基础设施
  • evans:更通用的gRPC客户端
  • docker-slim:优化Docker容器镜像的工具

许可证

go-prompt采用MIT许可证。


更多关于golang构建强大交互式命令行工具插件库go-prompt的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang构建强大交互式命令行工具插件库go-prompt的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Go-Prompt: 构建强大交互式命令行工具

Go-Prompt 是一个用于 Go 语言的交互式命令行输入库,它提供了类似现代 Shell 的自动补全、语法高亮和历史记录等功能。下面我将详细介绍如何使用 go-prompt 构建强大的交互式 CLI 工具。

基本安装

首先安装 go-prompt 库:

go get github.com/c-bata/go-prompt

基础用法示例

package main

import (
	"fmt"
	"github.com/c-bata/go-prompt"
)

func executor(in string) {
	fmt.Printf("你输入了: %s\n", in)
}

func completer(in prompt.Document) []prompt.Suggest {
	s := []prompt.Suggest{
		{Text: "help", Description: "显示帮助信息"},
		{Text: "exit", Description: "退出程序"},
		{Text: "list", Description: "列出所有项目"},
		{Text: "add", Description: "添加新项目"},
	}
	return prompt.FilterHasPrefix(s, in.GetWordBeforeCursor(), true)
}

func main() {
	p := prompt.New(
		executor,
		completer,
		prompt.OptionPrefix(">>> "),
		prompt.OptionTitle("我的CLI工具"),
	)
	p.Run()
}

核心功能详解

1. 执行器(Executor)

执行器函数处理用户输入的命令:

func executor(in string) {
	switch in {
	case "help":
		fmt.Println("帮助信息...")
	case "exit":
		fmt.Println("再见!")
		os.Exit(0)
	default:
		fmt.Printf("未知命令: %s\n", in)
	}
}

2. 自动补全(Completer)

补全函数提供建议列表:

func completer(d prompt.Document) []prompt.Suggest {
	commands := []prompt.Suggest{
		{Text: "create", Description: "创建新资源"},
		{Text: "delete", Description: "删除资源"},
		{Text: "update", Description: "更新资源"},
	}
	
	// 根据当前输入过滤建议
	return prompt.FilterHasPrefix(commands, d.GetWordBeforeCursor(), true)
}

3. 高级选项配置

go-prompt 提供了丰富的配置选项:

p := prompt.New(
	executor,
	completer,
	prompt.OptionPrefix("my-cli> "),
	prompt.OptionTitle("交互式CLI工具"),
	prompt.OptionPrefixTextColor(prompt.Yellow),
	prompt.OptionPreviewSuggestionTextColor(prompt.Blue),
	prompt.OptionSelectedSuggestionBGColor(prompt.LightGray),
	prompt.OptionSuggestionBGColor(prompt.DarkGray),
	prompt.OptionMaxSuggestion(10),
	prompt.OptionHistory([]string{"help", "exit"}),
)

实战示例:构建一个简单的文件管理器

package main

import (
	"fmt"
	"os"
	"strings"

	"github.com/c-bata/go-prompt"
)

var currentDir = "."

func executor(in string) {
	args := strings.Fields(in)
	if len(args) == 0 {
		return
	}

	switch args[0] {
	case "cd":
		if len(args) < 2 {
			fmt.Println("用法: cd <目录>")
			return
		}
		if err := os.Chdir(args[1]); err != nil {
			fmt.Printf("错误: %v\n", err)
		} else {
			currentDir, _ = os.Getwd()
		}
	case "ls":
		files, err := os.ReadDir(currentDir)
		if err != nil {
			fmt.Printf("错误: %v\n", err)
			return
		}
		for _, file := range files {
			fmt.Println(file.Name())
		}
	case "exit":
		os.Exit(0)
	default:
		fmt.Printf("未知命令: %s\n", args[0])
	}
}

func completer(d prompt.Document) []prompt.Suggest {
	commands := []prompt.Suggest{
		{Text: "cd", Description: "更改目录"},
		{Text: "ls", Description: "列出文件"},
		{Text: "exit", Description: "退出程序"},
	}

	// 如果是cd命令,提供目录补全
	if strings.HasPrefix(d.TextBeforeCursor(), "cd ") {
		dirs := getDirSuggestions()
		return prompt.FilterHasPrefix(dirs, d.GetWordBeforeCursor(), true)
	}

	return prompt.FilterHasPrefix(commands, d.GetWordBeforeCursor(), true)
}

func getDirSuggestions() []prompt.Suggest {
	files, err := os.ReadDir(currentDir)
	if err != nil {
		return nil
	}

	var dirs []prompt.Suggest
	for _, file := range files {
		if file.IsDir() {
			dirs = append(dirs, prompt.Suggest{
				Text:        file.Name(),
				Description: "目录",
			})
		}
	}
	return dirs
}

func main() {
	currentDir, _ = os.Getwd()
	
	p := prompt.New(
		executor,
		completer,
		prompt.OptionPrefix(currentDir+"> "),
		prompt.OptionTitle("简单文件管理器"),
	)
	p.Run()
}

高级特性

1. 自定义键绑定

p := prompt.New(
	executor,
	completer,
	prompt.OptionAddKeyBind(prompt.KeyBind{
		Key: prompt.ControlC,
		Fn: func(buf *prompt.Buffer) {
			fmt.Println("\n按Ctrl+C退出")
			os.Exit(0)
		},
	}),
)

2. 实时前缀更新

func livePrefix() (string, bool) {
	dir, _ := os.Getwd()
	return dir + "> ", true
}

p := prompt.New(
	executor,
	completer,
	prompt.OptionLivePrefix(livePrefix),
)

3. 多行输入支持

p := prompt.New(
	executor,
	completer,
	prompt.OptionMultiLine(true),
)

最佳实践

  1. 清晰的命令结构:设计清晰的命令层次结构
  2. 丰富的补全提示:为每个命令提供详细的描述
  3. 错误处理:优雅地处理用户输入错误
  4. 性能考虑:对于大量补全项,考虑延迟加载
  5. 测试:编写测试确保交互行为符合预期

总结

go-prompt 是一个功能强大且灵活的库,可以帮助你快速构建具有现代 Shell 特性的交互式命令行工具。通过合理使用其自动补全、历史记录和自定义样式等功能,可以显著提升用户体验。

回到顶部