Files
kebab/tasks/p9/p9-fb-22-tui-cursor-and-autoscroll.md
altair823 a299c49ad2 review(p9-fb-22): 회차 2 nit 반영 — 카운트 38→39 + doc comment 2-arm
회차 2 review (PR #96 회차 2) 의 2 건 cosmetic nit 모두 수렴.

- `tasks/HOTFIXES.md`, `tasks/p9/p9-fb-22-tui-cursor-and-autoscroll.md`:
  \"기존 38 개\" → \"기존 39 개 (input.rs unit 18 + tests/ask.rs 21)\"
  로 정확 카운트 + 출처 명시.
- `crates/kebab-tui/src/library.rs`: `active_buf_mut` doc comment 의
  \"3-line dispatch\" → \"2-arm dispatch\" (실제 dispatch 가 2 arm 이라
  가장 정확한 표현).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-04 15:36:49 +00:00

5.0 KiB

phase, component, task_id, title, status, depends_on, unblocks, contract_source, contract_sections, source_feedback
phase component task_id title status depends_on unblocks contract_source contract_sections source_feedback
P9 kebab-tui p9-fb-22 Mid-string cursor editing + Ask follow-tail auto-scroll (post-merge dogfooding) completed
p9-fb-10
p9-3
../../docs/superpowers/specs/2026-04-27-kebab-final-form-design.md
§1 UX
§10 UX
사용자 도그푸딩 2026-05-04 — Gitea

p9-fb-22 — InputBuffer cursor editing + Ask follow-tail

Goal

  • 모든 input pane (Ask / Search / Library filter overlay) 에서 화살표 / Home / End / Delete 로 mid-string 커서 편집 가능.
  • Ask 트랜스크립트가 새 응답 도착 시 자동으로 viewport bottom 을 따라감 (auto-tail). 사용자가 위로 스크롤하면 freeze, 명시적 키 (Shift-G) 로 다시 활성화.

Background

p9-fb-10InputBuffer 는 의도적으로 append-only — cursor_col == display_width(content) invariant 가 항상 성립. 좋은 결정이지만 mid-string 편집 (한글 한 글자 잘못 쳤을 때 backspace 로 다 지우지 않고 화살표로 그 자리만 고치기) 가 불가.

p9-3 의 Ask 트랜스크립트는 Paragraph::scroll((s.scroll, 0)) 의 offset 을 위에서부터 카운트. 새 답변 도착 시 s.scroll = 0 으로 리셋 — viewport 가 위쪽 고정. 트랜스크립트가 길어지면 새 응답이 시야 밖으로 밀림. 사용자는 매번 j 로 직접 스크롤해야 함.

Allowed dependencies

  • 기존 kebab-tui 의존성.
  • ratatuiunstable-rendered-line-info feature — Paragraph::line_count(width) 사용을 위해 활성화. ratatui 0.28 에 pin 된 동안 안정.

Public surface

신규 InputBuffer 메서드: move_left, move_right, move_home, move_end, delete_after. 기존 push_char / pop_char 는 cursor 위치에서 동작하도록 의미 변경 (cursor 가 끝에 있을 때 기존 동작과 동일).

신규 AskState 필드: follow_tail: bool (default true).

Behavior contract

InputBuffer

  • cursor_byte 가 새 source of truth (UTF-8 char boundary). cursor_col() 는 prefix slice 의 unicode-width 합으로 derive.
  • push_char(ch): content.insert(cursor_byte, ch)cursor_byte += ch.len_utf8(). cursor 가 끝에 있을 때 기존 append 동작과 동일.
  • pop_char(): cursor 직전 char 제거. cursor 가 시작에 있을 때 None 반환.
  • delete_after(): cursor 위치 char 제거 (cursor 그대로). 끝에서는 None.
  • move_left() / move_right(): char-boundary 단위 이동. bool 반환 (이동 성공 여부).
  • move_home() / move_end(): 양 끝점 점프.
  • backwards-compat: cursor 가 끝일 때 모든 메서드 동작이 p9-fb-10 spec 과 동일. 30+ 기존 테스트 변경 없이 통과.

Ask follow-tail

  • AskState::default()follow_tail = true 로 초기화 (수동 Default impl 추가 — derive(Default)false 가 됨).
  • render_answerfollow_tail 동안 매 프레임 Paragraph::line_count(inner.width) 로 wrapped row 수 계산, scroll = line_count - inner_height 로 pin. wrap-aware 이므로 viewport 너비 변경 시에도 정확히 bottom.
  • j (scroll down): follow_tail = false 로 disengage. s.scroll += 1.
  • k (scroll up): follow_tail = false. s.scroll -= 1.
  • Shift-G: follow_tail = true + s.scroll = 0. Normal 모드에서만.
  • 새 submission, Ctrl-Lfollow_tail = true 재설정.

Pane key handler 추가

  • Ask: Left / Right / Home / End / Delete mode 무관 (Mode::Insert / Normal 양쪽). Shift-G Normal 한정.
  • Search: 동일 5 key. Delete 만 input_dirty_at reset (cursor 이동 ≠ 쿼리 변경 → debounce timer 유지).
  • Library filter overlay: 동일 5 key, 활성 field (Tags / Lang) 의 buffer 에 적용.

Tests

  • 11 신규 InputBuffer unit (move_left/right ASCII/Hangul, home/end, mid-string insert, backspace at cursor + at home no-op, delete_after at cursor + at end no-op, mixed-width cursor invariant, take 후 cursor reset).
  • 10 신규 Ask integration (Left/Right/Home/End/Delete on Ask input, Hangul left arrow, follow_tail default, k disengages, Shift-G re-engages, Ctrl-L resets, follow-tail rendering bottom of long transcript).
  • 기존 39 개 테스트 (input.rs unit 18 + tests/ask.rs 21) 는 그대로 통과 (cursor 가 끝일 때 backwards-compat).

Risks / notes

  • ratatui::Paragraph::line_count 가 unstable feature flag 뒤에 있음 — ratatui 0.28 → 0.29 bump 시 stable surface 여부 재확인 필요. unstable surface 가 사라지면 manual estimator (per-Line ceil(display_cols / inner_width)) 로 fallback 가능.
  • cheatsheet popup body 가 Search +3 row, Ask +4 row 늘어남. p9-fb-21 의 deferred 한계 (75% height 안에 Inspect section 잘림 가능) 가 더 빡빡해짐 — 후속 task 로 popup scroll 또는 multi-column layout 고려 필요.

Live deviations 반영 위치: tasks/HOTFIXES.md 2026-05-04 — p9-fb-22 항목.