ui: Render diagnostic errors in sideline.

This commit is contained in:
Blaž Hrastnik 2021-03-15 16:19:31 +09:00
parent 1abf2953cd
commit 87e3cd3df2
4 changed files with 69 additions and 7 deletions

View File

@ -1,5 +1,3 @@
use crate::Range;
pub enum Severity { pub enum Severity {
Error, Error,
Warning, Warning,
@ -7,8 +5,12 @@ pub enum Severity {
Hint, Hint,
} }
pub struct Range {
pub start: usize,
pub end: usize,
}
pub struct Diagnostic { pub struct Diagnostic {
pub range: (usize, usize), pub range: Range,
pub line: usize, pub line: usize,
pub message: String, pub message: String,
pub severity: Option<Severity>, pub severity: Option<Severity>,

View File

@ -35,7 +35,7 @@ pub mod util {
pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize { pub fn lsp_pos_to_pos(doc: RopeSlice, pos: lsp::Position) -> usize {
let line = doc.line_to_char(pos.line as usize); let line = doc.line_to_char(pos.line as usize);
let line_start = doc.char_to_utf16_cu(line); let line_start = doc.char_to_utf16_cu(line);
doc.utf16_cu_to_char(pos.character as usize + line_start) doc.utf16_cu_to_char(line_start + pos.character as usize)
} }
pub fn pos_to_lsp_pos(doc: RopeSlice, pos: usize) -> lsp::Position { pub fn pos_to_lsp_pos(doc: RopeSlice, pos: usize) -> lsp::Position {
let line = doc.char_to_line(pos); let line = doc.char_to_line(pos);

View File

@ -140,14 +140,17 @@ pub async fn handle_language_server_message(&mut self, call: Option<helix_lsp::C
.into_iter() .into_iter()
.map(|diagnostic| { .map(|diagnostic| {
use helix_core::diagnostic::Severity::*; use helix_core::diagnostic::Severity::*;
use helix_core::{diagnostic::Severity, Diagnostic}; use helix_core::{
diagnostic::{Range, Severity},
Diagnostic,
};
use helix_lsp::{lsp, util::lsp_pos_to_pos}; use helix_lsp::{lsp, util::lsp_pos_to_pos};
use lsp::DiagnosticSeverity; use lsp::DiagnosticSeverity;
let start = lsp_pos_to_pos(doc, diagnostic.range.start); let start = lsp_pos_to_pos(doc, diagnostic.range.start);
let end = lsp_pos_to_pos(doc, diagnostic.range.end); let end = lsp_pos_to_pos(doc, diagnostic.range.end);
Diagnostic { Diagnostic {
range: (start, end), range: Range { start, end },
line: diagnostic.range.start.line as usize, line: diagnostic.range.start.line as usize,
message: diagnostic.message, message: diagnostic.message,
severity: diagnostic.severity.map( severity: diagnostic.severity.map(

View File

@ -56,6 +56,8 @@ pub fn render_view(
// TODO: this seems to prevent setting style later // TODO: this seems to prevent setting style later
// surface.set_style(viewport, theme.get("ui.background")); // surface.set_style(viewport, theme.get("ui.background"));
self.render_diagnostics(&view.doc, area, surface, theme, is_focused);
let area = Rect::new( let area = Rect::new(
viewport.x, viewport.x,
viewport.y + viewport.height.saturating_sub(1), viewport.y + viewport.height.saturating_sub(1),
@ -166,7 +168,8 @@ pub fn render_buffer(
// ugh,interleave highlight spans with diagnostic spans // ugh,interleave highlight spans with diagnostic spans
let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| { let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| {
diagnostic.range.0 <= char_index && diagnostic.range.1 > char_index diagnostic.range.start <= char_index
&& diagnostic.range.end > char_index
}); });
let style = if is_diagnostic { let style = if is_diagnostic {
@ -316,6 +319,60 @@ pub fn render_buffer(
} }
} }
pub fn render_diagnostics(
&self,
doc: &Document,
viewport: Rect,
surface: &mut Surface,
theme: &Theme,
is_focused: bool,
) {
use helix_core::diagnostic::Severity;
use tui::{
layout::Alignment,
text::Text,
widgets::{Paragraph, Widget},
};
let cursor = doc.selection().cursor();
let line = doc.text().char_to_line(cursor);
let diagnostics = doc.diagnostics.iter().filter(|diagnostic| {
diagnostic.range.start <= cursor && diagnostic.range.end >= cursor
});
let warning: Style = theme.get("warning");
let error: Style = theme.get("error");
let info: Style = theme.get("info");
let hint: Style = theme.get("hint");
// Vec::with_capacity(diagnostics.len()); // rough estimate
let mut lines = Vec::new();
for diagnostic in diagnostics {
let text = Text::styled(
&diagnostic.message,
match diagnostic.severity {
Some(Severity::Error) => error,
Some(Severity::Warning) | None => warning,
Some(Severity::Info) => info,
Some(Severity::Hint) => hint,
},
);
lines.extend(text.lines);
}
let paragraph = Paragraph::new(lines).alignment(Alignment::Right);
paragraph.render(
Rect::new(
viewport.x + viewport.width - 80 - 1,
viewport.y as u16 + 1,
80,
15,
),
surface,
);
}
pub fn render_statusline( pub fn render_statusline(
&self, &self,
doc: &Document, doc: &Document,