Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-view/src/gutter.rs')
| -rw-r--r-- | helix-view/src/gutter.rs | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/helix-view/src/gutter.rs b/helix-view/src/gutter.rs index 7506e515..3ecae919 100644 --- a/helix-view/src/gutter.rs +++ b/helix-view/src/gutter.rs @@ -1,7 +1,5 @@ use std::fmt::Write; -use helix_core::syntax::config::LanguageServerFeature; - use crate::{ editor::GutterType, graphics::{Style, UnderlineStyle}, @@ -9,7 +7,8 @@ use crate::{ }; fn count_digits(n: usize) -> usize { - (usize::checked_ilog10(n).unwrap_or(0) + 1) as usize + // TODO: use checked_log10 when MSRV reaches 1.67 + std::iter::successors(Some(n), |&n| (n >= 10).then_some(n / 10)).count() } pub type GutterFn<'doc> = Box<dyn FnMut(usize, bool, bool, &mut String) -> Option<Style> + 'doc>; @@ -56,7 +55,7 @@ pub fn diagnostic<'doc>( let error = theme.get("error"); let info = theme.get("info"); let hint = theme.get("hint"); - let diagnostics = &doc.diagnostics; + let diagnostics = doc.diagnostics(); Box::new( move |line: usize, _selected: bool, first_visual_line: bool, out: &mut String| { @@ -64,25 +63,28 @@ pub fn diagnostic<'doc>( return None; } use helix_core::diagnostic::Severity; - let first_diag_idx_maybe_on_line = diagnostics.partition_point(|d| d.line < line); - let diagnostics_on_line = diagnostics[first_diag_idx_maybe_on_line..] - .iter() - .take_while(|d| { - d.line == line - && d.provider.language_server_id().is_none_or(|id| { - doc.language_servers_with_feature(LanguageServerFeature::Diagnostics) - .any(|ls| ls.id() == id) - }) - }); - diagnostics_on_line.max_by_key(|d| d.severity).map(|d| { - write!(out, "●").ok(); - match d.severity { + if let Ok(index) = diagnostics.binary_search_by_key(&line, |d| d.line) { + let after = diagnostics[index..].iter().take_while(|d| d.line == line); + + let before = diagnostics[..index] + .iter() + .rev() + .take_while(|d| d.line == line); + + let diagnostics_on_line = after.chain(before); + + // This unwrap is safe because the iterator cannot be empty as it contains at least the item found by the binary search. + let diagnostic = diagnostics_on_line.max_by_key(|d| d.severity).unwrap(); + + 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 }, ) } @@ -94,9 +96,9 @@ pub fn diff<'doc>( theme: &Theme, _is_focused: bool, ) -> GutterFn<'doc> { - let added = theme.get("diff.plus.gutter"); - let deleted = theme.get("diff.minus.gutter"); - let modified = theme.get("diff.delta.gutter"); + let added = theme.get("diff.plus"); + let deleted = theme.get("diff.minus"); + let modified = theme.get("diff.delta"); if let Some(diff_handle) = doc.diff_handle() { let hunks = diff_handle.load(); let mut hunk_i = 0; @@ -179,7 +181,7 @@ pub fn line_numbers<'doc>( && current_line != line; let display_num = if relative { - current_line.abs_diff(line) + abs_diff(current_line, line) } else { line + 1 }; @@ -227,6 +229,15 @@ pub fn padding<'doc>( Box::new(|_line: usize, _selected: bool, _first_visual_line: bool, _out: &mut String| None) } +#[inline(always)] +const fn abs_diff(a: usize, b: usize) -> usize { + if a > b { + a - b + } else { + b - a + } +} + pub fn breakpoints<'doc>( editor: &'doc Editor, doc: &'doc Document, @@ -334,7 +345,7 @@ mod tests { use crate::graphics::Rect; use crate::DocumentId; use arc_swap::ArcSwap; - use helix_core::{syntax, Rope}; + use helix_core::Rope; #[test] fn test_default_gutter_widths() { @@ -346,7 +357,6 @@ mod tests { rope, None, Arc::new(ArcSwap::new(Arc::new(Config::default()))), - Arc::new(ArcSwap::from_pointee(syntax::Loader::default())), ); assert_eq!(view.gutters.layout.len(), 5); @@ -372,7 +382,6 @@ mod tests { rope, None, Arc::new(ArcSwap::new(Arc::new(Config::default()))), - Arc::new(ArcSwap::from_pointee(syntax::Loader::default())), ); assert_eq!(view.gutters.layout.len(), 1); @@ -391,7 +400,6 @@ mod tests { rope, None, Arc::new(ArcSwap::new(Arc::new(Config::default()))), - Arc::new(ArcSwap::from_pointee(syntax::Loader::default())), ); assert_eq!(view.gutters.layout.len(), 2); @@ -414,7 +422,6 @@ mod tests { rope, None, Arc::new(ArcSwap::new(Arc::new(Config::default()))), - Arc::new(ArcSwap::from_pointee(syntax::Loader::default())), ); let rope = Rope::from_str("a\nb\nc\nd\ne\nf\ng\nh\ni\nj\nk\nl\nm\nn\no\np"); @@ -422,7 +429,6 @@ mod tests { rope, None, Arc::new(ArcSwap::new(Arc::new(Config::default()))), - Arc::new(ArcSwap::from_pointee(syntax::Loader::default())), ); assert_eq!(view.gutters.layout.len(), 2); |