Skip to content

Commit

Permalink
Merge branch 'perf'
Browse files Browse the repository at this point in the history
```
group                       base                                   main
-----                       ----                                   ----
cursor::char::back          1.00     32.8±0.63ms        ? ?/sec    1.15     37.7±0.81ms        ? ?/sec
cursor::char::down          1.00     29.9±0.62ms        ? ?/sec    1.19     35.6±0.82ms        ? ?/sec
cursor::char::forward       1.00     31.8±0.74ms        ? ?/sec    1.06     33.8±0.90ms        ? ?/sec
cursor::char::up            1.00     30.3±0.86ms        ? ?/sec    1.02     30.8±0.73ms        ? ?/sec
cursor::edge::head_end      1.00     33.2±0.63ms        ? ?/sec    1.03     34.3±0.84ms        ? ?/sec
cursor::edge::top_bottom    1.00     31.5±0.81ms        ? ?/sec    1.11     34.9±0.82ms        ? ?/sec
cursor::paragraph::down     1.00     30.1±0.83ms        ? ?/sec    1.19     35.7±0.76ms        ? ?/sec
cursor::paragraph::up       1.00     30.0±0.68ms        ? ?/sec    1.03     30.9±0.63ms        ? ?/sec
cursor::word::back          1.00     30.4±0.61ms        ? ?/sec    1.05     32.1±0.64ms        ? ?/sec
cursor::word::forward       1.00     31.9±0.65ms        ? ?/sec    1.18     37.7±0.89ms        ? ?/sec
delete::char                1.00      3.4±0.10ms        ? ?/sec    4.48     15.3±0.82ms        ? ?/sec
delete::line                1.00  1243.4±42.36µs        ? ?/sec    7.71      9.6±0.38ms        ? ?/sec
delete::word                1.00      2.7±0.10ms        ? ?/sec    5.35     14.2±0.37ms        ? ?/sec
insert::append::10_lorem    1.00    327.2±4.89ms        ? ?/sec    1.00    327.6±4.92ms        ? ?/sec
insert::append::1_lorem     1.00      7.0±0.16ms        ? ?/sec    1.00      7.0±0.15ms        ? ?/sec
insert::append::50_lorem    1.00       3.1±0.02s        ? ?/sec    2.24       7.0±0.03s        ? ?/sec
insert::random::10_lorem    1.00    133.8±2.78ms        ? ?/sec    1.90    254.6±3.95ms        ? ?/sec
insert::random::1_lorem     1.00      6.7±0.16ms        ? ?/sec    1.01      6.8±0.14ms        ? ?/sec
insert::random::50_lorem    1.00    709.0±7.70ms        ? ?/sec    5.97       4.2±0.03s        ? ?/sec
search::back_long           1.00      4.3±0.15ms        ? ?/sec    3.02     13.0±0.49ms        ? ?/sec
search::back_short          1.01      4.3±0.14ms        ? ?/sec    1.00      4.2±0.10ms        ? ?/sec
search::forward_long        1.00      4.4±0.14ms        ? ?/sec    2.37     10.5±0.29ms        ? ?/sec
search::forward_short       1.02      4.2±0.14ms        ? ?/sec    1.00      4.1±0.10ms        ? ?/sec
```
  • Loading branch information
rhysd committed Jul 17, 2022
2 parents b56f252 + ee4162c commit 4e5b684
Showing 1 changed file with 31 additions and 35 deletions.
66 changes: 31 additions & 35 deletions src/widget.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::textarea::TextArea;
use crate::util::num_digits;
use std::cmp;
use std::sync::atomic::{AtomicU32, Ordering};
use tui::buffer::Buffer;
use tui::layout::Rect;
use tui::text::Text;
use tui::widgets::{Block, Paragraph, Widget};
use tui::widgets::{Paragraph, Widget};

// &mut 'a (u16, u16) is not available since TextAreaWidget instance totally takes over the ownership of TextArea
// instance. In the case, the TextArea instance cannot be accessed from any other objects since it is mutablly
Expand Down Expand Up @@ -36,40 +37,30 @@ impl ScrollTop {
}
}

pub struct Renderer<'a> {
scroll_top: &'a ScrollTop,
cursor: (u16, u16),
block: Option<Block<'a>>,
inner: Paragraph<'a>,
}
pub struct Renderer<'a>(&'a TextArea<'a>);

impl<'a> Renderer<'a> {
pub fn new(textarea: &'a TextArea<'a>) -> Self {
let lnum_len = num_digits(textarea.lines().len());
let lines: Vec<_> = textarea
.lines()
.iter()
.map(String::as_str)
.enumerate()
.map(|(row, line)| textarea.line_spans(line, row, lnum_len))
.collect();
let inner = Paragraph::new(Text::from(lines)).style(textarea.style());
let cursor = textarea.cursor();
Self {
scroll_top: &textarea.scroll_top,
cursor: (cursor.0 as u16, cursor.1 as u16),
block: textarea.block().cloned(),
inner,
Self(textarea)
}

#[inline]
fn text(&self, top_row: usize, height: usize) -> Text<'a> {
let lines_len = self.0.lines().len();
let lnum_len = num_digits(lines_len);
let bottom_row = cmp::min(top_row + height, lines_len);
let mut lines = Vec::with_capacity(bottom_row - top_row);
for (i, line) in self.0.lines()[top_row..bottom_row].iter().enumerate() {
lines.push(self.0.line_spans(line.as_str(), top_row + i, lnum_len));
}
Text::from(lines)
}
}

impl<'a> Widget for Renderer<'a> {
fn render(mut self, area: Rect, buf: &mut Buffer) {
let inner_area = if let Some(b) = self.block.take() {
let area = b.inner(area);
self.inner = self.inner.block(b);
area
fn render(self, area: Rect, buf: &mut Buffer) {
let inner_area = if let Some(b) = self.0.block() {
b.inner(area)
} else {
area
};
Expand All @@ -84,18 +75,23 @@ impl<'a> Widget for Renderer<'a> {
}
}

let (top_row, top_col) = self.scroll_top.load();
let row = next_scroll_top(top_row, self.cursor.0, inner_area.height);
let col = next_scroll_top(top_col, self.cursor.1, inner_area.width);
let cursor = self.0.cursor();
let (top_row, top_col) = self.0.scroll_top.load();
let top_row = next_scroll_top(top_row, cursor.0 as u16, inner_area.height);
let top_col = next_scroll_top(top_col, cursor.1 as u16, inner_area.width);

let scroll = (row, col);
if scroll != (0, 0) {
self.inner = self.inner.scroll(scroll);
let text = self.text(top_row as usize, inner_area.height as usize);
let mut inner = Paragraph::new(text).style(self.0.style());
if let Some(b) = self.0.block() {
inner = inner.block(b.clone());
}
if top_col != 0 {
inner = inner.scroll((0, top_col));
}

// Store scroll top position for rendering on the next tick
self.scroll_top.store(row, col);
self.0.scroll_top.store(top_row, top_col);

self.inner.render(area, buf);
inner.render(area, buf);
}
}

0 comments on commit 4e5b684

Please sign in to comment.