Fix 5 TUI bugs: layout, viewport, history, completion, help#15
Fix 5 TUI bugs: layout, viewport, history, completion, help#15twokidsCarl merged 1 commit intomainfrom
Conversation
- #4: Remove extra blank line below textarea (fix chat_height calc) - #5: Reset textarea viewport offset after height change to show line 1 - #6: Up/down arrows navigate history from first/last line of multi-line - #7: Include private_methods in tab completion for user-defined methods - #10: Indent all lines of multi-line system messages consistently Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
走查(Walkthrough)此PR增强了TUI组件的交互功能:优化聊天面板布局和消息渲染,扩展输入补全以支持私有方法和用户定义,实现鼠标交互(滚动、分隔线拖动、zone点击),以及动态加载可选的bubblezone依赖。 变更(Changes)
可能相关的PR
预估代码审查工作量🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (3)
lib/claw/tui/model.rb (2)
25-25: 静态分析提示:异常捕获顺序可优化。当前
rescue LoadError, Gem::MissingSpecError, Errno::EEXIST, Errno::EACCES的顺序虽然在 Ruby 中不会导致实际的遮蔽问题(因为它们不是继承关系),但按照惯例,建议将更具体的异常放在前面以提高代码可读性。此外,空的 rescue 块可以添加注释说明预期行为。
♻️ 建议改进
- rescue LoadError, Gem::MissingSpecError, Errno::EEXIST, Errno::EACCES - # mouse click zones will be disabled but scroll/drag still work. + rescue Errno::EEXIST, Errno::EACCES => e + # Symlink already exists or permission denied - zones disabled + rescue LoadError, Gem::MissingSpecError + # bubblezone gem not available - zones disabled end🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/claw/tui/model.rb` at line 25, Reorder the exceptions in the rescue clause in lib/claw/tui/model.rb to list the more specific Errno exceptions before the others (e.g., Errno::EEXIST, Errno::EACCES, then LoadError, Gem::MissingSpecError) to follow convention and improve readability, and add a brief comment inside the currently empty rescue block explaining why the exception is being ignored or how it’s handled (so the intent is clear to future readers).
7-28: 在运行时创建符号链接到 gem 目录存在潜在风险。这种动态修补
bubblezone原生扩展路径的方法有几个问题:
- 权限问题:写入 gem 安装目录可能需要 root/管理员权限
- 并发风险:多个进程同时运行可能导致竞态条件
- 污染 gem 目录:在 gem 目录中创建文件可能影响其他使用该 gem 的应用
建议考虑更安全的替代方案,例如在用户可写目录中处理,或者将此作为安装时的设置步骤而非运行时修补。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/claw/tui/model.rb` around lines 7 - 28, The runtime symlink creation to the gem installation (target/source/spec/versioned_dir) is risky; instead, detect the versioned native-extension dir (versioned_dir), and if present prepend it to $LOAD_PATH (or require the extension directly from that dir) and then require "bubblezone" (or "bubblezone/bubblezone"), rather than creating a filesystem symlink; ensure this change is implemented around the existing rescue block that handles require "bubblezone" (the begin/rescue and inner begin where spec, versioned_dir, target, source are used), and keep the existing exception handling for LoadError, Gem::MissingSpecError, Errno::EACCES, Errno::EEXIST while logging or skipping mouse zones when permission/concurrency prevents using the versioned dir.lib/claw/tui/chat_panel.rb (1)
17-18: 通过设置更详尽的注释来说明内部变量操作的必要性。当前代码使用
instance_variable_set直接修改@viewport_offset是为了修复TextArea高度变化后视口偏移陈旧的问题。这是针对 Bubbles 组件的已知限制(未提供公共 API 来重置视口状态)而采取的临时措施。建议将注释扩展为:
# Workaround: Recalculate viewport offset after height change because Bubbles::TextArea # does not provide a public API to reset viewport state. Without this, the viewport # position becomes stale, causing display bugs. This should be revisited if bubbles-ruby # adds a public viewport_offset setter or similar method. ta.instance_variable_set(:`@viewport_offset`, [ta.row - ta.height + 1, 0].max)这样可以帮助未来的维护者理解这不是任意的 hack,而是对已知问题的必要应对。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@lib/claw/tui/chat_panel.rb` around lines 17 - 18, Update the inline comment above the instance_variable_set call to clearly explain why we mutate the internal variable: state that this is a deliberate workaround for Bubbles::TextArea lacking a public API to reset viewport state, describe that without resetting `@viewport_offset` the viewport becomes stale after a height change (causing display bugs), and note this should be revisited if bubbles-ruby adds a public viewport_offset setter or equivalent; reference the ta.instance_variable_set(:`@viewport_offset`, [ta.row - ta.height + 1, 0].max) line and the TextArea/ta.row and ta.height usage in the comment so future maintainers understand it is intentional and temporary.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@lib/claw/tui/chat_panel.rb`:
- Around line 61-64: The call to Folding.fold_text in chat_panel.rb passes
unknown keyword args (zone: and fold_id:) that don't exist on Folding.fold_text
(defined as def self.fold_text(text, threshold: 10) in folding.rb), causing an
ArgumentError; fix by either removing the extra keywords from the call (change
folded = Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx) to folded
= Folding.fold_text(rendered.rstrip) and keep using folded[:folded] /
folded[:full] as before) or by updating the Folding.fold_text signature to
accept zone: and fold_id: (e.g., def self.fold_text(text, threshold: 10, zone:
nil, fold_id: nil)) and handle them inside the method; reference
Folding.fold_text, the call site in chat_panel.rb, and the zone / idx variables
when making the change.
In `@lib/claw/tui/model.rb`:
- Around line 221-230: Folding.fold_text currently only accepts (text,
threshold: 10) but callers (e.g., the code that calls
Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx)) pass keyword args
zone: and fold_id:, causing a mismatch; update the Folding.fold_text method
signature to accept those keywords (e.g., add zone: nil, fold_id: nil) and
ensure the implementation uses or safely ignores them (and maintain threshold:
default) so existing calls succeed without changing callers.
In `@lib/claw/version.rb`:
- Line 5: Update the BUILD constant in version.rb to reflect today's date and
reset the daily counter: change the BUILD constant value from "20260407-014" to
"20260408-001" (format YYYYMMDD-NNN, increment/reset per coding guideline) so
the BUILD constant matches the current change date.
---
Nitpick comments:
In `@lib/claw/tui/chat_panel.rb`:
- Around line 17-18: Update the inline comment above the instance_variable_set
call to clearly explain why we mutate the internal variable: state that this is
a deliberate workaround for Bubbles::TextArea lacking a public API to reset
viewport state, describe that without resetting `@viewport_offset` the viewport
becomes stale after a height change (causing display bugs), and note this should
be revisited if bubbles-ruby adds a public viewport_offset setter or equivalent;
reference the ta.instance_variable_set(:`@viewport_offset`, [ta.row - ta.height +
1, 0].max) line and the TextArea/ta.row and ta.height usage in the comment so
future maintainers understand it is intentional and temporary.
In `@lib/claw/tui/model.rb`:
- Line 25: Reorder the exceptions in the rescue clause in lib/claw/tui/model.rb
to list the more specific Errno exceptions before the others (e.g.,
Errno::EEXIST, Errno::EACCES, then LoadError, Gem::MissingSpecError) to follow
convention and improve readability, and add a brief comment inside the currently
empty rescue block explaining why the exception is being ignored or how it’s
handled (so the intent is clear to future readers).
- Around line 7-28: The runtime symlink creation to the gem installation
(target/source/spec/versioned_dir) is risky; instead, detect the versioned
native-extension dir (versioned_dir), and if present prepend it to $LOAD_PATH
(or require the extension directly from that dir) and then require "bubblezone"
(or "bubblezone/bubblezone"), rather than creating a filesystem symlink; ensure
this change is implemented around the existing rescue block that handles require
"bubblezone" (the begin/rescue and inner begin where spec, versioned_dir,
target, source are used), and keep the existing exception handling for
LoadError, Gem::MissingSpecError, Errno::EACCES, Errno::EEXIST while logging or
skipping mouse zones when permission/concurrency prevents using the versioned
dir.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 31f86579-8514-48bb-a4e1-fd5c62f041fd
📒 Files selected for processing (5)
lib/claw/tui/chat_panel.rblib/claw/tui/input_handler.rblib/claw/tui/model.rblib/claw/version.rbspec/claw/tui/model_spec.rb
| folded = Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx) | ||
| if folded[:folded] | ||
| msg[:folded_full] = folded[:full] | ||
| end |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 验证 Folding.fold_text 方法签名
ast-grep --pattern $'def self.fold_text($$$) {
$$$
}'
# 搜索完整的 fold_text 方法定义
rg -n "def self\.fold_text" --type ruby -A 5Repository: twokidsCarl/ruby-claw
Length of output: 439
🏁 Script executed:
# 查看完整的 folding.rb 文件
cat lib/claw/tui/folding.rb
# 查看 chat_panel.rb 的相关行
sed -n '55,70p' lib/claw/tui/chat_panel.rbRepository: twokidsCarl/ruby-claw
Length of output: 4104
🏁 Script executed:
# 搜索所有 fold_text 定义
rg -n "def.*fold_text" lib/claw/tui/ -A 3
# 查看 chat_panel.rb 第55-70行的完整上下文
sed -n '55,70p' lib/claw/tui/chat_panel.rb
# 确认这是否是实际存在的问题
rg -n "fold_text.*zone:" lib/claw/tui/Repository: twokidsCarl/ruby-claw
Length of output: 1131
Folding.fold_text 方法签名不匹配 — 将导致运行时 ArgumentError。
根据 lib/claw/tui/folding.rb:15,Folding.fold_text 方法签名为:
def self.fold_text(text, threshold: 10)但在 lib/claw/tui/chat_panel.rb:61 处调用时传递了 zone: 和 fold_id: 参数,这些参数在方法定义中不存在:
folded = Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx)会导致运行时 ArgumentError: unknown keywords: zone, fold_id。请移除这两个参数或更新 fold_text 方法签名以接受它们。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/claw/tui/chat_panel.rb` around lines 61 - 64, The call to
Folding.fold_text in chat_panel.rb passes unknown keyword args (zone: and
fold_id:) that don't exist on Folding.fold_text (defined as def
self.fold_text(text, threshold: 10) in folding.rb), causing an ArgumentError;
fix by either removing the extra keywords from the call (change folded =
Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx) to folded =
Folding.fold_text(rendered.rstrip) and keep using folded[:folded] /
folded[:full] as before) or by updating the Folding.fold_text signature to
accept zone: and fold_id: (e.g., def self.fold_text(text, threshold: 10, zone:
nil, fold_id: nil)) and handle them inside the method; reference
Folding.fold_text, the call site in chat_panel.rb, and the zone / idx variables
when making the change.
| when /\Afold_(\d+)\z/ | ||
| idx = $1.to_i | ||
| if idx < @chat_history.size | ||
| m = @chat_history[idx] | ||
| if m[:folded_full] | ||
| m[:content] = m[:folded_full] | ||
| m.delete(:folded_full) | ||
| end | ||
| end | ||
| end |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 搜索 Folding 模块的完整定义
rg -n "module Folding" --type ruby -A 50Repository: twokidsCarl/ruby-claw
Length of output: 3431
🏁 Script executed:
# Search for all calls to Folding.fold_text
rg -n "fold_text" --type ruby -B 2 -A 2Repository: twokidsCarl/ruby-claw
Length of output: 814
🏁 Script executed:
# Check chat_panel.rb around lines 61-64
fd "chat_panel.rb" --type f | head -1 | xargs wc -lRepository: twokidsCarl/ruby-claw
Length of output: 94
🏁 Script executed:
# Once we know file size, examine chat_panel.rb lines around 61-64
fd "chat_panel.rb" --type f | head -1 | xargs cat -n | sed -n '55,75p'Repository: twokidsCarl/ruby-claw
Length of output: 1152
🏁 Script executed:
# Also check model.rb around lines 221-230 to see full context
fd "model.rb" --path "*/tui/*" --type f | head -1 | xargs cat -n | sed -n '215,240p'Repository: twokidsCarl/ruby-claw
Length of output: 280
🏁 Script executed:
# Get model.rb file and show lines around 221-230
rg -n "fold_" lib/claw/tui/model.rb -B 3 -A 8 | head -50Repository: twokidsCarl/ruby-claw
Length of output: 473
🏁 Script executed:
# Check if there are multiple fold_text method definitions
rg -n "def.*fold_text" --type rubyRepository: twokidsCarl/ruby-claw
Length of output: 137
Folding.fold_text 方法签名与调用不匹配。
chat_panel.rb:61 调用 Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx) 传递了 zone: 和 fold_id: 参数,但 folding.rb:15 中的方法定义只接受 text 和 threshold: 10。这将导致运行时错误。
需要更新 Folding.fold_text 的方法签名以支持这些参数,或者修改调用代码以移除这些参数。
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/claw/tui/model.rb` around lines 221 - 230, Folding.fold_text currently
only accepts (text, threshold: 10) but callers (e.g., the code that calls
Folding.fold_text(rendered.rstrip, zone: zone, fold_id: idx)) pass keyword args
zone: and fold_id:, causing a mismatch; update the Folding.fold_text method
signature to accept those keywords (e.g., add zone: nil, fold_id: nil) and
ensure the implementation uses or safely ignores them (and maintain threshold:
default) so existing calls succeed without changing callers.
| module Claw | ||
| VERSION = "0.2.2" | ||
| BUILD = "20260407-011" | ||
| BUILD = "20260407-014" |
There was a problem hiding this comment.
BUILD 日期已过时。
根据编码指南,BUILD 常量应使用 YYYYMMDD-NNN 格式,其中日期应为代码更改时的当前日期。当前 BUILD 为 20260407-014(4月7日),但今天是4月8日。应更新为 20260408-001。
🔧 建议修复
- BUILD = "20260407-014"
+ BUILD = "20260408-001"根据编码指南:Increment the BUILD constant in lib/claw/version.rb every time you change code, using format YYYYMMDD-NNN where NNN is a sequential number starting at 001 each day
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| BUILD = "20260407-014" | |
| BUILD = "20260408-001" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@lib/claw/version.rb` at line 5, Update the BUILD constant in version.rb to
reflect today's date and reset the daily counter: change the BUILD constant
value from "20260407-014" to "20260408-001" (format YYYYMMDD-NNN,
increment/reset per coding guideline) so the BUILD constant matches the current
change date.
Summary
chat_heightcalculation)private_methods(false)+ tracked REPL definitions in tab completionTest plan
def abc→ enter → line 1 visible/helpall lines aligned🤖 Generated with Claude Code
Summary by CodeRabbit
发布说明
新功能
改进
测试