on master help sign in
Total mess but it works: diagnostic marking.
commit49254d7180c8b92be5426cab20914b0343c9282c authorBlaž Hrastnik <blaz@mxxn.io> dateTue 20 Oct 2020, 15:42 (6 years ago) parentf9bfba4
4 files changed+91−6
helix-core/src/diagnostic.rs+7−1 helix-lsp/src/lib.rs+3 helix-term/src/application.rs+79−5 helix-view/src/theme.rs+2
helix-core/src/diagnostic.rs+7−1
@@ -1 +1,7 @@
1−pub struct Diagnostic {}
1+use crate::Range;
2+
3+pub struct Diagnostic {
4+ pub range: (usize, usize),
5+ pub line: usize,
6+ pub message: String,
7+}
helix-lsp/src/lib.rs+3
@@ -10,6 +10,9 @@ use serde_json::Value;
1010
1111use serde::{Deserialize, Serialize};
1212
13+pub use lsp::Position;
14+pub use lsp::Url;
15+
1316use smol::prelude::*;
1417use smol::{
1518 channel::{Receiver, Sender},
helix-term/src/application.rs+79−5
@@ -29,10 +29,10 @@ use tui::{
2929 backend::CrosstermBackend,
3030 buffer::Buffer as Surface,
3131 layout::Rect,
32− style::{Color, Style},
32+ style::{Color, Modifier, Style},
3333};
3434
35−const OFFSET: u16 = 6; // 5 linenr + 1 gutter
35+const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
3636
3737type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
3838
@@ -205,6 +205,16 @@ impl Renderer {
205205 style
206206 };
207207
208+ // ugh, improve with a traverse method
209+ // or interleave highlight spans with selection and diagnostic spans
210+ let style = if view.state.diagnostics.iter().any(|diagnostic| {
211+ diagnostic.range.0 <= char_index && diagnostic.range.1 > char_index
212+ }) {
213+ style.clone().add_modifier(Modifier::UNDERLINED)
214+ } else {
215+ style
216+ };
217+
208218 // TODO: paint cursor heads except primary
209219
210220 self.surface
@@ -212,18 +222,23 @@ impl Renderer {
212222
213223 visual_x += width;
214224 }
215− // if grapheme == "\t"
216225
217226 char_index += 1;
218227 }
219228 }
220229 }
221230 }
231+
222232 let style: Style = theme.get("ui.linenr");
233+ let warning: Style = theme.get("warning");
223234 let last_line = view.last_line();
224235 for (i, line) in (view.first_line..last_line).enumerate() {
236+ if view.state.diagnostics.iter().any(|d| d.line == line) {
237+ self.surface.set_stringn(0, i as u16, "●", 1, warning);
238+ }
239+
225240 self.surface
226− .set_stringn(0, i as u16, format!("{:>5}", line + 1), 5, style);
241+ .set_stringn(1, i as u16, format!("{:>5}", line + 1), 5, style);
227242 }
228243 }
229244
@@ -240,6 +255,13 @@ impl Renderer {
240255 );
241256 self.surface
242257 .set_string(1, self.size.1 - 2, mode, self.text_color);
258+
259+ self.surface.set_string(
260+ self.size.0 - 10,
261+ self.size.1 - 2,
262+ format!("{}", view.state.diagnostics.len()),
263+ self.text_color,
264+ );
243265 }
244266
245267 pub fn render_prompt(&mut self, view: &View, prompt: &Prompt, theme: &Theme) {
@@ -545,7 +567,59 @@ impl<'a> Application<'a> {
545567 pub async fn handle_lsp_notification(&mut self, notification: Option<helix_lsp::Notification>) {
546568 use helix_lsp::Notification;
547569 match notification {
548− Some(Notification::PublishDiagnostics(params)) => unimplemented!("{:?}", params),
570+ Some(Notification::PublishDiagnostics(params)) => {
571+ let view = self.editor.views.iter_mut().find(|view| {
572+ let path = view
573+ .state
574+ .path
575+ .as_ref()
576+ .map(|path| helix_lsp::Url::from_file_path(path).unwrap());
577+
578+ eprintln!("{:?} {} {}", path, params.uri, params.diagnostics.len());
579+ // HAXX
580+ path == Some(params.uri.clone())
581+ });
582+
583+ fn lsp_pos_to_pos(doc: &helix_core::RopeSlice, pos: helix_lsp::Position) -> usize {
584+ let line = doc.line_to_char(pos.line as usize);
585+ let line_start = doc.char_to_utf16_cu(line);
586+ doc.utf16_cu_to_char(pos.character as usize + line_start)
587+ }
588+
589+ if let Some(view) = view {
590+ let doc = view.state.doc().slice(..);
591+ let diagnostics = params
592+ .diagnostics
593+ .into_iter()
594+ .map(|diagnostic| {
595+ let start = lsp_pos_to_pos(&doc, diagnostic.range.start);
596+ let end = lsp_pos_to_pos(&doc, diagnostic.range.end);
597+
598+ // eprintln!(
599+ // "{:?}-{:?} {}-{} {}",
600+ // diagnostic.range.start,
601+ // diagnostic.range.end,
602+ // start,
603+ // end,
604+ // diagnostic.message
605+ // );
606+
607+ helix_core::Diagnostic {
608+ range: (start, end),
609+ line: diagnostic.range.start.line as usize,
610+ message: diagnostic.message,
611+ // severity
612+ // code
613+ // source
614+ }
615+ })
616+ .collect();
617+
618+ view.state.diagnostics = diagnostics;
619+
620+ self.render();
621+ }
622+ }
549623 _ => unreachable!(),
550624 }
551625 }
helix-view/src/theme.rs+2
@@ -157,6 +157,8 @@ impl Default for Theme {
157157 "ui.background" => Style::default().bg(Color::Rgb(59, 34, 76)), // midnight
158158 "ui.linenr" => Style::default().fg(Color::Rgb(90, 89, 119)), // comet
159159 "ui.statusline" => Style::default().bg(Color::Rgb(40, 23, 51)), // revolver
160+
161+ "warning" => Style::default().fg(Color::Rgb(255, 205, 28)),
160162 };
161163
162164 let scopes = mapping.keys().map(ToString::to_string).collect();