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

126 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**
- **Prefer typed commands over magic ANSI**: Define small `crossterm::Command` wrappers so intent is obvious.
```rust
use std::fmt::{self, Write as _};
use crossterm::Command;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SetScrollRegion(pub std::ops::Range<u16>);
impl Command for SetScrollRegion {
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
// CSI {top};{bottom} r — set scroll region
write!(f, "\x1b[{};{}r", self.0.start, self.0.end)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ResetScrollRegion;
impl Command for ResetScrollRegion {
fn write_ansi(&self, f: &mut impl fmt::Write) -> fmt::Result {
// CSI r — reset scroll region
write!(f, "\x1b[r")
}
}
```
- **Comment raw ANSI if you must use it**: If wrappers arent viable, explain the sequence inline.
```rust
// CSI 1;{top} r — restrict scroll area to rows 1..=top
queue!(std::io::stdout(), Print(format!("\x1b[1;{}r", area.top()))).ok();
// CSI r — reset scroll region to full screen
queue!(std::io::stdout(), Print("\x1b[r")).ok();
```
- **Compute wrapped height using Unicode display width**: Count doublewidth characters and span concatenation.
```rust
use ratatui::text::Line;
use unicode_width::UnicodeWidthStr;
fn line_height(line: &Line, width: u16) -> u16 {
if width == 0 { return 1; }
let w: usize = line.spans.iter().map(|s| s.content.width()).sum();
((w as u16).div_ceil(width)).max(1)
}
```
- **Scroll viewport only when needed and keep it in sync**: Make room when not at the bottom, then update the viewport area.
```rust
use ratatui::layout::Size;
let screen = terminal.backend().size().unwrap_or(Size::new(0, 0));
let mut area = terminal.get_frame().area();
let needed = wrapped_line_count(&lines, area.width);
if area.bottom() < screen.height {
let n = needed.min(screen.height - area.bottom());
terminal.backend_mut()
.scroll_region_down(area.top()..screen.height, n)
.ok();
area.y += n;
terminal.set_viewport_area(area);
}
```
- **Insert lines by limiting the scroll region, printing, then resetting**: Place the cursor at the region end and print CRLF before spans.
```rust
use crossterm::{queue, style::Print};
use ratatui::layout::Position;
queue!(std::io::stdout(), SetScrollRegion(1..area.top())).ok();
terminal.set_cursor_position(Position::new(0, area.top() - 1)).ok();
for line in &lines {
queue!(std::io::stdout(), Print("\r\n")).ok();
write_spans(&mut std::io::stdout(), line.iter()).ok();
}
queue!(std::io::stdout(), ResetScrollRegion).ok();
```
- **Inline variables in format/write macros**: Follow house style for clarity.
```rust
write!(f, "\x1b[{};{}r", start, end)?;
```
- **Handle edge cases explicitly**: Guard zero widths and ensure at least one visual line.
```rust
let height = line_height(&line, area.width).max(1);
```
**DONTs**
- **Dont emit unexplained magic ANSI strings**: Theyre hard to review and maintain.
```rust
// BAD: unclear intent
queue!(std::io::stdout(), Print("\x1b[1;24r")).ok();
```
- **Dont approximate wrapping with lines.len()**: This ignores Unicode widths and span composition.
```rust
// BAD: ignores display width and wrapping
let wrapped = lines.len() as u16;
```
- **Dont move the cursor above the screen**: Large inserts can underflow and place the cursor offscreen.
```rust
// BAD: can underflow when many lines insert
terminal.set_cursor_position(Position::new(0, area.top() - lines.len() as u16)).ok();
```
- **Dont forget to reset the scroll region**: Leaving a restricted region breaks later rendering.
```rust
// BAD: missing reset
// queue!(std::io::stdout(), ResetScrollRegion).ok();
```
- **Dont scroll the whole screen linebyline**: Prefer setting a scroll region and printing once for correctness and speed.
```rust
// BAD: inefficient and fails for multiline wraps
terminal.backend_mut().scroll_region_up(0..area.top(), 1).ok();
```
- **Dont keep unused imports**: Trim them to reduce noise and lints.
```rust
// BAD: unused in this module
use ratatui::prelude::Backend;
```