on master help sign in
Allow static strings in set_status/set_error so API is nicer
d11b652Blaž Hrastnik
helix-term/src/application.rs+1−2
@@ -468,8 +468,7 @@ impl Application {
468 // TODO: fetch breakpoints (in case we're attaching)
468 // TODO: fetch breakpoints (in case we're attaching)
469
469
470 if debugger.configuration_done().await.is_ok() {
470 if debugger.configuration_done().await.is_ok() {
471− self.editor
472− .set_status("Debugged application started".to_owned());
471+ self.editor.set_status("Debugged application started");
473 }; // TODO: do we need to handle error?
472 }; // TODO: do we need to handle error?
474 }
473 }
475 ev => {
474 ev => {
helix-term/src/commands.rs+31−33
@@ -776,9 +776,8 @@ fn trim_selections(cx: &mut Context) {
776fn align_selections(cx: &mut Context) {
776fn align_selections(cx: &mut Context) {
777 let align_style = cx.count();
777 let align_style = cx.count();
778 if align_style > 3 {
778 if align_style > 3 {
779− cx.editor.set_error(
779+ cx.editor
780− "align only accept 1,2,3 as count to set left/center/right align".to_string(),
780+ .set_error("align only accept 1,2,3 as count to set left/center/right align");
781− );
782 return;
781 return;
783 }
782 }
784
783
@@ -793,7 +792,7 @@ fn align_selections(cx: &mut Context) {
793 let (l1, l2) = sel.line_range(text);
792 let (l1, l2) = sel.line_range(text);
794 if l1 != l2 {
793 if l1 != l2 {
795 cx.editor
794 cx.editor
796− .set_error("align cannot work with multi line selections".to_string());
795+ .set_error("align cannot work with multi line selections");
797 return;
796 return;
798 }
797 }
799 // if the selection is not in the same line with last selection, we set the column to 0
798 // if the selection is not in the same line with last selection, we set the column to 0
@@ -1790,7 +1789,7 @@ fn global_search(cx: &mut Context) {
1790 let call: job::Callback =
1789 let call: job::Callback =
1791 Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
1790 Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
1792 if all_matches.is_empty() {
1791 if all_matches.is_empty() {
1793− editor.set_status("No matches found".to_string());
1792+ editor.set_status("No matches found");
1794 return;
1793 return;
1795 }
1794 }
1796
1795
@@ -2177,10 +2176,10 @@ pub mod cmd {
2177 if args.is_empty() {
2176 if args.is_empty() {
2178 let style = doc!(cx.editor).indent_style;
2177 let style = doc!(cx.editor).indent_style;
2179 cx.editor.set_status(match style {
2178 cx.editor.set_status(match style {
2180− Tabs => "tabs".into(),
2179+ Tabs => "tabs".to_owned(),
2181− Spaces(1) => "1 space".into(),
2180+ Spaces(1) => "1 space".to_owned(),
2182 Spaces(n) if (2..=8).contains(&n) => format!("{} spaces", n),
2181 Spaces(n) if (2..=8).contains(&n) => format!("{} spaces", n),
2183− _ => "error".into(), // Shouldn't happen.
2182+ _ => unreachable!(), // Shouldn't happen.
2184 });
2183 });
2185 return Ok(());
2184 return Ok(());
2186 }
2185 }
@@ -2216,14 +2215,14 @@ pub mod cmd {
2216 if args.is_empty() {
2215 if args.is_empty() {
2217 let line_ending = doc!(cx.editor).line_ending;
2216 let line_ending = doc!(cx.editor).line_ending;
2218 cx.editor.set_status(match line_ending {
2217 cx.editor.set_status(match line_ending {
2219− Crlf => "crlf".into(),
2218+ Crlf => "crlf",
2220− LF => "line feed".into(),
2219+ LF => "line feed",
2221− FF => "form feed".into(),
2220+ FF => "form feed",
2222− CR => "carriage return".into(),
2221+ CR => "carriage return",
2223− Nel => "next line".into(),
2222+ Nel => "next line",
2224
2223
2225 // These should never be a document's default line ending.
2224 // These should never be a document's default line ending.
2226− VT | LS | PS => "error".into(),
2225+ VT | LS | PS => "error",
2227 });
2226 });
2228
2227
2229 return Ok(());
2228 return Ok(());
@@ -2259,7 +2258,7 @@ pub mod cmd {
2259 let (view, doc) = current!(cx.editor);
2258 let (view, doc) = current!(cx.editor);
2260 let success = doc.earlier(view.id, uk);
2259 let success = doc.earlier(view.id, uk);
2261 if !success {
2260 if !success {
2262− cx.editor.set_status("Already at oldest change".to_owned());
2261+ cx.editor.set_status("Already at oldest change");
2263 }
2262 }
2264
2263
2265 Ok(())
2264 Ok(())
@@ -2274,7 +2273,7 @@ pub mod cmd {
2274 let (view, doc) = current!(cx.editor);
2273 let (view, doc) = current!(cx.editor);
2275 let success = doc.later(view.id, uk);
2274 let success = doc.later(view.id, uk);
2276 if !success {
2275 if !success {
2277− cx.editor.set_status("Already at newest change".to_owned());
2276+ cx.editor.set_status("Already at newest change");
2278 }
2277 }
2279
2278
2280 Ok(())
2279 Ok(())
@@ -2634,7 +2633,7 @@ pub mod cmd {
2634 if let Some(label) = args.first() {
2633 if let Some(label) = args.first() {
2635 doc.set_encoding(label)
2634 doc.set_encoding(label)
2636 } else {
2635 } else {
2637− let encoding = doc.encoding().name().to_string();
2636+ let encoding = doc.encoding().name().to_owned();
2638 cx.editor.set_status(encoding);
2637 cx.editor.set_status(encoding);
2639 Ok(())
2638 Ok(())
2640 }
2639 }
@@ -3612,7 +3611,7 @@ pub fn code_action(cx: &mut Context) {
3612 None => return,
3611 None => return,
3613 };
3612 };
3614 if actions.is_empty() {
3613 if actions.is_empty() {
3615− editor.set_status("No code actions available".to_owned());
3614+ editor.set_status("No code actions available");
3616 return;
3615 return;
3617 }
3616 }
3618
3617
@@ -3836,7 +3835,7 @@ fn last_picker(cx: &mut Context) {
3836 compositor.push(picker);
3835 compositor.push(picker);
3837 }
3836 }
3838 // XXX: figure out how to show error when no last picker lifetime
3837 // XXX: figure out how to show error when no last picker lifetime
3839− // cx.editor.set_error("no last picker".to_owned())
3838+ // cx.editor.set_error("no last picker")
3840 }));
3839 }));
3841}
3840}
3842
3841
@@ -4098,7 +4097,7 @@ fn goto_last_accessed_file(cx: &mut Context) {
4098 if let Some(alt) = alternate_file {
4097 if let Some(alt) = alternate_file {
4099 cx.editor.switch(alt, Action::Replace);
4098 cx.editor.switch(alt, Action::Replace);
4100 } else {
4099 } else {
4101− cx.editor.set_error("no last accessed buffer".to_owned())
4100+ cx.editor.set_error("no last accessed buffer")
4102 }
4101 }
4103}
4102}
4104
4103
@@ -4125,7 +4124,7 @@ fn goto_last_modified_file(cx: &mut Context) {
4125 if let Some(alt) = alternate_file {
4124 if let Some(alt) = alternate_file {
4126 cx.editor.switch(alt, Action::Replace);
4125 cx.editor.switch(alt, Action::Replace);
4127 } else {
4126 } else {
4128− cx.editor.set_error("no last modified buffer".to_owned())
4127+ cx.editor.set_error("no last modified buffer")
4129 }
4128 }
4130}
4129}
4131
4130
@@ -4196,7 +4195,7 @@ fn goto_impl(
4196 jump_to(editor, location, offset_encoding, Action::Replace);
4195 jump_to(editor, location, offset_encoding, Action::Replace);
4197 }
4196 }
4198 [] => {
4197 [] => {
4199− editor.set_error("No definition found.".to_string());
4198+ editor.set_error("No definition found.");
4200 }
4199 }
4201 _locations => {
4200 _locations => {
4202 let picker = FilePicker::new(
4201 let picker = FilePicker::new(
@@ -4841,7 +4840,7 @@ fn undo(cx: &mut Context) {
4841 let (view, doc) = current!(cx.editor);
4840 let (view, doc) = current!(cx.editor);
4842 for _ in 0..count {
4841 for _ in 0..count {
4843 if !doc.undo(view.id) {
4842 if !doc.undo(view.id) {
4844− cx.editor.set_status("Already at oldest change".to_owned());
4843+ cx.editor.set_status("Already at oldest change");
4845 break;
4844 break;
4846 }
4845 }
4847 }
4846 }
@@ -4852,7 +4851,7 @@ fn redo(cx: &mut Context) {
4852 let (view, doc) = current!(cx.editor);
4851 let (view, doc) = current!(cx.editor);
4853 for _ in 0..count {
4852 for _ in 0..count {
4854 if !doc.redo(view.id) {
4853 if !doc.redo(view.id) {
4855− cx.editor.set_status("Already at newest change".to_owned());
4854+ cx.editor.set_status("Already at newest change");
4856 break;
4855 break;
4857 }
4856 }
4858 }
4857 }
@@ -4864,7 +4863,7 @@ fn earlier(cx: &mut Context) {
4864 for _ in 0..count {
4863 for _ in 0..count {
4865 // rather than doing in batch we do this so get error halfway
4864 // rather than doing in batch we do this so get error halfway
4866 if !doc.earlier(view.id, UndoKind::Steps(1)) {
4865 if !doc.earlier(view.id, UndoKind::Steps(1)) {
4867− cx.editor.set_status("Already at oldest change".to_owned());
4866+ cx.editor.set_status("Already at oldest change");
4868 break;
4867 break;
4869 }
4868 }
4870 }
4869 }
@@ -4876,7 +4875,7 @@ fn later(cx: &mut Context) {
4876 for _ in 0..count {
4875 for _ in 0..count {
4877 // rather than doing in batch we do this so get error halfway
4876 // rather than doing in batch we do this so get error halfway
4878 if !doc.later(view.id, UndoKind::Steps(1)) {
4877 if !doc.later(view.id, UndoKind::Steps(1)) {
4879− cx.editor.set_status("Already at newest change".to_owned());
4878+ cx.editor.set_status("Already at newest change");
4880 break;
4879 break;
4881 }
4880 }
4882 }
4881 }
@@ -4962,7 +4961,7 @@ fn yank_main_selection_to_clipboard_impl(
4962 bail!("Couldn't set system clipboard content: {}", e);
4961 bail!("Couldn't set system clipboard content: {}", e);
4963 }
4962 }
4964
4963
4965− editor.set_status("yanked main selection to system clipboard".to_owned());
4964+ editor.set_status("yanked main selection to system clipboard");
4966 Ok(())
4965 Ok(())
4967}
4966}
4968
4967
@@ -5399,7 +5398,7 @@ fn remove_primary_selection(cx: &mut Context) {
5399
5398
5400 let selection = doc.selection(view.id);
5399 let selection = doc.selection(view.id);
5401 if selection.len() == 1 {
5400 if selection.len() == 1 {
5402− cx.editor.set_error("no selections remaining".to_owned());
5401+ cx.editor.set_error("no selections remaining");
5403 return;
5402 return;
5404 }
5403 }
5405 let index = selection.primary_index();
5404 let index = selection.primary_index();
@@ -5506,7 +5505,7 @@ pub fn completion(cx: &mut Context) {
5506 }
5505 }
5507
5506
5508 if items.is_empty() {
5507 if items.is_empty() {
5509− // editor.set_error("No completion available".to_string());
5508+ // editor.set_error("No completion available");
5510 return;
5509 return;
5511 }
5510 }
5512 let size = compositor.size();
5511 let size = compositor.size();
@@ -5787,8 +5786,7 @@ fn jump_backward(cx: &mut Context) {
5787
5786
5788fn save_selection(cx: &mut Context) {
5787fn save_selection(cx: &mut Context) {
5789 push_jump(cx.editor);
5788 push_jump(cx.editor);
5790− cx.editor
5791− .set_status("Selection saved to jumplist".to_owned());
5789+ cx.editor.set_status("Selection saved to jumplist");
5792}
5790}
5793
5791
5794fn rotate_view(cx: &mut Context) {
5792fn rotate_view(cx: &mut Context) {
@@ -6161,7 +6159,7 @@ fn shell_keep_pipe(cx: &mut Context) {
6161 }
6159 }
6162
6160
6163 if ranges.is_empty() {
6161 if ranges.is_empty() {
6164− cx.editor.set_error("No selections remaining".to_string());
6162+ cx.editor.set_error("No selections remaining");
6165 return;
6163 return;
6166 }
6164 }
6167
6165
@@ -6247,7 +6245,7 @@ fn shell(cx: &mut Context, prompt: Cow<'static, str>, behavior: ShellBehavior) {
6247 };
6245 };
6248
6246
6249 if !success {
6247 if !success {
6250− cx.editor.set_error("Command failed".to_string());
6248+ cx.editor.set_error("Command failed");
6251 return;
6249 return;
6252 }
6250 }
6253
6251
helix-term/src/commands/dap.rs+10−12
@@ -298,8 +298,7 @@ pub fn dap_start_impl(
298
298
299pub fn dap_launch(cx: &mut Context) {
299pub fn dap_launch(cx: &mut Context) {
300 if cx.editor.debugger.is_some() {
300 if cx.editor.debugger.is_some() {
301− cx.editor
302− .set_error("Debugger is already running".to_string());
301+ cx.editor.set_error("Debugger is already running");
303 return;
302 return;
304 }
303 }
305
304
@@ -312,7 +311,7 @@ pub fn dap_launch(cx: &mut Context) {
312 Some(c) => c,
311 Some(c) => c,
313 None => {
312 None => {
314 cx.editor
313 cx.editor
315− .set_error("No debug adapter available for language".to_string());
314+ .set_error("No debug adapter available for language");
316 return;
315 return;
317 }
316 }
318 };
317 };
@@ -410,7 +409,7 @@ pub fn dap_toggle_breakpoint(cx: &mut Context) {
410 Some(path) => path.clone(),
409 Some(path) => path.clone(),
411 None => {
410 None => {
412 cx.editor
411 cx.editor
413− .set_error("Can't set breakpoint: document has no path".to_string());
412+ .set_error("Can't set breakpoint: document has no path");
414 return;
413 return;
415 }
414 }
416 };
415 };
@@ -517,7 +516,7 @@ pub fn dap_continue(cx: &mut Context) {
517 );
516 );
518 } else {
517 } else {
519 cx.editor
518 cx.editor
520− .set_error("Currently active thread is not stopped. Switch the thread.".into());
519+ .set_error("Currently active thread is not stopped. Switch the thread.");
521 }
520 }
522}
521}
523
522
@@ -543,7 +542,7 @@ pub fn dap_step_in(cx: &mut Context) {
543 });
542 });
544 } else {
543 } else {
545 cx.editor
544 cx.editor
546− .set_error("Currently active thread is not stopped. Switch the thread.".into());
545+ .set_error("Currently active thread is not stopped. Switch the thread.");
547 }
546 }
548}
547}
549
548
@@ -557,7 +556,7 @@ pub fn dap_step_out(cx: &mut Context) {
557 });
556 });
558 } else {
557 } else {
559 cx.editor
558 cx.editor
560− .set_error("Currently active thread is not stopped. Switch the thread.".into());
559+ .set_error("Currently active thread is not stopped. Switch the thread.");
561 }
560 }
562}
561}
563
562
@@ -571,7 +570,7 @@ pub fn dap_next(cx: &mut Context) {
571 });
570 });
572 } else {
571 } else {
573 cx.editor
572 cx.editor
574− .set_error("Currently active thread is not stopped. Switch the thread.".into());
573+ .set_error("Currently active thread is not stopped. Switch the thread.");
575 }
574 }
576}
575}
577
576
@@ -580,14 +579,14 @@ pub fn dap_variables(cx: &mut Context) {
580
579
581 if debugger.thread_id.is_none() {
580 if debugger.thread_id.is_none() {
582 cx.editor
581 cx.editor
583− .set_status("Cannot access variables while target is running".to_owned());
582+ .set_status("Cannot access variables while target is running");
584 return;
583 return;
585 }
584 }
586 let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) {
585 let (frame, thread_id) = match (debugger.active_frame, debugger.thread_id) {
587 (Some(frame), Some(thread_id)) => (frame, thread_id),
586 (Some(frame), Some(thread_id)) => (frame, thread_id),
588 _ => {
587 _ => {
589 cx.editor
588 cx.editor
590− .set_status("Cannot find current stack frame to access variables".to_owned());
589+ .set_status("Cannot find current stack frame to access variables");
591 return;
590 return;
592 }
591 }
593 };
592 };
@@ -783,8 +782,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {
783 let thread_id = match debugger.thread_id {
782 let thread_id = match debugger.thread_id {
784 Some(thread_id) => thread_id,
783 Some(thread_id) => thread_id,
785 None => {
784 None => {
786− cx.editor
787− .set_error("No thread is currently active".to_owned());
785+ cx.editor.set_error("No thread is currently active");
788 return;
786 return;
789 }
787 }
790 };
788 };
helix-view/src/editor.rs+9−6
@@ -14,6 +14,7 @@ use futures_util::stream::select_all::SelectAll;
14use tokio_stream::wrappers::UnboundedReceiverStream;
14use tokio_stream::wrappers::UnboundedReceiverStream;
15
15
16use std::{
16use std::{
17+ borrow::Cow,
17 collections::{BTreeMap, HashMap},
18 collections::{BTreeMap, HashMap},
18 io::stdin,
19 io::stdin,
19 num::NonZeroUsize,
20 num::NonZeroUsize,
@@ -284,7 +285,7 @@ pub struct Editor {
284 pub syn_loader: Arc<syntax::Loader>,
285 pub syn_loader: Arc<syntax::Loader>,
285 pub theme_loader: Arc<theme::Loader>,
286 pub theme_loader: Arc<theme::Loader>,
286
287
287− pub status_msg: Option<(String, Severity)>,
288+ pub status_msg: Option<(Cow<'static, str>, Severity)>,
288 pub autoinfo: Option<Info>,
289 pub autoinfo: Option<Info>,
289
290
290 pub config: Config,
291 pub config: Config,
@@ -357,18 +358,20 @@ impl Editor {
357 self.status_msg = None;
358 self.status_msg = None;
358 }
359 }
359
360
361+ #[inline]
360− pub fn set_status(&mut self, status: String) {
362+ pub fn set_status<T: Into<Cow<'static, str>>>(&mut self, status: T) {
361− self.status_msg = Some((status, Severity::Info));
363+ self.status_msg = Some((status.into(), Severity::Info));
362 }
364 }
363
365
366+ #[inline]
364− pub fn set_error(&mut self, error: String) {
367+ pub fn set_error<T: Into<Cow<'static, str>>>(&mut self, error: T) {
365− self.status_msg = Some((error, Severity::Error));
368+ self.status_msg = Some((error.into(), Severity::Error));
366 }
369 }
367
370
368 pub fn set_theme(&mut self, theme: Theme) {
371 pub fn set_theme(&mut self, theme: Theme) {
369 // `ui.selection` is the only scope required to be able to render a theme.
372 // `ui.selection` is the only scope required to be able to render a theme.
370 if theme.find_scope_index("ui.selection").is_none() {
373 if theme.find_scope_index("ui.selection").is_none() {
371− self.set_error("Invalid theme: `ui.selection` required".to_owned());
374+ self.set_error("Invalid theme: `ui.selection` required");
372 return;
375 return;
373 }
376 }
374
377