on master help sign in
Reroute LSP notification events into the main app event loop.
f9bfba4Blaž Hrastnik
Cargo.lock+1
@@ -472,6 +472,7 @@ dependencies = [
472 "anyhow",
472 "anyhow",
473 "clap",
473 "clap",
474 "crossterm",
474 "crossterm",
475+ "futures-util",
475 "helix-core",
476 "helix-core",
476 "helix-lsp",
477 "helix-lsp",
477 "helix-view",
478 "helix-view",
helix-core/src/diagnostic.rsnew file+1
@@ -0,0 +1 @@
1+pub struct Diagnostic {}
helix-core/src/lib.rs+2
@@ -1,4 +1,5 @@
1#![allow(unused)]
1#![allow(unused)]
2+mod diagnostic;
2pub mod graphemes;
3pub mod graphemes;
3mod history;
4mod history;
4pub mod indent;
5pub mod indent;
@@ -22,6 +23,7 @@ pub use selection::Range;
22pub use selection::Selection;
23pub use selection::Selection;
23pub use syntax::Syntax;
24pub use syntax::Syntax;
24
25
26+pub use diagnostic::Diagnostic;
25pub use history::History;
27pub use history::History;
26pub use state::State;
28pub use state::State;
27
29
helix-core/src/state.rs+7−3
@@ -1,6 +1,6 @@
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
1use crate::graphemes::{nth_next_grapheme_boundary, nth_prev_grapheme_boundary, RopeGraphemes};
2use crate::syntax::LOADER;
2use crate::syntax::LOADER;
3−use crate::{ChangeSet, Position, Range, Rope, RopeSlice, Selection, Syntax};
3+use crate::{ChangeSet, Diagnostic, Position, Range, Rope, RopeSlice, Selection, Syntax};
4use anyhow::Error;
4use anyhow::Error;
5
5
6use std::path::PathBuf;
6use std::path::PathBuf;
@@ -28,6 +28,8 @@ pub struct State {
28 /// Pending changes since last history commit.
28 /// Pending changes since last history commit.
29 pub changes: ChangeSet,
29 pub changes: ChangeSet,
30 pub old_state: Option<(Rope, Selection)>,
30 pub old_state: Option<(Rope, Selection)>,
31+
32+ pub diagnostics: Vec<Diagnostic>,
31}
33}
32
34
33#[derive(Copy, Clone, PartialEq, Eq)]
35#[derive(Copy, Clone, PartialEq, Eq)]
@@ -58,12 +60,13 @@ impl State {
58 syntax: None,
60 syntax: None,
59 changes,
61 changes,
60 old_state,
62 old_state,
63+ diagnostics: Vec::new(),
61 }
64 }
62 }
65 }
63
66
64 // TODO: passing scopes here is awkward
67 // TODO: passing scopes here is awkward
65 pub fn load(path: PathBuf, scopes: &[String]) -> Result<Self, Error> {
68 pub fn load(path: PathBuf, scopes: &[String]) -> Result<Self, Error> {
66− use std::{env, fs::File, io::BufReader, path::PathBuf};
69+ use std::{env, fs::File, io::BufReader};
67 let _current_dir = env::current_dir()?;
70 let _current_dir = env::current_dir()?;
68
71
69 let doc = Rope::from_reader(BufReader::new(File::open(path.clone())?))?;
72 let doc = Rope::from_reader(BufReader::new(File::open(path.clone())?))?;
@@ -81,7 +84,8 @@ impl State {
81 state.syntax = Some(syntax);
84 state.syntax = Some(syntax);
82 };
85 };
83
86
87+ // canonicalize path to absolute value
84− state.path = Some(path);
88+ state.path = Some(std::fs::canonicalize(path)?);
85
89
86 Ok(state)
90 Ok(state)
87 }
91 }
helix-lsp/src/lib.rs+16−17
@@ -2,7 +2,7 @@ mod transport;
2
2
3use transport::{Payload, Transport};
3use transport::{Payload, Transport};
4
4
5−use std::collections::HashMap;
5+// use std::collections::HashMap;
6
6
7use jsonrpc_core as jsonrpc;
7use jsonrpc_core as jsonrpc;
8use lsp_types as lsp;
8use lsp_types as lsp;
@@ -32,10 +32,12 @@ enum Message {
32}
32}
33
33
34#[derive(Debug, PartialEq, Clone)]
34#[derive(Debug, PartialEq, Clone)]
35−enum Notification {}
35+pub enum Notification {
36+ PublishDiagnostics(lsp::PublishDiagnosticsParams),
37+}
36
38
37impl Notification {
39impl Notification {
38− pub fn parse(method: &str, params: jsonrpc::Params) {
40+ pub fn parse(method: &str, params: jsonrpc::Params) -> Notification {
39 use lsp::notification::Notification as _;
41 use lsp::notification::Notification as _;
40
42
41 match method {
43 match method {
@@ -44,11 +46,10 @@ impl Notification {
44 .parse()
46 .parse()
45 .expect("Failed to parse PublishDiagnostics params");
47 .expect("Failed to parse PublishDiagnostics params");
46
48
47− println!("{:?}", params);
48−
49 // TODO: need to loop over diagnostics and distinguish them by URI
49 // TODO: need to loop over diagnostics and distinguish them by URI
50+ Notification::PublishDiagnostics(params)
50 }
51 }
51− _ => println!("unhandled notification: {}", method),
52+ _ => unimplemented!("unhandled notification: {}", method),
52 }
53 }
53 }
54 }
54}
55}
@@ -58,13 +59,13 @@ pub struct Client {
58 stderr: BufReader<ChildStderr>,
59 stderr: BufReader<ChildStderr>,
59
60
60 outgoing: Sender<Payload>,
61 outgoing: Sender<Payload>,
61− incoming: Receiver<Message>,
62+ pub incoming: Receiver<Notification>,
62
63
63 pub request_counter: u64,
64 pub request_counter: u64,
64
65
65 capabilities: Option<lsp::ServerCapabilities>,
66 capabilities: Option<lsp::ServerCapabilities>,
66 // TODO: handle PublishDiagnostics Version
67 // TODO: handle PublishDiagnostics Version
67− diagnostics: HashMap<lsp::Url, Vec<lsp::Diagnostic>>,
68+ // diagnostics: HashMap<lsp::Url, Vec<lsp::Diagnostic>>,
68}
69}
69
70
70impl Client {
71impl Client {
@@ -95,7 +96,7 @@ impl Client {
95 request_counter: 0,
96 request_counter: 0,
96
97
97 capabilities: None,
98 capabilities: None,
98− diagnostics: HashMap::new(),
99+ // diagnostics: HashMap::new(),
99 }
100 }
100 }
101 }
101
102
@@ -226,10 +227,7 @@ impl Client {
226 ) -> anyhow::Result<()> {
227 ) -> anyhow::Result<()> {
227 self.notify::<lsp::notification::DidOpenTextDocument>(lsp::DidOpenTextDocumentParams {
228 self.notify::<lsp::notification::DidOpenTextDocument>(lsp::DidOpenTextDocumentParams {
228 text_document: lsp::TextDocumentItem {
229 text_document: lsp::TextDocumentItem {
229− uri: lsp::Url::from_file_path(
230+ uri: lsp::Url::from_file_path(state.path().unwrap()).unwrap(),
230− std::fs::canonicalize(state.path.as_ref().unwrap()).unwrap(),
231− )
232− .unwrap(),
233 language_id: "rust".to_string(), // TODO: hardcoded for now
231 language_id: "rust".to_string(), // TODO: hardcoded for now
234 version: 0,
232 version: 0,
235 text: String::from(&state.doc),
233 text: String::from(&state.doc),
@@ -243,11 +241,12 @@ impl Client {
243 &mut self,
241 &mut self,
244 state: &helix_core::State,
242 state: &helix_core::State,
245 ) -> anyhow::Result<()> {
243 ) -> anyhow::Result<()> {
246− self.notify::<lsp::notification::DidSaveTextDocument>(lsp::DidSaveTextDocumentParams {
244+ self.notify::<lsp::notification::DidChangeTextDocument>(lsp::DidChangeTextDocumentParams {
247− text_document: lsp::TextDocumentIdentifier::new(
245+ text_document: lsp::VersionedTextDocumentIdentifier::new(
248− lsp::Url::from_file_path(state.path.as_ref().unwrap()).unwrap(),
246+ lsp::Url::from_file_path(state.path().unwrap()).unwrap(),
247+ 0, // TODO: version
249 ),
248 ),
250− text: None, // TODO?
249+ content_changes: vec![], // TODO:
251 })
250 })
252 .await
251 .await
253 }
252 }
helix-lsp/src/transport.rs+7−7
@@ -24,7 +24,7 @@ pub(crate) enum Payload {
24}
24}
25
25
26pub(crate) struct Transport {
26pub(crate) struct Transport {
27− incoming: Sender<Message>,
27+ incoming: Sender<Notification>, // TODO Notification | Call
28 outgoing: Receiver<Payload>,
28 outgoing: Receiver<Payload>,
29
29
30 pending_requests: HashMap<jsonrpc::Id, Sender<anyhow::Result<Value>>>,
30 pending_requests: HashMap<jsonrpc::Id, Sender<anyhow::Result<Value>>>,
@@ -39,7 +39,7 @@ impl Transport {
39 ex: &Executor,
39 ex: &Executor,
40 reader: BufReader<ChildStdout>,
40 reader: BufReader<ChildStdout>,
41 writer: BufWriter<ChildStdin>,
41 writer: BufWriter<ChildStdin>,
42− ) -> (Receiver<Message>, Sender<Payload>) {
42+ ) -> (Receiver<Notification>, Sender<Payload>) {
43 let (incoming, rx) = smol::channel::unbounded();
43 let (incoming, rx) = smol::channel::unbounded();
44 let (tx, outgoing) = smol::channel::unbounded();
44 let (tx, outgoing) = smol::channel::unbounded();
45
45
@@ -111,7 +111,7 @@ impl Transport {
111 }
111 }
112
112
113 pub async fn send(&mut self, request: String) -> anyhow::Result<()> {
113 pub async fn send(&mut self, request: String) -> anyhow::Result<()> {
114− println!("-> {}", request);
114+ // println!("-> {}", request);
115
115
116 // send the headers
116 // send the headers
117 self.writer
117 self.writer
@@ -132,11 +132,11 @@ impl Transport {
132 Message::Notification(jsonrpc::Notification { method, params, .. }) => {
132 Message::Notification(jsonrpc::Notification { method, params, .. }) => {
133 let notification = Notification::parse(&method, params);
133 let notification = Notification::parse(&method, params);
134
134
135− println!("<- {} {:?}", method, notification);
135+ // println!("<- {} {:?}", method, notification);
136− // dispatch
136+ self.incoming.send(notification).await?;
137 }
137 }
138 Message::Call(call) => {
138 Message::Call(call) => {
139− println!("<- {:?}", call);
139+ // println!("<- {:?}", call);
140 // dispatch
140 // dispatch
141 }
141 }
142 _ => unreachable!(),
142 _ => unreachable!(),
@@ -147,7 +147,7 @@ impl Transport {
147 pub async fn recv_response(&mut self, output: jsonrpc::Output) -> anyhow::Result<()> {
147 pub async fn recv_response(&mut self, output: jsonrpc::Output) -> anyhow::Result<()> {
148 match output {
148 match output {
149 jsonrpc::Output::Success(jsonrpc::Success { id, result, .. }) => {
149 jsonrpc::Output::Success(jsonrpc::Success { id, result, .. }) => {
150− println!("<- {}", result);
150+ // println!("<- {}", result);
151
151
152 let tx = self
152 let tx = self
153 .pending_requests
153 .pending_requests
helix-term/Cargo.toml+2
@@ -24,3 +24,5 @@ num_cpus = "1.13"
24tui = { git = "https://github.com/fdehau/tui-rs", default-features = false, features = ["crossterm"] }
24tui = { git = "https://github.com/fdehau/tui-rs", default-features = false, features = ["crossterm"] }
25crossterm = { version = "0.18", features = ["event-stream"] }
25crossterm = { version = "0.18", features = ["event-stream"] }
26clap = { version = "3.0.0-beta.2 ", default-features = false, features = ["std", "cargo"] }
26clap = { version = "3.0.0-beta.2 ", default-features = false, features = ["std", "cargo"] }
27+
28+futures-util = "0.3"
helix-term/src/application.rs+162−119
@@ -1,6 +1,11 @@
1use clap::ArgMatches as Args;
1use clap::ArgMatches as Args;
2use helix_core::{indent::TAB_WIDTH, state::Mode, syntax::HighlightEvent, Position, Range, State};
2use helix_core::{indent::TAB_WIDTH, state::Mode, syntax::HighlightEvent, Position, Range, State};
3+use helix_view::{
4+ commands,
5+ keymap::{self, Keymaps},
6+ prompt::Prompt,
3−use helix_view::{commands, keymap, prompt::Prompt, Editor, Theme, View};
7+ Editor, Theme, View,
8+};
4
9
5use std::{
10use std::{
6 borrow::Cow,
11 borrow::Cow,
@@ -31,14 +36,16 @@ const OFFSET: u16 = 6; // 5 linenr + 1 gutter
31
36
32type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
37type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
33
38
34−static EX: smol::Executor = smol::Executor::new();
35−
36const BASE_WIDTH: u16 = 30;
39const BASE_WIDTH: u16 = 30;
37
40
38−pub struct Application {
41+pub struct Application<'a> {
39 editor: Editor,
42 editor: Editor,
40 prompt: Option<Prompt>,
43 prompt: Option<Prompt>,
41 terminal: Renderer,
44 terminal: Renderer,
45+
46+ keymap: Keymaps,
47+ executor: &'a smol::Executor<'a>,
48+ lsp: helix_lsp::Client,
42}
49}
43
50
44struct Renderer {
51struct Renderer {
@@ -235,7 +242,7 @@ impl Renderer {
235 .set_string(1, self.size.1 - 2, mode, self.text_color);
242 .set_string(1, self.size.1 - 2, mode, self.text_color);
236 }
243 }
237
244
238− pub fn render_prompt(&mut self, view: &View, prompt: &Prompt) {
245+ pub fn render_prompt(&mut self, view: &View, prompt: &Prompt, theme: &Theme) {
239 // completion
246 // completion
240 if !prompt.completion.is_empty() {
247 if !prompt.completion.is_empty() {
241 // TODO: find out better way of clearing individual lines of the screen
248 // TODO: find out better way of clearing individual lines of the screen
@@ -254,7 +261,7 @@ impl Renderer {
254 }
261 }
255 self.surface.set_style(
262 self.surface.set_style(
256 Rect::new(0, self.size.1 - col_height - 2, self.size.0, col_height),
263 Rect::new(0, self.size.1 - col_height - 2, self.size.0, col_height),
257− view.theme.get("ui.statusline"),
264+ theme.get("ui.statusline"),
258 );
265 );
259 for (i, command) in prompt.completion.iter().enumerate() {
266 for (i, command) in prompt.completion.iter().enumerate() {
260 let color = if prompt.completion_selection_index.is_some()
267 let color = if prompt.completion_selection_index.is_some()
@@ -330,8 +337,8 @@ impl Renderer {
330 }
337 }
331}
338}
332
339
333−impl Application {
340+impl<'a> Application<'a> {
334− pub fn new(mut args: Args) -> Result<Self, Error> {
341+ pub fn new(mut args: Args, executor: &'a smol::Executor<'a>) -> Result<Self, Error> {
335 let terminal = Renderer::new()?;
342 let terminal = Renderer::new()?;
336 let mut editor = Editor::new();
343 let mut editor = Editor::new();
337
344
@@ -339,11 +346,18 @@ impl Application {
339 editor.open(file, terminal.size)?;
346 editor.open(file, terminal.size)?;
340 }
347 }
341
348
349+ let lsp = helix_lsp::Client::start(&executor, "rust-analyzer", &[]);
350+
342 let mut app = Self {
351 let mut app = Self {
343 editor,
352 editor,
344 terminal,
353 terminal,
345 // TODO; move to state
354 // TODO; move to state
346 prompt: None,
355 prompt: None,
356+
357+ //
358+ keymap: keymap::default(),
359+ executor,
360+ lsp,
347 };
361 };
348
362
349 Ok(app)
363 Ok(app)
@@ -361,7 +375,7 @@ impl Application {
361 if prompt.should_close {
375 if prompt.should_close {
362 self.prompt = None;
376 self.prompt = None;
363 } else {
377 } else {
364− self.terminal.render_prompt(view, prompt);
378+ self.terminal.render_prompt(view, prompt, theme_ref);
365 }
379 }
366 }
380 }
367 }
381 }
@@ -375,7 +389,13 @@ impl Application {
375
389
376 pub async fn event_loop(&mut self) {
390 pub async fn event_loop(&mut self) {
377 let mut reader = EventStream::new();
391 let mut reader = EventStream::new();
378− let keymap = keymap::default();
392+
393+ // initialize lsp
394+ let res = self.lsp.initialize().await;
395+ let res = self
396+ .lsp
397+ .text_document_did_open(&self.editor.view().unwrap().state)
398+ .await;
379
399
380 self.render();
400 self.render();
381
401
@@ -384,126 +404,149 @@ impl Application {
384 break;
404 break;
385 }
405 }
386
406
387− // Handle key events
407+ use futures_util::{select, FutureExt};
388− match reader.next().await {
408+ select! {
389− Some(Ok(Event::Resize(width, height))) => {
409+ event = reader.next().fuse() => {
390− self.terminal.resize(width, height);
410+ self.handle_terminal_events(event).await
411+ }
412+ notification = self.lsp.incoming.next().fuse() => {
413+ self.handle_lsp_notification(notification).await
414+ }
415+ }
416+ }
417+ }
391
418
419+ pub async fn handle_terminal_events(
420+ &mut self,
421+ event: Option<Result<Event, crossterm::ErrorKind>>,
422+ ) {
423+ // Handle key events
424+ match event {
425+ Some(Ok(Event::Resize(width, height))) => {
426+ self.terminal.resize(width, height);
427+
392− // TODO: simplistic ensure cursor in view for now
428+ // TODO: simplistic ensure cursor in view for now
393− // TODO: loop over views
429+ // TODO: loop over views
394− if let Some(view) = self.editor.view_mut() {
430+ if let Some(view) = self.editor.view_mut() {
395− view.size = self.terminal.size;
431+ view.size = self.terminal.size;
396− view.ensure_cursor_in_view()
432+ view.ensure_cursor_in_view()
397− };
433+ };
434+
435+ self.render();
436+ }
437+ Some(Ok(Event::Key(event))) => {
438+ // if there's a prompt, it takes priority
439+ if let Some(prompt) = &mut self.prompt {
440+ self.prompt
441+ .as_mut()
442+ .unwrap()
443+ .handle_input(event, &mut self.editor);
398
444
399 self.render();
445 self.render();
400− }
401− Some(Ok(Event::Key(event))) => {
402− // if there's a prompt, it takes priority
403− if let Some(prompt) = &mut self.prompt {
404− self.prompt
405− .as_mut()
406− .unwrap()
407− .handle_input(event, &mut self.editor);
408−
409− self.render();
410− } else if let Some(view) = self.editor.view_mut() {
446+ } else if let Some(view) = self.editor.view_mut() {
411− let keys = vec![event];
447+ let keys = vec![event];
412− // TODO: sequences (`gg`)
448+ // TODO: sequences (`gg`)
413− // TODO: handle count other than 1
449+ // TODO: handle count other than 1
414− match view.state.mode() {
450+ match view.state.mode() {
415− Mode::Insert => {
451+ Mode::Insert => {
416− if let Some(command) = keymap[&Mode::Insert].get(&keys) {
452+ if let Some(command) = self.keymap[&Mode::Insert].get(&keys) {
417− command(view, 1);
453+ command(view, 1);
418− } else if let KeyEvent {
454+ } else if let KeyEvent {
419− code: KeyCode::Char(c),
455+ code: KeyCode::Char(c),
420− ..
456+ ..
421− } = event
457+ } = event
422− {
458+ {
423− commands::insert::insert_char(view, c);
459+ commands::insert::insert_char(view, c);
424− }
425− view.ensure_cursor_in_view();
426 }
460 }
461+ view.ensure_cursor_in_view();
462+ }
427− Mode::Normal => {
463+ Mode::Normal => {
428− if let &[KeyEvent {
464+ if let &[KeyEvent {
429− code: KeyCode::Char(':'),
465+ code: KeyCode::Char(':'),
430− ..
466+ ..
431− }] = keys.as_slice()
467+ }] = keys.as_slice()
432− {
468+ {
433− let prompt = Prompt::new(
469+ let prompt = Prompt::new(
434− ":".to_owned(),
470+ ":".to_owned(),
435− |_input: &str| {
471+ |_input: &str| {
436− // TODO: i need this duplicate list right now to avoid borrow checker issues
472+ // TODO: i need this duplicate list right now to avoid borrow checker issues
437− let command_list = vec![
473+ let command_list = vec![
438− String::from("q"),
474+ String::from("q"),
439− String::from("aaa"),
475+ String::from("aaa"),
440− String::from("bbb"),
476+ String::from("bbb"),
441− String::from("ccc"),
477+ String::from("ccc"),
442− String::from("ddd"),
478+ String::from("ddd"),
443− String::from("eee"),
479+ String::from("eee"),
444− String::from("averylongcommandaverylongcommandaverylongcommandaverylongcommandaverylongcommand"),
480+ String::from("averylongcommandaverylongcommandaverylongcommandaverylongcommandaverylongcommand"),
445− String::from("q"),
481+ String::from("q"),
446− String::from("aaa"),
482+ String::from("aaa"),
447− String::from("bbb"),
483+ String::from("bbb"),
448− String::from("ccc"),
484+ String::from("ccc"),
449− String::from("ddd"),
485+ String::from("ddd"),
450− String::from("eee"),
486+ String::from("eee"),
451− String::from("q"),
487+ String::from("q"),
452− String::from("aaa"),
488+ String::from("aaa"),
453− String::from("bbb"),
489+ String::from("bbb"),
454− String::from("ccc"),
490+ String::from("ccc"),
455− String::from("ddd"),
491+ String::from("ddd"),
456− String::from("eee"),
492+ String::from("eee"),
457− String::from("q"),
493+ String::from("q"),
458− String::from("aaa"),
494+ String::from("aaa"),
459− String::from("bbb"),
495+ String::from("bbb"),
460− String::from("ccc"),
496+ String::from("ccc"),
461− String::from("ddd"),
497+ String::from("ddd"),
462− String::from("eee"),
498+ String::from("eee"),
463− String::from("q"),
499+ String::from("q"),
464− String::from("aaa"),
500+ String::from("aaa"),
465− String::from("bbb"),
501+ String::from("bbb"),
466− String::from("ccc"),
502+ String::from("ccc"),
467− String::from("ddd"),
503+ String::from("ddd"),
468− String::from("eee"),
504+ String::from("eee"),
469− ];
505+ ];
470− command_list
506+ command_list
471− .into_iter()
507+ .into_iter()
472− .filter(|command| command.contains(_input))
508+ .filter(|command| command.contains(_input))
473− .collect()
509+ .collect()
474− }, // completion
510+ }, // completion
475− |editor: &mut Editor, input: &str| match input {
511+ |editor: &mut Editor, input: &str| match input {
476− "q" => editor.should_close = true,
512+ "q" => editor.should_close = true,
477− _ => (),
513+ _ => (),
478− },
514+ },
479− );
515+ );
480−
516+
481− self.prompt = Some(prompt);
517+ self.prompt = Some(prompt);
482−
518+
483− // HAXX: special casing for command mode
519+ // HAXX: special casing for command mode
484− } else if let Some(command) = keymap[&Mode::Normal].get(&keys) {
520+ } else if let Some(command) = self.keymap[&Mode::Normal].get(&keys) {
485− command(view, 1);
521+ command(view, 1);
486−
522+
487− // TODO: simplistic ensure cursor in view for now
523+ // TODO: simplistic ensure cursor in view for now
488− view.ensure_cursor_in_view();
524+ view.ensure_cursor_in_view();
489− }
490 }
525 }
491− mode => {
526+ }
527+ mode => {
492− if let Some(command) = keymap[&mode].get(&keys) {
528+ if let Some(command) = self.keymap[&mode].get(&keys) {
493− command(view, 1);
529+ command(view, 1);
494
530
495− // TODO: simplistic ensure cursor in view for now
531+ // TODO: simplistic ensure cursor in view for now
496− view.ensure_cursor_in_view();
532+ view.ensure_cursor_in_view();
497− }
498 }
533 }
499 }
534 }
500− self.render();
501 }
535 }
536+ self.render();
502 }
537 }
503− Some(Ok(Event::Mouse(_))) => (), // unhandled
504− Some(Err(x)) => panic!(x),
505− None => break,
506 }
538 }
539+ Some(Ok(Event::Mouse(_))) => (), // unhandled
540+ Some(Err(x)) => panic!(x),
541+ None => panic!(),
542+ };
543+ }
544+
545+ pub async fn handle_lsp_notification(&mut self, notification: Option<helix_lsp::Notification>) {
546+ use helix_lsp::Notification;
547+ match notification {
548+ Some(Notification::PublishDiagnostics(params)) => unimplemented!("{:?}", params),
549+ _ => unreachable!(),
507 }
550 }
508 }
551 }
509
552
helix-term/src/main.rs+6−6
@@ -26,15 +26,15 @@ fn main() -> Result<(), Error> {
26 std::thread::spawn(move || smol::block_on(EX.run(smol::future::pending::<()>())));
26 std::thread::spawn(move || smol::block_on(EX.run(smol::future::pending::<()>())));
27 }
27 }
28
28
29− let mut lsp = helix_lsp::Client::start(&EX, "rust-analyzer", &[]);
29+ // let mut lsp = helix_lsp::Client::start(&EX, "rust-analyzer", &[]);
30
30
31 smol::block_on(async {
31 smol::block_on(async {
32− let res = lsp.initialize().await;
32+ // let res = lsp.initialize().await;
33− let state = helix_core::State::load("test.rs".into(), &[]).unwrap();
33+ // let state = helix_core::State::load("test.rs".into(), &[]).unwrap();
34− let res = lsp.text_document_did_open(&state).await;
34+ // let res = lsp.text_document_did_open(&state).await;
35− loop {}
35+ // loop {}
36
36
37− // Application::new(args).unwrap().run().await;
37+ Application::new(args, &EX).unwrap().run().await;
38 });
38 });
39
39
40 Ok(())
40 Ok(())
helix-view/src/keymap.rs+2−2
@@ -87,8 +87,8 @@ use std::collections::HashMap;
87pub use crossterm::event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers};
87pub use crossterm::event::{KeyCode, KeyEvent as Key, KeyModifiers as Modifiers};
88
88
89// TODO: could be trie based
89// TODO: could be trie based
90−type Keymap = HashMap<Vec<Key>, Command>;
90+pub type Keymap = HashMap<Vec<Key>, Command>;
91−type Keymaps = HashMap<state::Mode, Keymap>;
91+pub type Keymaps = HashMap<state::Mode, Keymap>;
92
92
93macro_rules! key {
93macro_rules! key {
94 ($ch:expr) => {
94 ($ch:expr) => {
helix-view/src/view.rs+1−1
@@ -18,7 +18,7 @@ pub struct View {
18 pub first_line: usize,
18 pub first_line: usize,
19 pub size: (u16, u16),
19 pub size: (u16, u16),
20
20
21− // TODO: Doc<> fields
21+ // TODO: Doc fields
22 pub history: History,
22 pub history: History,
23}
23}
24
24