Gutter functions

pull/1184/head
Blaž Hrastnik 3 years ago
parent 42fde95223
commit 30171416cb

@ -1,7 +1,7 @@
//! LSP diagnostic utility types. //! LSP diagnostic utility types.
/// Describes the severity level of a [`Diagnostic`]. /// Describes the severity level of a [`Diagnostic`].
#[derive(Debug, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Severity { pub enum Severity {
Error, Error,
Warning, Warning,
@ -17,7 +17,7 @@ pub struct Range {
} }
/// Corresponds to [`lsp_types::Diagnostic`](https://docs.rs/lsp-types/0.91.0/lsp_types/struct.Diagnostic.html) /// Corresponds to [`lsp_types::Diagnostic`](https://docs.rs/lsp-types/0.91.0/lsp_types/struct.Diagnostic.html)
#[derive(Debug)] #[derive(Debug, Clone)]
pub struct Diagnostic { pub struct Diagnostic {
pub range: Range, pub range: Range,
pub line: usize, pub line: usize,

@ -17,7 +17,7 @@ use helix_core::{
}; };
use helix_view::{ use helix_view::{
document::{Mode, SCRATCH_BUFFER_NAME}, document::{Mode, SCRATCH_BUFFER_NAME},
editor::LineNumber, editor::{Config, LineNumber},
graphics::{CursorKind, Modifier, Rect, Style}, graphics::{CursorKind, Modifier, Rect, Style},
info::Info, info::Info,
input::KeyEvent, input::KeyEvent,
@ -412,22 +412,6 @@ impl EditorView {
let text = doc.text().slice(..); let text = doc.text().slice(..);
let last_line = view.last_line(doc); let last_line = view.last_line(doc);
let linenr = theme.get("ui.linenr");
let linenr_select: Style = theme.try_get("ui.linenr.selected").unwrap_or(linenr);
let warning = theme.get("warning");
let error = theme.get("error");
let info = theme.get("info");
let hint = theme.get("hint");
// Whether to draw the line number for the last line of the
// document or not. We only draw it if it's not an empty line.
let draw_last = text.line_to_byte(last_line) < text.len_bytes();
let current_line = doc
.text()
.char_to_line(doc.selection(view.id).primary().cursor(text));
// it's used inside an iterator so the collect isn't needless: // it's used inside an iterator so the collect isn't needless:
// https://github.com/rust-lang/rust-clippy/issues/6164 // https://github.com/rust-lang/rust-clippy/issues/6164
#[allow(clippy::needless_collect)] #[allow(clippy::needless_collect)]
@ -437,51 +421,99 @@ impl EditorView {
.map(|range| range.cursor_line(text)) .map(|range| range.cursor_line(text))
.collect(); .collect();
for (i, line) in (view.offset.row..(last_line + 1)).enumerate() { fn diagnostic(
use helix_core::diagnostic::Severity; doc: &Document,
if let Some(diagnostic) = doc.diagnostics().iter().find(|d| d.line == line) { _view: &View,
surface.set_stringn( theme: &Theme,
viewport.x, _config: &Config,
viewport.y + i as u16, _is_focused: bool,
"●", _width: usize,
1, ) -> GutterFn {
match diagnostic.severity { let warning = theme.get("warning");
Some(Severity::Error) => error, let error = theme.get("error");
Some(Severity::Warning) | None => warning, let info = theme.get("info");
Some(Severity::Info) => info, let hint = theme.get("hint");
Some(Severity::Hint) => hint, let diagnostics = doc.diagnostics().to_vec(); // TODO
},
); Box::new(move |line: usize, _selected: bool| {
} 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,
},
));
}
None
})
}
let selected = cursors.contains(&line); fn line_number(
doc: &Document,
view: &View,
theme: &Theme,
config: &Config,
is_focused: bool,
width: usize,
) -> GutterFn {
let text = doc.text().slice(..);
let last_line = view.last_line(doc);
// Whether to draw the line number for the last line of the
// document or not. We only draw it if it's not an empty line.
let draw_last = text.line_to_byte(last_line) < text.len_bytes();
let text = if line == last_line && !draw_last { let linenr = theme.get("ui.linenr");
" ~".into() let linenr_select: Style = theme.try_get("ui.linenr.selected").unwrap_or(linenr);
} else {
let line = match config.line_number { let current_line = doc
LineNumber::Absolute => line + 1, .text()
LineNumber::Relative => { .char_to_line(doc.selection(view.id).primary().cursor(text));
if current_line == line {
line + 1 let config = config.line_number;
} else {
abs_diff(current_line, line) Box::new(move |line: usize, selected: bool| {
} if line == last_line && !draw_last {
} Some((format!("{:>1$}", '~', width), linenr))
};
format!("{:>5}", line)
};
surface.set_stringn(
viewport.x + 1,
viewport.y + i as u16,
text,
5,
if selected && is_focused {
linenr_select
} else { } else {
linenr let line = match config {
}, LineNumber::Absolute => line + 1,
); LineNumber::Relative => {
if current_line == line {
line + 1
} else {
abs_diff(current_line, line)
}
}
};
let style = if selected && is_focused {
linenr_select
} else {
linenr
};
Some((format!("{:>1$}", line, width), style))
}
})
}
type GutterFn = Box<dyn Fn(usize, bool) -> Option<(String, Style)>>;
type Gutter = fn(&Document, &View, &Theme, &Config, bool, usize) -> GutterFn;
let gutters: &[(Gutter, usize)] = &[(diagnostic, 1), (line_number, 5)];
let mut offset = 0;
for (constructor, width) in gutters {
let gutter = constructor(doc, view, theme, config, is_focused, *width);
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);
}
}
offset += *width as u16;
} }
} }

@ -106,7 +106,7 @@ pub struct Config {
pub file_picker: FilePickerConfig, pub file_picker: FilePickerConfig,
} }
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)]
#[serde(rename_all = "kebab-case")] #[serde(rename_all = "kebab-case")]
pub enum LineNumber { pub enum LineNumber {
/// Show absolute line number /// Show absolute line number

Loading…
Cancel
Save