feat(kebab-tui): p9-fb-13 cheatsheet popup (F1) #86

Merged
altair823 merged 2 commits from feat/p9-fb-13-cheatsheet into main 2026-05-03 08:32:58 +00:00
Owner

요약

도그푸딩 item 11 — vim 비익숙 사용자도 TUI 조작 가능. F1 으로 cheatsheet modal popup 띄움 — 현재 pane 의 키 매핑 + global 토글 한 자리.

변경

  • cheatsheet::render_cheatsheet (new) — 70%/60% centered modal, 5 sections (Global/Library/Search/Ask/Inspect) + 현재 focused pane footer
  • App.cheatsheet_visible: bool + pub fn cheatsheet_visible() getter
  • cheatsheet_intercept in run loop — F1 toggle, Esc close-when-visible, 그 외 fall-through. modifier-bearing 무시. mode_intercept 보다 먼저 dispatch.
  • render_root 가 error overlay 위에 cheatsheet overlay

HOTFIXES (?F1 rebind)

spec 의 ? 가 Library 의 Char('?') → SwitchPane(Ask) 와 충돌. F1 (universal help) 로 rebind. verb hint line 재구성도 deferral (기존 footer 가 동일 역할). spec status plannedin_progress (NOT completed).

테스트

  • 5 신규 unit (F1 toggle, Esc visible/hidden, modifier 무시, fall-through, render content)
  • 기존 113 + 신규 5 = 118 TUI 테스트 통과
  • cargo test --workspace --no-fail-fast -j 1 exit 0
  • cargo clippy --workspace --all-targets -- -D warnings clean

문서

  • README kebab tui 행: F1 cheatsheet 안내
  • HANDOFF entry
  • HOTFIXES rebind rationale + verb hint deferral
  • spec status planned → in_progress
## 요약 도그푸딩 item 11 — vim 비익숙 사용자도 TUI 조작 가능. F1 으로 cheatsheet modal popup 띄움 — 현재 pane 의 키 매핑 + global 토글 한 자리. ## 변경 - **`cheatsheet::render_cheatsheet`** (new) — 70%/60% centered modal, 5 sections (Global/Library/Search/Ask/Inspect) + 현재 focused pane footer - **`App.cheatsheet_visible: bool`** + `pub fn cheatsheet_visible()` getter - **`cheatsheet_intercept`** in run loop — F1 toggle, Esc close-when-visible, 그 외 fall-through. modifier-bearing 무시. `mode_intercept` 보다 먼저 dispatch. - **render_root** 가 error overlay 위에 cheatsheet overlay ## HOTFIXES (`?` → `F1` rebind) spec 의 `?` 가 Library 의 `Char('?') → SwitchPane(Ask)` 와 충돌. F1 (universal help) 로 rebind. verb hint line 재구성도 deferral (기존 footer 가 동일 역할). spec status `planned` → `in_progress` (NOT `completed`). ## 테스트 - 5 신규 unit (F1 toggle, Esc visible/hidden, modifier 무시, fall-through, render content) - 기존 113 + 신규 5 = 118 TUI 테스트 통과 - `cargo test --workspace --no-fail-fast -j 1` exit 0 - `cargo clippy --workspace --all-targets -- -D warnings` clean ## 문서 - README `kebab tui` 행: F1 cheatsheet 안내 - HANDOFF entry - HOTFIXES rebind rationale + verb hint deferral - spec status planned → in_progress
altair823 added 1 commit 2026-05-03 08:28:33 +00:00
도그푸딩 item 11 — vim 비익숙 사용자도 TUI 조작 가능. F1 으로 cheatsheet
modal popup, 현재 pane 의 키 매핑 + global 토글 (i/Esc/F1) 한 자리.

## 핵심 변경

- **`kebab-tui::cheatsheet::render_cheatsheet(f, area, app)`** 신규 —
  70%/60% centered modal. 5 sections (Global / Library / Search / Ask
  / Inspect) 각 pane 의 모든 키 + 동사구 설명. footer 에 현재 focused
  pane 명시. theme.style(Role::Heading/CitationMarker/Hint) 으로 색
  계층 (header bold, key cyan-marker, body plain, hint dim).
- **`App.cheatsheet_visible: bool`** field + `pub fn cheatsheet_
  visible() -> bool` getter (read-only — set/unset 은 F1 intercept
  invariant).
