# fzfdemo **Repository Path**: lflxp/fzfdemo ## Basic Information - **Project Name**: fzfdemo - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-03-21 - **Last Updated**: 2026-03-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # fzfdemo 一个基于 fzf 风格的交互式命令行工具,支持命令执行、结果选择、模糊搜索和历史命令管理。 ## 功能特性 - 🎯 **命令执行与结果选择** - 执行命令后,结果按行显示,支持单词级选择 - 🔍 **模糊搜索** - 支持精确匹配优先的模糊搜索算法 - 📜 **历史命令管理** - 从 shell history 加载历史命令,支持模糊搜索 - ⌨️ **Vim 快捷键** - 支持 Ctrl+A/E/W/R 等常用快捷键 - 🖱️ **鼠标支持** - 支持鼠标滚轮滚动和点击选择 - 🎨 **颜色主题** - 选中行绿色高亮,搜索匹配红色高亮 - 🚀 **Kubectl 快速操作** - 支持快捷键快速组合 kubectl 命令,类似 CS 游戏快速买枪 ## 项目架构 ``` fzfdemo/ ├── main.go # 主程序文件(所有代码) ├── go.mod # Go 模块定义 ├── go.sum # 依赖版本锁定 ├── fzfdemo # 编译后的可执行文件 └── README.md # 项目文档 ``` ### 核心数据结构 ```go // 主应用结构 type Demo struct { ttyin *os.File // 终端输入 ttyout *os.File // 终端输出 running bool // 运行状态 width int // 终端宽度 height int // 终端高度 origState *term.State // 原始终端状态 theme *tui.ColorTheme // 颜色主题 input *InputBuffer // 输入框状态 selection *SelectionState // 选择框状态 completer *CommandCompleter // 命令补全器 } // 输入缓冲区 type InputBuffer struct { content []rune // 输入内容 cursor int // 光标位置 } // 选择状态 type SelectionState struct { items []string // 原始命令输出 filteredItems []FilteredItem // 过滤后的项目 selected int // 选中行索引 wordStart int // 单词起始位置 wordEnd int // 单词结束位置 words []WordRange // 单词边界 mode SelectMode // 当前模式 scrollOffset int // 滚动偏移 errMsg string // 错误信息 search *SearchBuffer // 搜索缓冲 } // 选择模式 type SelectMode int const ( ModeNormal SelectMode = iota // 输入模式 ModeSelection // 选择模式 ModeSearch // 搜索模式 ModeInteractive // 交互模式 ModeHistory // 历史命令模式 ) ``` ## 数据流程 ``` ┌─────────────────────────────────────────────────────────────────┐ │ 用户输入流程 │ └─────────────────────────────────────────────────────────────────┘ 用户输入字符 │ ▼ ┌───────────────┐ │ handleInput │ ← 处理键盘/鼠标输入 └───────────────┘ │ ├─→ Tab/回车 ─→ executeCommand() ─→ 终端显示结果 │ │ │ ▼ │ ModeSelection (选择模式) │ │ │ ┌───────┴───────┐ │ ▼ ▼ │ j/k/↑↓ 选择 / 搜索 │ │ │ │ ▼ ▼ │ 选择单词 ModeSearch │ │ │ │ ▼ ▼ │ 回车确认 模糊匹配过滤 │ │ │ ▼ │ 添加到输入框 │ ├─→ Ctrl+R ─→ searchHistory() ─→ ModeHistory │ │ │ ▼ │ 模糊搜索历史命令 │ │ │ ▼ │ 选择并填入输入框 │ ├─→ , (逗号) ─→ 接受补全建议 │ └─→ Ctrl+C ─→ 退出程序 ``` ## 功能设计 ### 1. 输入模式 (ModeNormal) - 字符输入:在光标位置插入 - 命令补全:从历史命令中匹配前缀,灰色显示建议 - Vim 快捷键:Ctrl+A/E/W 支持 ### 2. 选择模式 (ModeSelection) - 行级选择:↑↓ 或 j/k 上下移动 - 单词选择:←→ 或 h/l 左右移动 - 搜索功能:按 / 进入搜索模式 - 确认选择:回车将选中单词添加到输入框 ### 3. 搜索模式 (ModeSearch) - 模糊匹配:精确匹配优先,连续匹配加分 - 实时过滤:输入字符即时过滤结果 - 高亮显示:匹配字符用红色加粗显示 ### 4. 历史命令模式 (ModeHistory) - 快捷键:Ctrl+R 进入 - 模糊搜索:支持不连续字符匹配 - 快速填入:回车将选中命令填入输入框 ### 5. 交互模式 (ModeInteractive) - 适用命令:vim, ssh, top, kubectl edit 等 - 终端接管:恢复终端状态后执行命令 - 自动返回:命令结束后返回主界面 ## 关键代码 ### 模糊匹配算法 ```go func FuzzyMatch(pattern, text string) FuzzyMatchResult { // 1. 精确匹配优先(连续字符串) exactIdx := strings.Index(textLower, patternLower) if exactIdx >= 0 { // 精确匹配得分 = 1000 + 长度*100 // 单词开头加分 +500 // 路径分隔符后加分 +300 return FuzzyMatchResult{score: 1000 + patternLen*100, matched: true} } // 2. 模糊匹配(不连续字符) // 基础分数 + 连续加分 + 单词开头加分 // 连续匹配:每次递增 +2 // 单词开头:+10 // 驼峰命名:+5 } ``` ### 命令执行 ```go func (d *Demo) executeCommand(command string) { // 使用 sh 执行命令,速度快 cmd := exec.Command("sh", "-c", command) cmd.Env = os.Environ() // 从 /dev/null 读取 stdin,避免 suspended devNull, _ := os.Open("/dev/null") cmd.Stdin = devNull // 捕获 stdout 和 stderr var stdout, stderr strings.Builder cmd.Stdout = &stdout cmd.Stderr = &stderr cmd.Run() // 合并输出并显示 lines := strings.Split(allOutput, "\n") d.selection.SetItems(lines) d.selection.mode = ModeSelection } ``` ### 历史命令加载 ```go func (cc *CommandCompleter) loadHistory() { // 读取多个 history 文件 historyFiles := []string{ "~/.bash_history", "~/.zsh_history", "~/.local/share/fish/fish_history", } // 解析 zsh history 格式: ": timestamp:0;command" if strings.HasPrefix(line, ": ") { parts := strings.SplitN(line, ";", 2) line = parts[1] } // 按频率和时间排序 sort.Slice(cc.history, func(i, j int) bool { return cc.history[i].frequency > cc.history[j].frequency }) } ``` ### 终端控制 ```go func (d *Demo) Init() error { // 打开终端 d.ttyin, _ = os.OpenFile("/dev/tty", os.O_RDONLY, 0) d.ttyout, _ = os.OpenFile("/dev/tty", os.O_WRONLY, 0) // 设置 raw 模式 d.origState, _ = term.MakeRaw(int(d.ttyin.Fd())) // 启用鼠标 d.csi("?1000h") // 按钮点击 d.csi("?1002h") // 拖拽和滚轮 d.csi("?1006h") // SGR 扩展模式 } ``` ## 使用说明 ### 安装 ```bash # 克隆项目 git clone cd fzfdemo # 编译 go build -o fzfdemo main.go # 复制到 PATH(可选) sudo cp fzfdemo /usr/local/bin/ ``` ### 基本使用 ```bash # 直接运行 ./fzfdemo # 带参数运行(命令预填充到输入框) ./fzfdemo kubectl get pods ./fzfdemo docker ps ./fzfdemo ls -la ``` ### 快捷键一览 #### 输入模式 | 快捷键 | 功能 | |--------|------| | `Tab` / `回车` | 执行命令 | | `Ctrl+R` | 搜索历史命令 | | `Ctrl+K` | Kubectl 快速操作 | | `Ctrl+Q` | 重置输入框 | | `Ctrl+A` | 光标移到行首 | | `Ctrl+E` | 光标移到行尾 | | `Ctrl+W` | 删除前面一个单词 | | `Ctrl+C` | 退出程序 | | `,` | 接受补全建议 | #### 选择模式 | 快捷键 | 功能 | |--------|------| | `↑↓` 或 `j/k` | 上下选择行 | | `←→` 或 `h/l` | 左右选择单词 | | `/` | 进入搜索模式 | | `回车` | 将选中单词添加到输入框 | | `ESC` | 返回输入模式 | | `q` | 退出程序 | #### 搜索模式 | 快捷键 | 功能 | |--------|------| | `字符输入` | 模糊搜索过滤 | | `↑↓` | 上下选择行 | | `Tab` | 切换到单词选择 | | `回车` | 确认选择 | | `ESC` | 取消搜索 | #### 历史命令模式 | 快捷键 | 功能 | |--------|------| | `字符输入` | 模糊搜索过滤 | | `↑↓` | 上下选择行 | | `回车` | 将命令填入输入框 | | `ESC` / `q` | 取消 | | `Backspace` | 删除字符重新搜索 | ### 使用示例 ```bash # 示例 1:执行命令并选择结果中的内容 ./fzfdemo > kubectl get pods # 输入命令 [Tab 执行] nginx-pod Running 1/1 # 显示结果 redis-pod Running 1/1 mysql-pod Running 1/1 # 用 j/k 选择行,h/l 选择单词 # 回车将选中内容添加到输入框 > kubectl get pods mysql-pod # 输入框变为这样 # 示例 2:搜索历史命令 ./fzfdemo > [Ctrl+R] 历史命令 (共 500 条) kubectl get pods -A docker ps ls -la # 输入字符过滤,回车填入命令 # 示例 3:使用命令补全 ./fzfdemo > kubectl ge # 输入部分命令 > kubectl get [pods] # 灰色显示补全建议 > kubectl get , # 按逗号接受补全 # 示例 4:在结果中搜索 ./fzfdemo > ls -la [Tab 执行] total 48 drwxr-xr-x 5 user staff 160 . -rw-r--r-- 1 user staff 1234 main.go -rw-r--r-- 1 user staff 567 go.mod [/ 进入搜索] > main # 输入搜索内容 -rw-r--r-- 1 user staff 1234 main.go # 只显示匹配的行 # 示例 5:Kubectl 快速操作(类似 CS 游戏快速买枪) ./fzfdemo > [Ctrl+K] # 进入 Kubectl 快速操作模式 ╔══════════════════════════════════════╗ ║ 选择操作类型 (输入数字) ║ ╠══════════════════════════════════════╣ ║ [1] get - 获取资源列表 ║ ║ [2] edit - 编辑资源 ║ ║ [3] delete - 删除资源 ║ ║ [4] describe - 查看资源详情 ║ ║ [5] logs - 查看Pod日志 ║ ║ [6] exec - 在容器中执行命令 ║ ║ [7] apply - 应用配置文件 ║ ║ [8] create - 创建资源 ║ ╚══════════════════════════════════════╝ > [1] # 输入 1 选择 get 操作 # 自动进入资源搜索列表 # 显示所有可用资源 [1] pods (po) [2] services (svc) [3] deployments (deploy) [4] configmaps (cm) [5] secrets # 直接输入搜索字符过滤(如 "pod") > pod [1] pods (po) # 或输入数字直接选择(如 1) > [1] # 选择 pods # 自动生成命令并显示结果 > kubectl get pods # 搜索列表显示 kubectl get pods -A 的结果 NAMESPACE NAME READY STATUS default nginx-pod 1/1 Running default redis-pod 1/1 Running kube-system coredns-xxx 1/1 Running # 输入搜索字符过滤(如 "default") > default NAMESPACE NAME READY STATUS default nginx-pod 1/1 Running default redis-pod 1/1 Running # 选择具体资源后按回车 > nginx-pod # 自动生成完整命令并填入输入框 > kubectl get pods -n default nginx-pod ``` ## Kubectl 快速操作 这是一个类似 CS 游戏快速买枪的快捷键功能,可以快速组合 kubectl 命令。 ### 使用流程 ``` Ctrl+K → 输入操作数字 → 输入资源数字 → 自动搜索 → 选择资源 → 生成命令 ``` ### 详细步骤 1. **按 Ctrl+K 进入快速操作模式** - 显示操作类型选择框(8 种操作) 2. **输入操作类型数字** - 1 = get(获取资源) - 2 = edit(编辑资源) - 3 = delete(删除资源) - 4 = describe(查看资源详情) - 5 = logs(查看 Pod 日志) - 6 = exec(在容器中执行命令) - 7 = apply(应用配置文件) - 8 = create(创建资源) 3. **自动进入资源搜索列表** - 显示所有可用资源(pods, services, deployments 等) - 支持直接输入搜索字符过滤 - 支持输入数字快速选择 4. **选择资源后自动执行** - 输入框显示:`kubectl get pods` - 搜索列表显示:`kubectl get pods -A` 的执行结果 5. **在搜索列表中选择具体资源** - 输入搜索字符过滤(如 "default") - 按回车选择具体资源 - 自动生成完整命令填入输入框 ### 快捷组合示例 | 快捷键序列 | 结果 | |------------|------| | `Ctrl+K` → `1` → `1` | kubectl get pods | | `Ctrl+K` → `2` → `3` | kubectl edit deployments | | `Ctrl+K` → `5` → `1` | kubectl logs pods | | `Ctrl+K` → `3` → `4` | kubectl delete configmaps | ### 搜索功能 在资源搜索列表中: - 直接输入字符进行模糊搜索 - 支持精确匹配(完全匹配) - 支持前缀匹配(以搜索词开头) - 支持包含匹配(包含搜索词) - 按 Tab 清空搜索,恢复所有资源 - 按 ESC 退出 ## 交互式命令支持 以下命令会自动识别为交互式命令,终端会交给命令控制: | 类别 | 命令 | |------|------| | 编辑器 | vim, vi, nvim, nano, emacs | | 分页器 | less, more, man | | Kubernetes | kubectl edit, kubectl exec -it, kubectl logs -f, -w, --watch | | Docker | docker exec -it, docker run -it | | 远程连接 | ssh, telnet, ftp | | 监控工具 | top, htop, watch | | 数据库 | mysql, psql, redis-cli | | Git | git rebase -i, git commit --interactive | ## 颜色主题 | 元素 | 颜色 | |------|------| | 输入框边框 | 亮青色 | | 命令提示符 `>` | 绿色 | | 选中行 | 亮绿色 | | 未选中行 | 灰色 | | 搜索匹配字符 | 红色加粗 | | 单词选择 | 反色白字 | | 历史命令标题 | 品红色 | | 状态栏 | 黄色 | | 帮助栏 | 灰色 | | 错误信息 | 红色 | ## 依赖 ```go require ( github.com/junegunn/fzf v0.70.0 // 颜色主题 golang.org/x/term v0.41.0 // 终端控制 ) ``` ## 系统要求 - Go 1.21+ - 支持 ANSI 转义序列的终端(iTerm2, Terminal.app, Windows Terminal 等) - macOS / Linux ## 许可证 MIT License