diff options
author | Blaž Hrastnik | 2021-11-22 08:02:46 +0000 |
---|---|---|
committer | Blaž Hrastnik | 2021-11-29 02:00:28 +0000 |
commit | 27c1a84f053d1282ed09d64ec737a46f55685d85 (patch) | |
tree | 95c25e00ffe0472859d525fb365a7773df422e75 /helix-term/src/ui | |
parent | ba45db84d4b49913836a949472366a30a620e67b (diff) |
Reuse a text buffer for each gutter line
Diffstat (limited to 'helix-term/src/ui')
-rw-r--r-- | helix-term/src/ui/editor.rs | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 2cc212ea..82fb8fbf 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -421,6 +421,8 @@ impl EditorView { .map(|range| range.cursor_line(text)) .collect(); + use std::fmt::Write; + fn diagnostic<'doc>( doc: &'doc Document, _view: &View, @@ -435,18 +437,16 @@ impl EditorView { let hint = theme.get("hint"); let diagnostics = doc.diagnostics(); - Box::new(move |line: usize, _selected: bool| { + Box::new(move |line: usize, _selected: bool, out: &mut String| { use helix_core::diagnostic::Severity; if let Some(diagnostic) = diagnostics.iter().find(|d| d.line == line) { - return Some(( - "●".to_string(), - match diagnostic.severity { - Some(Severity::Error) => error, - Some(Severity::Warning) | None => warning, - Some(Severity::Info) => info, - Some(Severity::Hint) => hint, - }, - )); + write!(out, "●").unwrap(); + return Some(match diagnostic.severity { + Some(Severity::Error) => error, + Some(Severity::Warning) | None => warning, + Some(Severity::Info) => info, + Some(Severity::Hint) => hint, + }); } None }) @@ -475,9 +475,10 @@ impl EditorView { let config = config.line_number; - Box::new(move |line: usize, selected: bool| { + Box::new(move |line: usize, selected: bool, out: &mut String| { if line == last_line && !draw_last { - Some((format!("{:>1$}", '~', width), linenr)) + write!(out, "{:>1$}", '~', width).unwrap(); + Some(linenr) } else { let line = match config { LineNumber::Absolute => line + 1, @@ -494,25 +495,38 @@ impl EditorView { } else { linenr }; - Some((format!("{:>1$}", line, width), style)) + write!(out, "{:>1$}", line, width).unwrap(); + Some(style) } }) } - type GutterFn<'doc> = Box<dyn Fn(usize, bool) -> Option<(String, Style)> + 'doc>; + type GutterFn<'doc> = Box<dyn Fn(usize, bool, &mut String) -> Option<Style> + 'doc>; type Gutter = for<'doc> fn(&'doc Document, &View, &Theme, &Config, bool, usize) -> GutterFn<'doc>; let gutters: &[(Gutter, usize)] = &[(diagnostic, 1), (line_number, 5)]; let mut offset = 0; + + // avoid lots of small allocations by reusing a text buffer for each line + let mut text = String::with_capacity(8); + for (constructor, width) in gutters { let gutter = constructor(doc, view, theme, config, is_focused, *width); + text.reserve(*width); // ensure there's enough space for the gutter for (i, line) in (view.offset.row..(last_line + 1)).enumerate() { let selected = cursors.contains(&line); - if let Some((text, style)) = gutter(line, selected) { - surface.set_stringn(viewport.x + offset, viewport.y + i as u16, text, 5, style); + if let Some(style) = gutter(line, selected, &mut text) { + surface.set_stringn( + viewport.x + offset, + viewport.y + i as u16, + &text, + *width, + style, + ); } + text.clear(); } offset += *width as u16; } |