- **`cheatsheet_intercept(app, key)`** in run.rs:
  - F1 → toggle (open ↔ close), consumed
  - Esc 가 visible 일 때 → close, consumed (mode_intercept 가 같은
    Esc 를 mode flip 으로 해석하지 않도록 cheatsheet_intercept 가
    먼저 dispatch)
  - 그 외 키 → fall-through (popup 열린 채 navigation 가능)
  - modifier-bearing F1 (Ctrl-F1 등) 무시
- **run loop 통합**: `cheatsheet_intercept` → `mode_intercept` →
  pane dispatch 순. render_root 가 error overlay 위에 cheatsheet
  overlay (사용자가 error 도중에도 도움말 소환 가능).

## HOTFIXES (`?` → `F1` rebind)

spec 은 `?` 를 trigger 로 명시했지만 Library 가 이미 `Char('?')` 를
quick-Ask binding 으로 사용 중 (handle_key_library line 305). spec 의
`?` 채택 = 기존 binding 깨거나 mode-aware special case 추가. 후자는
mode machine 에 더 많은 분기 추가하므로 회피.

**Live binding**: `F1` (universal help key, no collision).

**Per-pane verb hint line**: spec 의 verb-form hint 재구성도 본 PR
에서 deferral. 기존 `render_footer` 의 pane-별 힌트 문자열이 동일 UX
역할 — 후속 PR 에서 mode-aware verb fragments 로 split 가능.

spec status `planned` → `in_progress` (NOT `completed` — verb hint
deferral 명시).

## 테스트

- 5 신규 integration unit (`tests/cheatsheet.rs`):
  - F1 toggles visibility (open ↔ close, consumed 양쪽)
  - Esc closes when visible / falls through when hidden
  - modifier-bearing F1 (Ctrl-F1, Alt-F1) 무시
  - arbitrary keys (j, /, q, Enter) fall through 하면서 popup 열린 채
  - render_cheatsheet 가 모든 section header (Global/Library/Search/
    Ask/Inspect) + global toggle (F1, Esc) 출력
- 기존 113 TUI 테스트 + 신규 5 = 118 통과
- `cargo test --workspace --no-fail-fast -j 1` exit 0
- `cargo clippy --workspace --all-targets -- -D warnings` clean

## 문서

- README `kebab tui` 행: F1 cheatsheet popup 안내
- HANDOFF: 2026-05-03 entry
- HOTFIXES: ?→F1 rebind rationale + verb hint deferral
- spec status `planned` → `in_progress`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 requested changes 2026-05-03 08:29:30 +00:00
Dismissed
claude-reviewer-01 left a comment
Member

회차 1 — F1 trigger + Esc-close + render content + modifier filter 모두 깔끔. 5 신규 unit (toggle / esc-close-or-fall / modifier-ignore / arbitrary-fall-through / render content) 도 contract 핵심 cover. HOTFIXES 의 ?→F1 rebind 사유 명확.

actionable nit 1 건 — cheatsheet_intercept doc 에 'Esc-when-visible 는 mode flip 도 안 함 (single-effect per keystroke)' 트레이드오프 + cheatsheet 본문이 hard-coded string 이라 후속에서 stale 가능 maintenance TODO.

회차 1 — F1 trigger + Esc-close + render content + modifier filter 모두 깔끔. 5 신규 unit (toggle / esc-close-or-fall / modifier-ignore / arbitrary-fall-through / render content) 도 contract 핵심 cover. HOTFIXES 의 ?→F1 rebind 사유 명확. actionable nit 1 건 — cheatsheet_intercept doc 에 'Esc-when-visible 는 mode flip 도 안 함 (single-effect per keystroke)' 트레이드오프 + cheatsheet 본문이 hard-coded string 이라 후속에서 stale 가능 maintenance TODO.
@@ -377,0 +402,4 @@
/// instead of also flipping mode.
/// - Any other key while visible → fall through (so the key reaches
/// the active pane normally — useful if the user wants to keep
/// the popup open and still navigate). The popup auto-closes

의도 명확화 doc nit: cheatsheet 가 visible 인 상태에서 사용자가 INSERT 모드면, Esc 가 cheatsheet 만 닫고 mode flip 은 안 합니다 (cheatsheet_intercept 가 mode_intercept 보다 먼저 dispatch). 사용자 expected: "Esc 누르면 cheatsheet 닫히고 mode 도 Normal 됨" 가능성.

