Kode-cli/docs/TAB_BEHAVIOR_DEMO.md
CrazyBoyM 926df2cfaf feat: Ultra-redesign completion system with @mention integration
- Complete architectural overhaul of useUnifiedCompletion hook
- Unified state management: 8 separate states → single CompletionState interface
- Simplified core logic: getWordAtCursor 194 lines → 42 lines (78% reduction)
- Fixed infinite React update loops with ref-based input tracking
- Smart triggering mechanism replacing aggressive auto-completion
- Integrated @agent and @file mention system with system reminders
- Added comprehensive agent loading and mention processing
- Enhanced Tab/Arrow/Enter key handling with clean event management
- Maintained 100% functional compatibility across all completion types

Key improvements:
• File path completion (relative, absolute, ~expansion, @references)
• Slash command completion (/help, /model, etc.)
• Agent completion (@agent-xxx with intelligent descriptions)
• System command completion (PATH scanning with fallback)
• Terminal-style Tab cycling, Enter confirmation, Escape cancellation
• Preview mode with boundary calculation
• History navigation compatibility
• Empty directory handling with user feedback

Architecture: Event-driven @mention detection → system reminder injection → LLM tool usage
Performance: Eliminated 7-layer nested conditionals, reduced state synchronization issues
Reliability: Fixed maximum update depth exceeded warnings, stable state management
2025-08-21 01:21:12 +08:00

3.9 KiB
Raw Permalink Blame History

Tab 补全行为演示

🎯 核心洞察Tab的两个职责

1 Tab = "尽可能补全"

2 Tab Tab = "显示所有选项"


📱 实际例子假设有文件package.json, package-lock.json

标准终端的智慧

cat p[Tab]
# 🤔 思考:有 package.json, package-lock.json, public/
# 💡 决策:补全到公共前缀
cat package█

cat package[Tab]  
# 🤔 思考:还是有歧义
# 💡 决策:不动(或蜂鸣)

cat package[Tab][Tab]
# 🤔 思考:用户需要看选项了
# 💡 决策:显示所有
package.json  package-lock.json

cat package.j[Tab]
# 🤔 思考:唯一匹配!
# 💡 决策:直接补全
cat package.json█

我们现在的问题

cat p[Tab]
# 😵 立即显示菜单
▸ package.json
  package-lock.json  
  public/
# 用户:我只是想补全啊,不是要选择!

🧠 终端的补全决策树

按下 Tab
    ↓
有几个匹配?
    ↓
┌────────┼────────┐
0个      1个      多个
↓        ↓        ↓
蜂鸣    补全完成   有公共前缀?
                   ↓
              ┌────┴────┐
              有        无
              ↓         ↓
          补全前缀   是第二次Tab
                      ↓
                 ┌────┴────┐
                 是        否
                 ↓         ↓
             显示菜单    蜂鸣

💭 为什么这样设计?

效率原则

  • 最少按键: 能补全就补全,不要问
  • 渐进显示: 只在需要时才显示选项
  • 智能判断: 根据上下文做最合理的事

用户心智模型

Tab = "帮我补全"
Tab Tab = "我需要看看有什么选项"

🔨 我们需要的改动

当前代码(过于简单)

if (key.tab) {
  if (suggestions.length > 1) {
    showMenu()  // ❌ 太早了!
  }
}

应该的代码(智能判断)

if (key.tab) {
  const now = Date.now()
  const isDoubleTab = (now - lastTabTime) < 300
  
  if (suggestions.length === 0) {
    beep()
  } else if (suggestions.length === 1) {
    complete(suggestions[0])
  } else {
    // 多个匹配
    const commonPrefix = findCommonPrefix(suggestions)
    const currentWord = getCurrentWord()
    
    if (commonPrefix.length > currentWord.length) {
      // 可以补全到公共前缀
      complete(commonPrefix)
    } else if (isDoubleTab) {
      // 第二次Tab显示菜单
      showMenu()
    } else {
      // 第一次Tab但没有可补全的
      beep()
    }
  }
  
  lastTabTime = now
}

🎮 交互示例

场景:输入命令参数

# 文件: README.md, README.txt, package.json

$ cat R[Tab]
$ cat README      # 补全公共前缀

$ cat README[Tab]
*beep*            # 无法继续补全

$ cat README[Tab][Tab]
README.md  README.txt   # 显示选项

$ cat README.m[Tab]
$ cat README.md   # 唯一匹配,完成

场景:路径导航

$ cd s[Tab]
$ cd src/         # 唯一匹配,补全+加斜杠

$ cd src/[Tab][Tab]
components/  hooks/  utils/   # 继续显示下级

$ cd src/c[Tab]
$ cd src/components/   # 继续补全

📊 影响分析

操作 按键次数(现在) 按键次数(改进后) 节省
输入 package.json 5次(p+Tab+↓+↓+Enter) 3次(pa+Tab+.j+Tab) 40%
进入 src/components 4次(s+Tab+Enter+c+Tab) 2次(s+Tab+c+Tab) 50%
选择多个选项之一 3次(Tab+↓+Enter) 4次(Tab+Tab+↓+Enter) -33%

平均效率提升:~30%


🚀 结论

一个原则Tab应该"尽力而为",而不是"立即放弃"

两个规则

  1. 能补全就补全
  2. 不能补全才显示选项(且需要双击)

三个好处

  1. 符合用户期望
  2. 减少操作次数
  3. 保持专注流程