diff --git a/helix-core/src/diagnostic.rs b/helix-core/src/diagnostic.rs index 5056c26a..cf58b9af 100644 --- a/helix-core/src/diagnostic.rs +++ b/helix-core/src/diagnostic.rs @@ -1,3 +1,4 @@ +#[derive(Eq, PartialEq)] pub enum Severity { Error, Warning, diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index a273fc6f..eab9397c 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -42,7 +42,6 @@ pub struct Context<'a> { pub callback: Option, pub on_next_key_callback: Option>, pub callbacks: &'a mut LspCallbacks, - pub status_msg: Option, } impl<'a> Context<'a> { @@ -97,11 +96,6 @@ impl<'a> Context<'a> { }); self.callbacks.push(callback); } - - // TODO: allow &'static str? - pub fn set_status(&mut self, msg: String) { - self.status_msg = Some(msg); - } } /// A command is a function that takes the current state and a count, and does a side-effect on the @@ -852,6 +846,8 @@ pub fn command_mode(cx: &mut Context) { } }, // completion move |editor: &mut Editor, input: &str, event: PromptEvent| { + use helix_view::editor::Action; + if event != PromptEvent::Validate { return; } @@ -863,16 +859,20 @@ pub fn command_mode(cx: &mut Context) { editor.close(editor.view().id); } ["o", path] | ["open", path] => { - use helix_view::editor::Action; editor.open(path.into(), Action::Replace); } ["w"] | ["write"] => { - // TODO: non-blocking via save() command let id = editor.view().doc; let doc = &mut editor.documents[id]; + if doc.path().is_none() { + editor.set_error("cannot write a buffer without a filename".to_string()); + return; + } tokio::spawn(doc.save()); } - + ["new"] => { + editor.new_file(Action::Replace); + } _ => (), } }, @@ -1585,7 +1585,7 @@ pub fn yank(cx: &mut Context) { register::set(reg, values); - cx.set_status(msg) + cx.editor.set_status(msg) } #[derive(Copy, Clone)] diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 49024226..79a6ede2 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -28,7 +28,6 @@ use tui::{ pub struct EditorView { keymap: Keymaps, on_next_key: Option>, - status_msg: Option, last_insert: (commands::Command, Vec), completion: Option, } @@ -40,7 +39,6 @@ impl EditorView { Self { keymap: keymap::default(), on_next_key: None, - status_msg: None, last_insert: (commands::normal_mode, Vec::new()), completion: None, } @@ -86,17 +84,6 @@ impl EditorView { 1, ); self.render_statusline(doc, view, area, surface, theme, is_focused); - - // render status - if let Some(status_msg) = &self.status_msg { - let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender - surface.set_string( - view.area.x, - view.area.y + view.area.height, - status_msg, - style, - ); - } } pub fn render_buffer( @@ -537,6 +524,9 @@ impl Component for EditorView { EventResult::Consumed(None) } Event::Key(key) => { + // clear status + cx.editor.status_msg = None; + let (view, doc) = cx.editor.current(); let mode = doc.mode(); @@ -547,12 +537,8 @@ impl Component for EditorView { callback: None, callbacks: cx.callbacks, on_next_key_callback: None, - status_msg: None, }; - // clear status - self.status_msg = None; - if let Some(on_next_key) = self.on_next_key.take() { // if there's a command waiting input, do that first on_next_key(&mut cxt, key); @@ -602,7 +588,6 @@ impl Component for EditorView { } self.on_next_key = cxt.on_next_key_callback.take(); - self.status_msg = cxt.status_msg.take(); // appease borrowck let callback = cxt.callback.take(); @@ -641,6 +626,23 @@ impl Component for EditorView { self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused); } + // render status msg + if let Some((status_msg, severity)) = &cx.editor.status_msg { + use helix_view::editor::Severity; + let style = if *severity == Severity::Error { + cx.editor.theme.get("error") + } else { + Style::default().fg(Color::Rgb(164, 160, 232)) // lavender + }; + + surface.set_string( + area.x, + area.y + area.height.saturating_sub(1), + status_msg, + style, + ); + } + if let Some(completion) = &self.completion { completion.render(area, surface, cx) // render completion here diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index 83208f78..e9f027f3 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -7,12 +7,16 @@ use slotmap::SlotMap; use anyhow::Error; +pub use helix_core::diagnostic::Severity; + pub struct Editor { pub tree: Tree, pub documents: SlotMap, pub count: Option, pub theme: Theme, pub language_servers: helix_lsp::Registry, + + pub status_msg: Option<(String, Severity)>, } #[derive(Copy, Clone)] @@ -43,9 +47,18 @@ impl Editor { count: None, theme, language_servers, + status_msg: None, } } + pub fn set_status(&mut self, status: String) { + self.status_msg = Some((status, Severity::Info)); + } + + pub fn set_error(&mut self, error: String) { + self.status_msg = Some((error, Severity::Error)); + } + fn _refresh(&mut self) { for (view, _) in self.tree.views_mut() { let doc = &self.documents[view.doc];