- 开发工具
【免费下载链接】pterm
✨ PTerm is a modern Go module to easily beautify console output. Featuring charts, progressbars, tables, trees, text input, select menus and much more 🚀 It's completely configurable and 100% cross-platform compatible.
本指南聚焦 Go 终端美化库 PTerm 中InteractiveMultiselectPrinter的筛选输入框占位提示(filter input placeholder)定制能力。通过_examples/interactive_multiselect/custom-filter-placeholder这一官方示例,你将掌握如何把默认的[type to search]提示替换为带图标的个性化文案,并理解该占位文本在模糊搜索渲染管线中的位置与作用,从而打造更友好的交互式多选命令行界面。
场景背景:带模糊搜索的多选菜单
PTerm 的InteractiveMultiselectPrinter(源码见 interactive_multiselect_printer.go)用于渲染可交互的多选菜单:用户通过键盘逐项勾选、确认后程序拿到所选选项列表。它的默认实例DefaultInteractiveMultiselect自带以下关键配置(见 interactive_multiselect_printer.go):
Filter: true——默认开启模糊筛选,用户直接在输入框敲字符即可实时过滤选项;MaxHeight: 5——菜单最多同时显示 5 行,超出部分自动滚动;FilterInputPlaceholder: "[type to search]"——筛选输入框为空时显示的占位提示;KeySelect: keys.Enter、KeyConfirm: keys.Tab——回车勾选/取消勾选,Tab 确认提交;Selector: "❯"——当前高亮行的选择指示符。
模糊匹配本身由github.com/lithammer/fuzzysearch/fuzzy库的fuzzy.RankFindFold完成(见 interactive_multiselect_printer.go),大小写不敏感且按匹配度排序。占位提示就是这一筛选体验的第一视觉入口,因此官方专门提供了custom-filter-placeholder示例来说明如何定制它。
完整示例:自定义筛选占位提示
官方示例的完整源码位于 _examples/interactive_multiselect/custom-filter-placeholder/main.go,对应 README 见 _examples/interactive_multiselect/custom-filter-placeholder/README.md。核心代码如下:
package main import ( "fmt" "github.com/pterm/pterm" ) func main() { var options []string for i := 0; i < 100; i++ { options = append(options, fmt.Sprintf("Option %d", i)) } // A few extra options that are easy to find with the fuzzy search filter. for i := 0; i < 5; i++ { options = append(options, fmt.Sprintf("You can use fuzzy searching (%d)", i)) } // WithFilterInputPlaceholder replaces the hint text that is shown in the // filter input while it is still empty. printer := pterm.DefaultInteractiveMultiselect. WithOptions(options). WithFilterInputPlaceholder("🔍 Start typing") selectedOptions, _ := printer.Show() pterm.Info.Printfln("Selected options: %s", pterm.Green(selectedOptions)) }代码拆解
- 构造 105 个选项:前 100 个是规则的
Option 0到Option 99,另外追加 5 个包含fuzzy searching字样的特殊选项。这样设计是为了演示模糊搜索:直接输入fuzzy就能把列表瞬间过滤到那 5 个目标项,验证搜索能力的真实可用性。 - 链式配置:
pterm.DefaultInteractiveMultiselect是零值预置的默认实例,WithOptions(options)注入选项列表,WithFilterInputPlaceholder("🔍 Start typing")替换占位提示。PTerm 的With*方法采用“返回新实例”的链式风格(见 interactive_multiselect_printer.go),不会污染全局默认对象。 - 展示与输出:
Show()进入交互循环,返回([]string, error);随后用pterm.Info.Printfln与pterm.Green以绿色信息流打印最终选中项。
WithFilterInputPlaceholder 的底层实现
从源码看,该能力由三个部分组成(见 interactive_multiselect_printer.go):
- 字段定义:
FilterInputPlaceholder string是InteractiveMultiselectPrinter结构体上的公开字段; - 默认值:
DefaultInteractiveMultiselect中预置为"[type to search]"; - 设置器:
// WithFilterInputPlaceholder sets the filter input placeholder text. func (p InteractiveMultiselectPrinter) WithFilterInputPlaceholder(text string) *InteractiveMultiselectPrinter { p.FilterInputPlaceholder = text return &p }占位文本在哪里被渲染
占位提示并非“输入框内”的独立控件,而是作为菜单标题行的一部分渲染。在renderSelectMenu中(见 interactive_multiselect_printer.go):
if p.Filter { content.WriteString(Sprintf("%s %s: %s\n", p.text, p.SelectorStyle.Sprint(p.FilterInputPlaceholder), p.fuzzySearchString)) }即菜单首行输出格式为:提示文本 + 占位提示(带SelectorStyle样式)+ 用户已输入的搜索字符串。这意味着:
- 占位提示始终显示在冒号左侧、紧跟主题文本之后,并以
SelectorStyle(默认主题的SecondaryStyle)着色; - 用户开始输入后,
p.fuzzySearchString不断追加字符(keys.RuneKey分支,见 interactive_multiselect_printer.go),冒号右侧实时回显输入内容,占位提示仍然保留在左侧作为引导; - 使用
keys.Backspace删除输入时,代码按 rune(而非 byte)逐个移除字符(见 interactive_multiselect_printer.go),确保 emoji 等多字节字符也能正确回退;当搜索串清空后,完整选项列表自动恢复。
理解了这一点就能明白:WithFilterInputPlaceholder只影响“输入为空时”的提示文案,不影响模糊搜索本身的行为与结果。同一定制能力在单选菜单InteractiveSelectPrinter中也存在(默认值同为"[type to search]",见 interactive_select_printer.go),只是该示例以多选菜单呈现。
键盘操作与交互流程
运行该示例后,交互流程与默认菜单一致,仅首行提示文案变为🔍 Start typing:
| 按键 | 作用 |
|---|---|
Enter | 勾选 / 取消勾选当前高亮项 |
Tab | 确认选择并结束交互 |
↑/↓(或Ctrl+P/Ctrl+N) | 移动高亮光标,超出可视窗口自动滚动 |
← | 取消全部选择 |
→ | 全选所有选项 |
| 任意字符键 | 追加到模糊搜索串,实时过滤选项 |
Backspace | 删除搜索串最后一个字符(按 rune 处理) |
Ctrl+C | 中断并触发OnInterruptFunc(若已配置) |
其中Enter/Tab的默认键位可通过WithKeySelect/WithKeyConfirm重绑定,但注意:当Filter开启时,KeySelect与KeyConfirm均不能设置为keys.Space,否则Show()会返回错误if filter/search is active, keys.Space can not be used for KeySelect or KeyConfirm(见 interactive_multiselect_printer.go)。该约束同样被测试用例 interactive_multiselect_printer_test.go 明确覆盖。
CI 自动化:无人值守演示
示例目录下还附带一个 _examples/interactive_multiselect/custom-filter-placeholder/ci.go,它的作用是在CI=true环境变量存在时,通过keyboard.SimulateKeyPress自动模拟按键序列,使交互式 demo 可以无人值守运行并被录制成文档动画:
- 逐个敲入
fuzzy触发模糊过滤(每个字符间隔 150ms); - 依次
Enter、Down、Enter、Down、Enter勾选 3 个匹配项; Tab确认提交。
这套模拟与单元测试中simulateKeys(见 interactive_test.go)的思路一致:通过全局键盘 mock 注入按键流,验证交互行为。日常开发中你无需关心该文件,直接忽略即可。
运行示例
在 Go 1.26+(见 go.mod)环境中,进入示例目录直接运行:
cd _examples/interactive_multiselect/custom-filter-placeholder go run main.go如需无人值守自动演示,可设置环境变量后运行:
CI=true go run main.go示例运行完成后,程序会打印类似INFO Selected options: [You can use fuzzy searching (0) ...]的结果行。也可以在项目根目录执行bash _examples/test.sh批量跑通所有示例(见 _examples/test.sh)。
实践要点小结
- 占位提示默认值为
[type to search],通过WithFilterInputPlaceholder可替换为任意字符串,包括 emoji 与多字节文本(渲染与回退均按 UTF-8 rune 安全处理); - 占位文本在
renderSelectMenu中以SelectorStyle样式渲染在菜单标题行,冒号右侧实时回显模糊搜索输入; - 自定义占位提示不影响模糊搜索、滚动、全选/全不选等既有交互能力,可与
WithShowSelectedOptions、WithCheckmark、WithMaxHeight等方法自由组合; - 若关闭筛选(
WithFilter(false)),占位提示将不再显示,因为渲染分支只在Filter == true时输出占位文本; - 交互式组件依赖终端支持 ANSI 控制序列与按键监听,示例为跨平台设计,但务必在真实终端(而非管道重定向)中运行才能获得完整交互体验。
- 开发工具
【免费下载链接】pterm
✨ PTerm is a modern Go module to easily beautify console output. Featuring charts, progressbars, tables, trees, text input, select menus and much more 🚀 It's completely configurable and 100% cross-platform compatible.
相关推荐
pterm 交互式多选组件自定义勾选标记(Checkmark)实战指南
pterm 交互式多选组件自定义勾选标记(Checkmark)实战指南 导读 本文以 pterm 仓库中的 interactive_multiselect/cu
开发工具PTerm交互式组件完全指南:从文本输入到多选菜单的实战技巧
PTerm交互式组件完全指南:从文本输入到多选菜单的实战技巧 PTerm是一个现代化的Go模块,专门用于美化控制台输出。它提供了丰富的交互式组件,包括文本输入框
开发工具PTerm InteractiveMultiselect 实战指南:构建带模糊搜索与自定义按键的终端多选菜单
PTerm InteractiveMultiselect 实战指南:构建带模糊搜索与自定义按键的终端多选菜单 PTerm 的 InteractiveMultis
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考