현재 동작 (단일 키스트로크 = 단일 효과) 도 합리적이지만, 사용자가 두 번 Esc 를 누르면 닫고 + mode flip 이 됨. 의도된 트레이드오프임을 doc 에 한 줄 추가하면 후속 사용자 피드백 시 reasoning 빠르게 트레이스 가능:

/// - **Esc while visible** → close. Returning `true` here means
///   the global `mode_intercept` does NOT also see the Esc, so the
///   user's "close cheatsheet" action stays a single keystroke
///   instead of also flipping mode. **Trade-off**: in Insert mode,
///   user needs a second Esc to flip to Normal — single-effect
///   per keystroke wins over compound actions.

또 cheatsheet 본문이 hard-coded string table 이라 후속에서 키 binding 바뀌면 cheatsheet 가 stale 가능 — 별 항목으로 doc TODO 추가:

//! **Maintenance**: the `push_section(...)` calls hold every key
//! binding as a literal string — a future PR that changes a
//! binding (e.g. swap `r` → `R`) MUST update the matching entry
//! here. No automated link from `handle_key_*` to the cheatsheet.
**의도 명확화 doc nit**: cheatsheet 가 visible 인 상태에서 사용자가 INSERT 모드면, `Esc` 가 cheatsheet 만 닫고 mode flip 은 안 합니다 (`cheatsheet_intercept` 가 mode_intercept 보다 먼저 dispatch). 사용자 expected: "Esc 누르면 cheatsheet 닫히고 mode 도 Normal 됨" 가능성. 현재 동작 (단일 키스트로크 = 단일 효과) 도 합리적이지만, 사용자가 두 번 Esc 를 누르면 닫고 + mode flip 이 됨. 의도된 트레이드오프임을 doc 에 한 줄 추가하면 후속 사용자 피드백 시 reasoning 빠르게 트레이스 가능: ``` /// - **Esc while visible** → close. Returning `true` here means /// the global `mode_intercept` does NOT also see the Esc, so the /// user's "close cheatsheet" action stays a single keystroke /// instead of also flipping mode. **Trade-off**: in Insert mode, /// user needs a second Esc to flip to Normal — single-effect /// per keystroke wins over compound actions. ``` 또 cheatsheet 본문이 hard-coded string table 이라 후속에서 키 binding 바뀌면 cheatsheet 가 stale 가능 — 별 항목으로 doc TODO 추가: ``` //! **Maintenance**: the `push_section(...)` calls hold every key //! binding as a literal string — a future PR that changes a //! binding (e.g. swap `r` → `R`) MUST update the matching entry //! here. No automated link from `handle_key_*` to the cheatsheet. ```
altair823 added 1 commit 2026-05-03 08:32:42 +00:00
- `cheatsheet_intercept` doc 에 trade-off 명시: Esc-when-visible 가
  cheatsheet 만 닫고 mode flip 안 함 (single-effect-per-keystroke).
  Insert 모드 사용자는 두 번째 Esc 로 Normal 전환.
- `cheatsheet.rs` 모듈 doc 에 maintenance 경고 추가: push_section()
  이 hard-coded string 이라 binding 변경 시 cheatsheet 동기화 수동.
  자동 link 없음 — future PR 가 키 바꾸면 cheatsheet 도 갱신 필수.

118 TUI 테스트 통과 + clippy clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
claude-reviewer-01 approved these changes 2026-05-03 08:32:53 +00:00
claude-reviewer-01 left a comment
Member

회차 2 — nit 1 건 깔끔히 반영.

  • cheatsheet_intercept doc: Esc-while-visible 의 single-effect 트레이드오프 (Insert 사용자는 두 번째 Esc 로 mode flip) 명시
  • cheatsheet.rs 모듈 doc: hard-coded string maintenance 경고 추가

추가 지적 없음. 머지 OK.

회차 2 — nit 1 건 깔끔히 반영. - cheatsheet_intercept doc: Esc-while-visible 의 single-effect 트레이드오프 (Insert 사용자는 두 번째 Esc 로 mode flip) 명시 - cheatsheet.rs 모듈 doc: hard-coded string maintenance 경고 추가 추가 지적 없음. 머지 OK.
altair823 merged commit 27f4c76a11 into main 2026-05-03 08:32:58 +00:00
altair823 deleted branch feat/p9-fb-13-cheatsheet 2026-05-03 08:32:59 +00:00
Sign in to join this conversation.
No Reviewers
No Label
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: altair823-org/kebab#86