summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/diagnostic.rs8
-rw-r--r--helix-lsp/src/lib.rs3
-rw-r--r--helix-term/src/application.rs84
-rw-r--r--helix-view/src/theme.rs2
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();