mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
4.0 KiB
4.0 KiB
DOs
- Document boolean returns: Explain exactly what
true/falsemean and what the caller must do.
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.
// 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::Interruptif busy; never exit in this branch.
// 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.
// 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.
// 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.
// 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.
// 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
- Don’t leave boolean semantics implicit: Undocumented booleans invite misuse.
// BAD: What does true mean here?
pub(crate) fn on_ctrl_c(&mut self) -> bool { /* ... */ }
- Don’t exit immediately on first Ctrl+C when idle: Show the hint first to prevent accidental exits.
// 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);
}
- Don’t send interrupts when idle: Only interrupt when work is active.
// BAD: Unconditionally interrupting
self.submit_op(Op::Interrupt); // will do nothing useful when idle
- Don’t forget to clear the hint on activity: Otherwise the UI will exit on next Ctrl+C unexpectedly.
// 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... */
}
- Don’t mutate UI state without a redraw: Users won’t see the updated hint/title.
// 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();