diff options
-rw-r--r-- | helix-core/src/diagnostic.rs | 8 | ||||
-rw-r--r-- | helix-lsp/src/lib.rs | 3 | ||||
-rw-r--r-- | helix-term/src/application.rs | 84 | ||||
-rw-r--r-- | helix-view/src/theme.rs | 2 |
4 files changed, 91 insertions, 6 deletions
diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs index aee648aa..96ed6746 100644 --- a/helix-core/src/diagnostic.rs +++ b/helix-core/src/diagnostic.rs @@ -1 +1,7 @@ -pub struct Diagnostic {} +use crate::Range; + +pub struct Diagnostic { + pub range: (usize, usize), + pub line: usize, + pub message: String, +} diff --git a/helix-lsp/src/lib.rs b/helix-lsp/src/lib.rs index 3598a594..939f9927 100644 --- a/helix-lsp/src/lib.rs +++ b/helix-lsp/src/lib.rs @@ -10,6 +10,9 @@ use serde_json::Value; use serde::{Deserialize, Serialize}; +pub use lsp::Position; +pub use lsp::Url; + use smol::prelude::*; use smol::{ channel::{Receiver, Sender}, diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs index 3d5b3459..5551e26f 100644 --- a/helix-term/src/application.rs +++ b/helix-term/src/application.rs @@ -29,10 +29,10 @@ use tui::{ backend::CrosstermBackend, buffer::Buffer as Surface, layout::Rect, - style::{Color, Style}, + style::{Color, Modifier, Style}, }; -const OFFSET: u16 = 6; // 5 linenr + 1 gutter +const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>; @@ -205,6 +205,16 @@ impl Renderer { style }; + // ugh, improve with a traverse method + // or interleave highlight spans with selection and diagnostic spans + let style = if view.state.diagnostics.iter().any(|diagnostic| { + diagnostic.range.0 <= char_index && diagnostic.range.1 > char_index + }) { + style.clone().add_modifier(Modifier::UNDERLINED) + } else { + style + }; + // TODO: paint cursor heads except primary self.surface @@ -212,18 +222,23 @@ impl Renderer { visual_x += width; } - // if grapheme == "\t" char_index += 1; } } } } + let style: Style = theme.get("ui.linenr"); + let warning: Style = theme.get("warning"); let last_line = view.last_line(); for (i, line) in (view.first_line..last_line).enumerate() { + if view.state.diagnostics.iter().any(|d| d.line == line) { + self.surface.set_stringn(0, i as u16, "●", 1, warning); + } + self.surface - .set_stringn(0, i as u16, format!("{:>5}", line + 1), 5, style); + .set_stringn(1, i as u16, format!("{:>5}", line + 1), 5, style); } } @@ -240,6 +255,13 @@ impl Renderer { ); self.surface .set_string(1, self.size.1 - 2, mode, self.text_color); + + self.surface.set_string( + self.size.0 - 10, + self.size.1 - 2, + format!("{}", view.state.diagnostics.len()), + self.text_color, + ); } pub fn render_prompt(&mut self, view: &View, prompt: &Prompt, theme: &Theme) { @@ -545,7 +567,59 @@ impl<'a> Application<'a> { pub async fn handle_lsp_notification(&mut self, notification: Option<helix_lsp::Notification>) { use helix_lsp::Notification; match notification { - Some(Notification::PublishDiagnostics(params)) => unimplemented!("{:?}", params), + Some(Notification::PublishDiagnostics(params)) => { + let view = self.editor.views.iter_mut().find(|view| { + let path = view + .state + .path + .as_ref() + .map(|path| helix_lsp::Url::from_file_path(path).unwrap()); + + eprintln!("{:?} {} {}", path, params.uri, params.diagnostics.len()); + // HAXX + path == Some(params.uri.clone()) + }); + + fn lsp_pos_to_pos(doc: &helix_core::RopeSlice, pos: helix_lsp::Position) -> usize { + let line = doc.line_to_char(pos.line as usize); + let line_start = doc.char_to_utf16_cu(line); + doc.utf16_cu_to_char(pos.character as usize + line_start) + } + + if let Some(view) = view { + let doc = view.state.doc().slice(..); + let diagnostics = params + .diagnostics + .into_iter() + .map(|diagnostic| { + let start = lsp_pos_to_pos(&doc, diagnostic.range.start); + let end = lsp_pos_to_pos(&doc, diagnostic.range.end); + + // eprintln!( + // "{:?}-{:?} {}-{} {}", + // diagnostic.range.start, + // diagnostic.range.end, + // start, + // end, + // diagnostic.message + // ); + + helix_core::Diagnostic { + range: (start, end), + line: diagnostic.range.start.line as usize, + message: diagnostic.message, + // severity + // code + // source + } + }) + .collect(); + + view.state.diagnostics = diagnostics; + + self.render(); + } + } _ => unreachable!(), } } diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index 4cc399ed..809ec05d 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -157,6 +157,8 @@ impl Default for Theme { "ui.background" => Style::default().bg(Color::Rgb(59, 34, 76)), // midnight "ui.linenr" => Style::default().fg(Color::Rgb(90, 89, 119)), // comet "ui.statusline" => Style::default().bg(Color::Rgb(40, 23, 51)), // revolver + + "warning" => Style::default().fg(Color::Rgb(255, 205, 28)), }; let scopes = mapping.keys().map(ToString::to_string).collect(); |