review(p9-1): 회차 1 지적 반영

- p9-2/3/4 미머지 시점에 / ? Enter 키로 focus 가 Search/Ask/Inspect 로
  옮겨가면 헤더만 바뀌고 본문은 Library 그대로 + 키 매핑도 Library 라
  사용자에게 거짓말. footer hint 가 \"Search pane not yet implemented
  (lands with p9-2) — q to return\" 로 전환된다. 새 stub 핸들러
  `handle_key_unimplemented_pane` 가 q / Esc 만 받아 Library 로 복귀,
  나머지 키는 no-op (이전 구현은 handle_key_library 로 위임해서 focus
  와 다른 pane state 가 mutate 되던 절뚝거림 차단).
- `format_doc_row` 의 `{title:<title_w$}` 가 std::fmt 의 named-arg
  width specifier — 미래 reader 가 같은 패턴 보고 헷갈리지 않도록
  doc 링크 한 줄 코멘트 추가.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-02 13:31:19 +00:00
parent 43ff4048e8
commit 63c6d007ae
2 changed files with 36 additions and 5 deletions

View File

@@ -194,6 +194,10 @@ pub(crate) fn format_doc_row(d: &DocSummary, title_w: usize) -> String {
.format(&time::format_description::well_known::Rfc3339)
.unwrap_or_else(|_| "?".to_string());
let updated_short = updated.split('T').next().unwrap_or("?");
// `<width$>` is std::fmt's named-arg width form (`title_w` is the
// named arg below; `$` says "use it as the padding width"). See
// https://doc.rust-lang.org/std/fmt/#width §"Width via named
// parameters".
format!(
"{title:<title_w$} {tags:<12} {updated_short:<10} {chunk_count}",
title = title,

View File

@@ -41,11 +41,12 @@ pub(crate) fn run_loop(app: &mut App) -> Result<()> {
let outcome = match app.focus {
Pane::Library => handle_key_library(app, key),
// p9-2/3/4 plug their handlers here as their
// crates land. Until then, any non-Library
// pane behaves like Library (we never switch
// to them at present).
// crates land. Until then, the non-Library
// panes accept only `q` / `Esc` to return —
// anything else is a no-op. The footer hint
// tells the user the pane is unimplemented.
Pane::Search | Pane::Ask | Pane::Inspect | Pane::Jobs => {
handle_key_library(app, key)
handle_key_unimplemented_pane(app, key)
}
};
match outcome {
@@ -67,6 +68,26 @@ pub(crate) fn run_loop(app: &mut App) -> Result<()> {
Ok(())
}
/// Stub key handler for panes whose authoring task has not landed
/// yet. `q` / `Esc` returns to Library; everything else is a no-op.
/// Does NOT delegate to `handle_key_library` because that would let
/// `j` / `k` / `f` mutate Library state while focus says otherwise —
/// confusing UX.
fn handle_key_unimplemented_pane(
app: &mut App,
key: crossterm::event::KeyEvent,
) -> KeyOutcome {
use crossterm::event::KeyCode;
if app.error_overlay.is_some() {
app.error_overlay = None;
return KeyOutcome::Continue;
}
match key.code {
KeyCode::Char('q') | KeyCode::Esc => KeyOutcome::SwitchPane(Pane::Library),
_ => KeyOutcome::Continue,
}
}
fn render_root(f: &mut Frame, app: &App) {
let outer = Layout::default()
.direction(Direction::Vertical)
@@ -110,6 +131,9 @@ fn render_header(f: &mut Frame, area: Rect, app: &App) {
}
fn render_footer(f: &mut Frame, area: Rect, app: &App) {
// p9-2/3/4 가 머지되기 전에는 SwitchPane(Search/Ask/Inspect) 가
// focus 만 바꾸고 본문은 Library 가 그려지는 절뚝거림이 사용자에게
// 보임. footer 에서 \"미구현\" 을 명시해 거짓말 안 함.
let hints = match app.focus {
Pane::Library => {
if app.library.inner.filter_edit.is_some() {
@@ -118,7 +142,10 @@ fn render_footer(f: &mut Frame, area: Rect, app: &App) {
"j/k=move gg=top G=bottom f=filter /=search ?=ask Enter=inspect q=quit"
}
}
_ => "q=quit",
Pane::Search => "Search pane not yet implemented (lands with p9-2) — q to return",
Pane::Ask => "Ask pane not yet implemented (lands with p9-3) — q to return",
Pane::Inspect => "Inspect pane not yet implemented (lands with p9-4) — q to return",
Pane::Jobs => "Jobs pane not yet implemented — q to return",
};
let line = Line::from(Span::styled(
hints,