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.rs64
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);