on master help sign in
Add the :new command, don't crash if saving without filename.
commit7c915dc0651f2cd69bc40adca027729c3b12f4e3 authorBlaž Hrastnik <blaz@mxxn.io> dateFri 7 May 2021, 14:19 (5 years ago) parentf8844c6
4 files changed+44−28
helix-core/src/diagnostic.rs+1 helix-term/src/commands.rs+10−10 helix-term/src/ui/editor.rs+20−18 helix-view/src/editor.rs+13
helix-core/src/diagnostic.rs+1
@@ -1,3 +1,4 @@
1+#[derive(Eq, PartialEq)]
12pub enum Severity {
23 Error,
34 Warning,
helix-term/src/commands.rs+10−10
@@ -42,7 +42,6 @@ pub struct Context<'a> {
4242 pub callback: Option<crate::compositor::Callback>,
4343 pub on_next_key_callback: Option<Box<dyn FnOnce(&mut Context, KeyEvent)>>,
4444 pub callbacks: &'a mut LspCallbacks,
45− pub status_msg: Option<String>,
4645}
4746
4847impl<'a> Context<'a> {
@@ -97,11 +96,6 @@ impl<'a> Context<'a> {
9796 });
9897 self.callbacks.push(callback);
9998 }
100−
101− // TODO: allow &'static str?
102− pub fn set_status(&mut self, msg: String) {
103− self.status_msg = Some(msg);
104− }
10599}
106100
107101/// 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) {
852846 }
853847 }, // completion
854848 move |editor: &mut Editor, input: &str, event: PromptEvent| {
849+ use helix_view::editor::Action;
850+
855851 if event != PromptEvent::Validate {
856852 return;
857853 }
@@ -863,16 +859,20 @@ pub fn command_mode(cx: &mut Context) {
863859 editor.close(editor.view().id);
864860 }
865861 ["o", path] | ["open", path] => {
866− use helix_view::editor::Action;
867862 editor.open(path.into(), Action::Replace);
868863 }
869864 ["w"] | ["write"] => {
870− // TODO: non-blocking via save() command
871865 let id = editor.view().doc;
872866 let doc = &mut editor.documents[id];
867+ if doc.path().is_none() {
868+ editor.set_error("cannot write a buffer without a filename".to_string());
869+ return;
870+ }
873871 tokio::spawn(doc.save());
874872 }
875−
873+ ["new"] => {
874+ editor.new_file(Action::Replace);
875+ }
876876 _ => (),
877877 }
878878 },
@@ -1585,7 +1585,7 @@ pub fn yank(cx: &mut Context) {
15851585
15861586 register::set(reg, values);
15871587
1588− cx.set_status(msg)
1588+ cx.editor.set_status(msg)
15891589}
15901590
15911591#[derive(Copy, Clone)]
helix-term/src/ui/editor.rs+20−18
@@ -28,7 +28,6 @@ use tui::{
2828pub struct EditorView {
2929 keymap: Keymaps,
3030 on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
31− status_msg: Option<String>,
3231 last_insert: (commands::Command, Vec<KeyEvent>),
3332 completion: Option<Completion>,
3433}
@@ -40,7 +39,6 @@ impl EditorView {
4039 Self {
4140 keymap: keymap::default(),
4241 on_next_key: None,
43− status_msg: None,
4442 last_insert: (commands::normal_mode, Vec::new()),
4543 completion: None,
4644 }
@@ -86,17 +84,6 @@ impl EditorView {
8684 1,
8785 );
8886 self.render_statusline(doc, view, area, surface, theme, is_focused);
89−
90− // render status
91− if let Some(status_msg) = &self.status_msg {
92− let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender
93− surface.set_string(
94− view.area.x,
95− view.area.y + view.area.height,
96− status_msg,
97− style,
98− );
99− }
10087 }
10188
10289 pub fn render_buffer(
@@ -537,6 +524,9 @@ impl Component for EditorView {
537524 EventResult::Consumed(None)
538525 }
539526 Event::Key(key) => {
527+ // clear status
528+ cx.editor.status_msg = None;
529+
540530 let (view, doc) = cx.editor.current();
541531 let mode = doc.mode();
542532
@@ -547,12 +537,8 @@ impl Component for EditorView {
547537 callback: None,
548538 callbacks: cx.callbacks,
549539 on_next_key_callback: None,
550− status_msg: None,
551540 };
552541
553− // clear status
554− self.status_msg = None;
555−
556542 if let Some(on_next_key) = self.on_next_key.take() {
557543 // if there's a command waiting input, do that first
558544 on_next_key(&mut cxt, key);
@@ -602,7 +588,6 @@ impl Component for EditorView {
602588 }
603589
604590 self.on_next_key = cxt.on_next_key_callback.take();
605− self.status_msg = cxt.status_msg.take();
606591 // appease borrowck
607592 let callback = cxt.callback.take();
608593
@@ -641,6 +626,23 @@ impl Component for EditorView {
641626 self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
642627 }
643628
629+ // render status msg
630+ if let Some((status_msg, severity)) = &cx.editor.status_msg {
631+ use helix_view::editor::Severity;
632+ let style = if *severity == Severity::Error {
633+ cx.editor.theme.get("error")
634+ } else {
635+ Style::default().fg(Color::Rgb(164, 160, 232)) // lavender
636+ };
637+
638+ surface.set_string(
639+ area.x,
640+ area.y + area.height.saturating_sub(1),
641+ status_msg,
642+ style,
643+ );
644+ }
645+
644646 if let Some(completion) = &self.completion {
645647 completion.render(area, surface, cx)
646648 // render completion here
helix-view/src/editor.rs+13
@@ -7,12 +7,16 @@ use slotmap::SlotMap;
77
88use anyhow::Error;
99
10+pub use helix_core::diagnostic::Severity;
11+
1012pub struct Editor {
1113 pub tree: Tree,
1214 pub documents: SlotMap<DocumentId, Document>,
1315 pub count: Option<usize>,
1416 pub theme: Theme,
1517 pub language_servers: helix_lsp::Registry,
18+
19+ pub status_msg: Option<(String, Severity)>,
1620}
1721
1822#[derive(Copy, Clone)]
@@ -43,9 +47,18 @@ impl Editor {
4347 count: None,
4448 theme,
4549 language_servers,
50+ status_msg: None,
4651 }
4752 }
4853
54+ pub fn set_status(&mut self, status: String) {
55+ self.status_msg = Some((status, Severity::Info));
56+ }
57+
58+ pub fn set_error(&mut self, error: String) {
59+ self.status_msg = Some((error, Severity::Error));
60+ }
61+
4962 fn _refresh(&mut self) {
5063 for (view, _) in self.tree.views_mut() {
5164 let doc = &self.documents[view.doc];