Files
codex/prs/bolinfest/study/PR-1402-study.md
2025-09-02 15:17:45 -07:00

124 lines
4.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
**DOs**
- **Document boolean returns**: Explain exactly what `true`/`false` mean and what the caller must do.
```rust
impl ChatWidget<'_> {
/// Handle Ctrl+C.
/// Returns true if the caller should exit the app.
/// Returns false if handled internally (interrupt or hint shown).
pub(crate) fn on_ctrl_c(&mut self) -> bool { /* ... */ }
}
```
- **Delegate exit to the app**: Let the widget decide intent; the app performs the exit.
```rust
// codex-rs/tui/src/app.rs
if widget.on_ctrl_c() {
// Widget signaled exit
let _ = self.app_event_tx.send(AppEvent::ExitRequest);
}
```
- **Interrupt only when a task is running**: Forward `Op::Interrupt` if busy; never exit in this branch.
```rust
// codex-rs/tui/src/chatwidget.rs
if self.bottom_pane.is_task_running() {
self.bottom_pane.clear_ctrl_c_quit_hint();
self.submit_op(Op::Interrupt);
return false; // handled internally
}
```
- **Show a quit hint when idle; exit on second press**: First Ctrl+C shows “Ctrl+C to quit”; second Ctrl+C exits.
```rust
// Still in on_ctrl_c()
if self.bottom_pane.ctrl_c_quit_hint_visible() {
return true; // caller should exit
} else {
self.bottom_pane.show_ctrl_c_quit_hint();
return false; // handled internally
}
```
- **Clear the hint on other activity**: Any keypress or task start should remove the hint.
```rust
// On any key event
pub(crate) fn handle_key_event(&mut self, key_event: KeyEvent) {
self.bottom_pane.clear_ctrl_c_quit_hint();
/* ...existing handling... */
}
// When a task starts
EventMsg::TaskStarted => {
self.bottom_pane.clear_ctrl_c_quit_hint();
self.bottom_pane.set_task_running(true);
self.request_redraw();
}
```
- **Update UI through dedicated APIs and request redraws**: Keep state changes localized and visible.
```rust
// codex-rs/tui/src/bottom_pane/mod.rs
pub(crate) fn show_ctrl_c_quit_hint(&mut self) {
self.ctrl_c_quit_hint = true;
self.composer.set_ctrl_c_quit_hint(true, self.has_input_focus);
self.request_redraw();
}
pub(crate) fn clear_ctrl_c_quit_hint(&mut self) {
if self.ctrl_c_quit_hint {
self.ctrl_c_quit_hint = false;
self.composer.set_ctrl_c_quit_hint(false, self.has_input_focus);
self.request_redraw();
}
}
```
- **Keep responsibilities layered**: BottomPane owns hint state; Composer renders it; Widget orchestrates behavior; App decides process exit.
```rust
// codex-rs/tui/src/bottom_pane/chat_composer.rs (rendering)
let bs = if has_focus {
if self.ctrl_c_quit_hint {
BlockState { right_title: "Ctrl+C to quit".into(), border_style: Style::default() }
} else {
BlockState { right_title: "Enter to send | Ctrl+D to quit | Ctrl+J for newline".into(),
border_style: Style::default() }
}
} else { /* ... */ };
```
**DON'Ts**
- **Dont leave boolean semantics implicit**: Undocumented booleans invite misuse.
```rust
// BAD: What does true mean here?
pub(crate) fn on_ctrl_c(&mut self) -> bool { /* ... */ }
```
- **Dont exit immediately on first Ctrl+C when idle**: Show the hint first to prevent accidental exits.
```rust
// BAD: Immediate exit on first Ctrl+C
if key.code == KeyCode::Char('c') && key.modifiers.contains(KeyModifiers::CONTROL) {
let _ = self.app_event_tx.send(AppEvent::ExitRequest);
}
```
- **Dont send interrupts when idle**: Only interrupt when work is active.
```rust
// BAD: Unconditionally interrupting
self.submit_op(Op::Interrupt); // will do nothing useful when idle
```
- **Dont forget to clear the hint on activity**: Otherwise the UI will exit on next Ctrl+C unexpectedly.
```rust
// BAD: No hint clearing at the start of key handling
pub(crate) fn handle_key_event(&mut self, key_event: KeyEvent) {
/* ...handles keys but leaves hint visible... */
}
```
- **Dont mutate UI state without a redraw**: Users wont see the updated hint/title.
```rust
// BAD: State changed, but no redraw requested
self.ctrl_c_quit_hint = true;
self.composer.set_ctrl_c_quit_hint(true, self.has_input_focus);
// missing: self.request_redraw();
```