Skip to content

Commit

Permalink
feat(buffer): add Buffer::cell, cell_mut and index implementations (#…
Browse files Browse the repository at this point in the history
…1084)

Code which previously called `buf.get(x, y)` or `buf.get_mut(x, y)`
should now use index operators, or be transitioned to `buff.cell()` or
`buf.cell_mut()` for safe access that avoids panics by returning
`Option<&Cell>` and `Option<&mut Cell>`.

The new methods accept `Into<Position>` instead of `x` and `y`
coordinates, which makes them more ergonomic to use.

```rust
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10));

let cell = buf[(0, 0)];
let cell = buf[Position::new(0, 0)];

let symbol = buf.cell((0, 0)).map(|cell| cell.symbol());
let symbol = buf.cell(Position::new(0, 0)).map(|cell| cell.symbol());

buf[(0, 0)].set_symbol("🐀");
buf[Position::new(0, 0)].set_symbol("🐀");

buf.cell_mut((0, 0)).map(|cell| cell.set_symbol("🐀"));
buf.cell_mut(Position::new(0, 0)).map(|cell| cell.set_symbol("🐀"));
```

The existing `get()` and `get_mut()` methods are marked as deprecated.
These are fairly widely used and we will leave these methods around on
the buffer for a longer time than our normal deprecation approach (2
major release)

Addresses part of: #1011

---------

Co-authored-by: EdJoPaTo <rfc-conform-git-commit-email@funny-long-domain-label-everyone-hates-as-it-is-too-long.edjopato.de>
  • Loading branch information
joshka and EdJoPaTo authored Aug 6, 2024
1 parent bb71e5f commit a23ecd9
Show file tree
Hide file tree
Showing 30 changed files with 379 additions and 152 deletions.
4 changes: 2 additions & 2 deletions examples/colors_rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ use ratatui::{
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
ExecutableCommand,
},
layout::{Constraint, Layout, Rect},
layout::{Constraint, Layout, Position, Rect},
style::Color,
text::Text,
widgets::Widget,
Expand Down Expand Up @@ -224,7 +224,7 @@ impl Widget for &mut ColorsWidget {
// pixel below it
let fg = colors[yi * 2][xi];
let bg = colors[yi * 2 + 1][xi];
buf.get_mut(x, y).set_char('▀').set_fg(fg).set_bg(bg);
buf[Position::new(x, y)].set_char('▀').set_fg(fg).set_bg(bg);
}
}
self.frame_count += 1;
Expand Down
2 changes: 1 addition & 1 deletion examples/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ impl App {
for (i, cell) in visible_content.enumerate() {
let x = i as u16 % area.width;
let y = i as u16 / area.width;
*buf.get_mut(area.x + x, area.y + y) = cell;
buf[(area.x + x, area.y + y)] = cell;
}

if scrollbar_needed {
Expand Down
2 changes: 1 addition & 1 deletion examples/demo2/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Widget for RgbSwatch {
let hue = xi as f32 * 360.0 / f32::from(area.width);
let fg = color_from_oklab(hue, Okhsv::max_saturation(), value_fg);
let bg = color_from_oklab(hue, Okhsv::max_saturation(), value_bg);
buf.get_mut(x, y).set_char('▀').set_fg(fg).set_bg(bg);
buf[(x, y)].set_char('▀').set_fg(fg).set_bg(bg);
}
}
}
Expand Down
11 changes: 5 additions & 6 deletions examples/demo2/destroy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ fn drip(frame_count: usize, area: Rect, buf: &mut Buffer) {
for _ in 0..pixel_count {
let src_x = rng.gen_range(0..area.width);
let src_y = rng.gen_range(1..area.height - 2);
let src = buf.get_mut(src_x, src_y).clone();
let src = buf[(src_x, src_y)].clone();
// 1% of the time, move a blank or pixel (10:1) to the top line of the screen
if rng.gen_ratio(1, 100) {
let dest_x = rng
.gen_range(src_x.saturating_sub(5)..src_x.saturating_add(5))
.clamp(area.left(), area.right() - 1);
let dest_y = area.top() + 1;

let dest = buf.get_mut(dest_x, dest_y);
let dest = &mut buf[(dest_x, dest_y)];
// copy the cell to the new location about 1/10 of the time blank out the cell the rest
// of the time. This has the effect of gradually removing the pixels from the screen.
if rng.gen_ratio(1, 10) {
Expand All @@ -70,8 +70,7 @@ fn drip(frame_count: usize, area: Rect, buf: &mut Buffer) {
let dest_x = src_x;
let dest_y = src_y.saturating_add(1).min(area.bottom() - 2);
// copy the cell to the new location
let dest = buf.get_mut(dest_x, dest_y);
*dest = src;
buf[(dest_x, dest_y)] = src;
}
}
}
Expand Down Expand Up @@ -101,8 +100,8 @@ fn text(frame_count: usize, area: Rect, buf: &mut Buffer) {

for row in area.rows() {
for col in row.columns() {
let cell = buf.get_mut(col.x, col.y);
let mask_cell = mask_buf.get(col.x, col.y);
let cell = &mut buf[(col.x, col.y)];
let mask_cell = &mut mask_buf[(col.x, col.y)];
cell.set_symbol(mask_cell.symbol());

// blend the mask cell color with the cell color
Expand Down
2 changes: 1 addition & 1 deletion examples/demo2/tabs/about.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub fn render_logo(selected_row: usize, area: Rect, buf: &mut Buffer) {
for (x, (ch1, ch2)) in line1.chars().zip(line2.chars()).enumerate() {
let x = area.left() + x as u16;
let y = area.top() + y as u16;
let cell = buf.get_mut(x, y);
let cell = &mut buf[(x, y)];
let rat_color = THEME.logo.rat;
let term_color = THEME.logo.term;
match (ch1, ch2) {
Expand Down
2 changes: 1 addition & 1 deletion examples/flex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ impl App {
for (i, cell) in visible_content.enumerate() {
let x = i as u16 % area.width;
let y = i as u16 / area.width;
*buf.get_mut(area.x + x, area.y + y) = cell;
buf[(area.x + x, area.y + y)] = cell;
}

if scrollbar_needed {
Expand Down
4 changes: 1 addition & 3 deletions examples/hyperlink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,7 @@ impl WidgetRef for Hyperlink<'_> {
{
let text = two_chars.collect::<String>();
let hyperlink = format!("\x1B]8;;{}\x07{}\x1B]8;;\x07", self.url, text);
buffer
.get_mut(area.x + i as u16 * 2, area.y)
.set_symbol(hyperlink.as_str());
buffer[(area.x + i as u16 * 2, area.y)].set_symbol(hyperlink.as_str());
}
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/backend/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,7 @@ impl Backend for TestBackend {
I: Iterator<Item = (u16, u16, &'a Cell)>,
{
for (x, y, c) in content {
let cell = self.buffer.get_mut(x, y);
*cell = c.clone();
self.buffer[(x, y)] = c.clone();
}
Ok(())
}
Expand Down
2 changes: 1 addition & 1 deletion src/buffer/assert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ macro_rules! assert_buffer_eq {
.into_iter()
.enumerate()
.map(|(i, (x, y, cell))| {
let expected_cell = expected.get(x, y);
let expected_cell = &expected[(x, y)];
format!("{i}: at ({x}, {y})\n expected: {expected_cell:?}\n actual: {cell:?}")
})
.collect::<Vec<String>>()
Expand Down
Loading

0 comments on commit a23ecd9

Please sign in to comment.