feat(kebab-tui): p9-fb-12 partial — Mode enum + global i/Esc + auto switch + status label #84
Reference in New Issue
Block a user
Delete Branch "feat/p9-fb-12-mode"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
요약
도그푸딩 item 10 — vim-style NORMAL/INSERT mode 도입. 절반 ship: 사용자 가시 signal (mode label + auto flip + i/Esc global) 만, dispatch 의 input-empty heuristic 제거는 follow-up PR.
변경
Mode { Normal, Insert }+auto_for(pane)+label()+Default = NormalApp.mode: Modefieldmode_intercept— Insert+Esc → Normal (어디서나), Normal+i → Insert (Library/Inspect/Jobs 만; Search/Ask 는 자동 Insert 라 i 가 typed char)Mode::auto_for(p)자동 flipDeferred → follow-up PR (HOTFIXES entry)
spec 의 "is_typing_mod (search) + input-empty heuristic (ask) 제거" 는 별 PR. 회귀 surface 좁게 유지. spec status
in_progress유지 (NOTcompleted).테스트
cargo test --workspace --no-fail-fast -j 1exit 0cargo clippy --workspace --all-targets -- -D warningsclean문서
kebab tui행: vim mode + auto NORMAL/INSERT도그푸딩 item 10 — vim 비익숙 사용자도 \"지금 키가 입력 vs 명령\" 명확히 구분 가능. 절반 ship: 사용자 가시 signal (mode label + auto flip + i/Esc global) 만 land, 키 dispatch 의 input-empty heuristic 제거는 follow-up. ## 핵심 변경 - **`kebab_tui::Mode { Normal, Insert }`** enum + `Default = Normal`. - `Mode::label()` → `"-- NORMAL --"` / `"-- INSERT --"` (status bar 문자열, 테스트로 핀). - `Mode::auto_for(pane)` → Library/Inspect/Jobs = Normal, Search/Ask = Insert. pane 전환 시 자동 적용. - **`App.mode: Mode`** field. `App::new` 가 starting pane 의 auto mode 로 init. - **run loop `mode_intercept(app, key)`** — pane dispatch 전에 호출: - Insert + `Esc` → Normal (어디서나, modifier 없음) - Normal + `i` (Library/Inspect/Jobs 만) → Insert - Search/Ask 의 `i` 는 fall-through (이미 Insert 라 typed char) - 그 외 fall-through - **pane 전환 시** `app.mode = Mode::auto_for(p)` 자동 flip — 사용자가 Tab 으로 Search 가면 자동으로 Insert. - **status bar (header)** 에 mode label colored — Insert = Role:: Success (green), Normal = Role::Heading (cyan + bold). a11y: 색은 reinforcement, 글자가 authoritative signal. ## Deferred (HOTFIXES entry 추가) spec p9-fb-12 의 \"기존 P9-3 ask 의 e/j/k input-empty heuristic 제거 — mode 로 명확히\" 는 별 PR 로. 현재 dispatch 는 여전히: - search.rs 의 `is_typing_mod` (SHIFT 만 typing 으로, CTRL/ALT 는 chord) - ask.rs 의 input.is_empty() 가 e/j/k 를 navigation 으로 분기 테스트가 heuristic 에 의존해 있어, 회귀 surface 좁게 유지하려고 splitting. spec status `in_progress` 유지 (not `completed`) — follow-up PR 가 heuristic 제거 + 완전 mode-authoritative 후 `completed` flip. ## 테스트 - 신규 3 unit (`Mode::auto_for` 모든 pane, label literals 핀, default = Normal) - 기존 98 TUI 테스트 모두 통과 (heuristic 그대로라 회귀 0) - workspace 전체 `cargo test --workspace --no-fail-fast -j 1` exit 0 - `cargo clippy --workspace --all-targets -- -D warnings` clean ## 문서 - README `kebab tui` 행: vim-style mode + auto NORMAL/INSERT + i/Esc 안내 - HANDOFF entry (partial-ship 명시) - HOTFIXES entry (heuristic 제거 deferral 사유) - spec status planned → in_progress (NOT completed) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>회차 1 — partial-ship 전략 합리적 (사용자 가시 signal 만 ship, heuristic 제거는 follow-up). HOTFIXES + spec status in_progress 유지로 deferred 부분 명시 깔끔. mode_intercept 의 modifier-aware filter (Ctrl+Esc 무시 등) 도 견고.
actionable nit 2 건 — (a) mode_intercept 동작 회귀 테스트 부재 (Mode enum 만 테스트, intercept 자체는 pin 안 됨), (b) auto_for 가 사용자 manual flip 을 pane 전환 시 덮어쓰는 동작에 doc 부재 — 의도된 트레이드오프임을 명시.
신규 unit 테스트 3 건은
Modeenum 자체의 invariant 만 cover (auto_for / label / default).mode_intercept의 실제 동작 (Insert+Esc → Normal, Normal+i → Insert in Library only, Search/Ask 에서 i fall-through, Ctrl+Esc 무시 등) 회귀 테스트가 없습니다.현재 dispatch 가 run loop 안에 있어 직접 테스트 어렵지만,
mode_intercept를pub(crate)로 노출하고tests/mode.rs에서 KeyEvent 직접 만들어 검증 가능. 5개 정도 (Esc-from-Insert, i-on-Library, i-on-Search-falls-through, Ctrl+Esc 무시, Esc-from-Normal noop) 면 spec 의 가시 contract pin.선택:
pub(crate) fn mode_intercept+tests/mode.rs신규.@@ -145,1 +156,4 @@app.focus = p;// p9-fb-12: auto-flip mode on switch.// Library/Inspect/Jobs → Normal,// Search/Ask → Insert. User can still의도된 동작이지만 사용자 surprise 가능: pane 전환 시
Mode::auto_for(p)가 사용자가 방금Esc로 manual flip 한 mode 를 덮어씁니다. 시나리오:Esc→ Normal (user 의도: navigation)사용자 입장에서 "Esc 누르면 그 모드 sticky" 가 기대일 수 있습니다. v1 으로 자동 flip 이 합리적이지만 (Search/Ask 의 주 use case 가 typing), doc 으로 명시해두면 후속 사용자 피드백 시 의도된 트레이드오프임을 보여줄 수 있습니다.
제안:
Mode::auto_fordoc 또는 run loop pane-switch 분기 주석에:- `mode_intercept` 를 `pub` 로 노출 + `pub use run::mode_intercept` 로 lib.rs export. 신규 `tests/mode.rs` 6 integration unit: - Esc-from-Insert flips to Normal on every pane (consumed) - Esc-from-Normal falls through (pane handler 가 처리 — Library 의 quit signal 등 보존) - i-from-Normal on Library/Inspect/Jobs flips to Insert (consumed) - i-on-Search/Ask falls through (이미 Insert, i 가 typed char) - Ctrl/Alt modifier 는 intercept 안 함 (chord 가능) - Shift+Esc 는 toggle 됨 (modifier filter 가 SHIFT allow), Shift+I (capital) 는 fall-through (lowercase i 만 toggle 키) - `Mode::auto_for` doc 에 \"auto-flip overrides user manual mode on pane switch\" 명시 — 의도된 트레이드오프 (typing 이 Search/Ask 의 dominant case). sticky-per-pane 은 future task. 워크스페이스 clippy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>회차 2 — nit 2 건 깔끔히 반영.
추가 지적 없음. 머지 OK.