mirror of
https://github.com/openai/codex.git
synced 2026-04-28 18:32:04 +03:00
98 lines
3.8 KiB
Markdown
98 lines
3.8 KiB
Markdown
**DOs**
|
||
- Use `poll()` before `read()`: Check for input with a short timeout so the event reader doesn’t hold Crossterm’s global event lock, which can block `cursor::position()` and cause resize crashes.
|
||
```rust
|
||
use std::time::{Duration, Instant};
|
||
use crossterm::event::{self, Event};
|
||
|
||
const EVENT_POLL: Duration = Duration::from_millis(100);
|
||
|
||
loop {
|
||
if event::poll(EVENT_POLL)? {
|
||
match event::read()? {
|
||
Event::Key(k) => app_event_tx.send(AppEvent::KeyEvent(k)),
|
||
Event::Resize(_, _) => app_event_tx.send(AppEvent::RequestRedraw),
|
||
Event::Mouse(m) => match m.kind {
|
||
MouseEventKind::ScrollUp => scroll_event_helper.scroll_up(),
|
||
MouseEventKind::ScrollDown => scroll_event_helper.scroll_down(),
|
||
_ => {}
|
||
},
|
||
Event::Paste(p) => app_event_tx.send(AppEvent::Paste(p.replace("\r", "\n"))),
|
||
_ => {}
|
||
}
|
||
} else {
|
||
// No input this tick; do lightweight work or continue.
|
||
}
|
||
}
|
||
```
|
||
|
||
- Keep timeout comments precise: Explain why `poll()` is used and distinguish the poll interval from Crossterm’s separate lock timeout used by `cursor::position()`.
|
||
```rust
|
||
// Poll every 100ms to avoid holding Crossterm’s event lock.
|
||
// cursor::position() may wait up to ~2s to acquire that lock;
|
||
// if the reader holds it continuously, position reads can fail.
|
||
```
|
||
|
||
- Cite upstream patterns: Add a brief comment linking to Ratatui’s own example so future maintainers recognize this is a known, recommended pattern.
|
||
```rust
|
||
// Pattern inspired by Ratatui inline example:
|
||
// https://github.com/ratatui/ratatui/blob/9836f0760d4a053d9d1eba78171be89cb22dc850/examples/apps/inline/src/main.rs#L98-L118
|
||
```
|
||
|
||
- Model Ratatui’s tick/input loop: Optionally separate “ticks” from input so the UI can update periodically even without events (closer to Ratatui examples).
|
||
```rust
|
||
use std::time::{Duration, Instant};
|
||
use crossterm::event::{self, Event};
|
||
|
||
const TICK_RATE: Duration = Duration::from_millis(200);
|
||
|
||
let mut last_tick = Instant::now();
|
||
loop {
|
||
let timeout = TICK_RATE.saturating_sub(last_tick.elapsed());
|
||
if event::poll(timeout)? {
|
||
match event::read()? {
|
||
Event::Key(k) => app_event_tx.send(AppEvent::KeyEvent(k)),
|
||
Event::Resize(_, _) => app_event_tx.send(AppEvent::RequestRedraw),
|
||
_ => {}
|
||
}
|
||
}
|
||
if last_tick.elapsed() >= TICK_RATE {
|
||
app_event_tx.send(AppEvent::Tick);
|
||
last_tick = Instant::now();
|
||
}
|
||
}
|
||
```
|
||
|
||
- Use named durations to avoid confusion: Make differing timeouts explicit and keep comments in sync.
|
||
```rust
|
||
const EVENT_POLL: Duration = Duration::from_millis(100);
|
||
const CURSOR_LOCK_TIMEOUT_DOC: &str = "cursor::position() may wait ~2s for event lock";
|
||
```
|
||
|
||
**DON’Ts**
|
||
- Don’t call `read()` in a tight loop: This can monopolize the event lock and make `cursor::position()` fail during resizes.
|
||
```rust
|
||
// BAD: holds the event lock continuously
|
||
while let Ok(event) = crossterm::event::read() {
|
||
handle(event); // Other code needing the event lock may starve
|
||
}
|
||
```
|
||
|
||
- Don’t write ambiguous timeout comments: Avoid mixing numbers (e.g., “2 sec” vs “100ms”) without clarifying what each applies to.
|
||
```rust
|
||
// BAD: “Use 100ms so we don’t hit the 2s timeout”
|
||
// Which timeout? For what call? Be explicit.
|
||
```
|
||
|
||
- Don’t diverge from proven upstream patterns without reason: If you implement a different loop structure, explain why it’s needed for your app.
|
||
```rust
|
||
// If not following Ratatui’s poll+read+tick pattern,
|
||
// document the rationale and implications for event lock usage.
|
||
```
|
||
|
||
- Don’t redraw lazily on resize: Make resize explicit and cheap—request a redraw promptly.
|
||
```rust
|
||
match event {
|
||
crossterm::event::Event::Resize(_, _) => app_event_tx.send(AppEvent::RequestRedraw),
|
||
_ => {}
|
||
}
|
||
``` |