From 1970f1fff089183e8b15bd39cd7cc09e8f987d53 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:33:16 +0000 Subject: [PATCH 01/11] feat: Picker titles --- helix-term/src/commands.rs | 65 ++++++++++++++++++++------------ helix-term/src/commands/dap.rs | 4 +- helix-term/src/commands/lsp.rs | 27 ++++++++++--- helix-term/src/commands/typed.rs | 1 + helix-term/src/ui/mod.rs | 27 ++++++++----- helix-term/src/ui/picker.rs | 17 +++++++-- 6 files changed, 97 insertions(+), 44 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 9064e1cc0..859886fa9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2538,6 +2538,7 @@ fn global_search(cx: &mut Context) { cx.editor.registers.last_search_register = reg; let picker = Picker::new( + Some("Global Search"), columns, 1, // contents [], @@ -3100,9 +3101,16 @@ fn buffer_picker(cx: &mut Context) { .into() }), ]; - let picker = Picker::new(columns, 2, items, (), |cx, meta, action| { - cx.editor.switch(meta.id, action); - }) + let picker = Picker::new( + Some("Buffers"), + columns, + 2, + items, + (), + |cx, meta, action| { + cx.editor.switch(meta.id, action); + }, + ) .with_preview(|editor, meta| { let doc = &editor.documents.get(&meta.id)?; let lines = doc.selections().values().next().map(|selection| { @@ -3178,6 +3186,7 @@ fn jumplist_picker(cx: &mut Context) { ]; let picker = Picker::new( + Some("Jump List"), columns, 1, // path cx.editor.tree.views().flat_map(|(view, _)| { @@ -3260,6 +3269,7 @@ fn changed_file_picker(cx: &mut Context) { ]; let picker = Picker::new( + Some("Changed Files"), columns, 1, // path [], @@ -3350,32 +3360,39 @@ pub fn command_palette(cx: &mut Context) { ui::PickerColumn::new("doc", |item: &MappableCommand, _| item.doc().into()), ]; - let picker = Picker::new(columns, 0, commands, keymap, move |cx, command, _action| { - let mut ctx = Context { - register, - count, - editor: cx.editor, - callback: Vec::new(), - on_next_key_callback: None, - jobs: cx.jobs, - }; - let focus = view!(ctx.editor).id; + let picker = Picker::new( + Some("Commands"), + columns, + 0, + commands, + keymap, + move |cx, command, _action| { + let mut ctx = Context { + register, + count, + editor: cx.editor, + callback: Vec::new(), + on_next_key_callback: None, + jobs: cx.jobs, + }; + let focus = view!(ctx.editor).id; - command.execute(&mut ctx); + command.execute(&mut ctx); - if ctx.editor.tree.contains(focus) { - let config = ctx.editor.config(); - let mode = ctx.editor.mode(); - let view = view_mut!(ctx.editor, focus); - let doc = doc_mut!(ctx.editor, &view.doc); + if ctx.editor.tree.contains(focus) { + let config = ctx.editor.config(); + let mode = ctx.editor.mode(); + let view = view_mut!(ctx.editor, focus); + let doc = doc_mut!(ctx.editor, &view.doc); - view.ensure_cursor_in_view(doc, config.scrolloff); + view.ensure_cursor_in_view(doc, config.scrolloff); - if mode != Mode::Insert { - doc.append_changes_to_history(view); + if mode != Mode::Insert { + doc.append_changes_to_history(view); + } } - } - }); + }, + ); compositor.push(Box::new(overlaid(picker))); }, )); diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index 83dd936cd..1d9112be2 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -52,6 +52,7 @@ fn thread_picker( }), ]; let picker = Picker::new( + None, columns, 0, threads, @@ -256,6 +257,7 @@ pub fn dap_launch(cx: &mut Context) { )]; cx.push_layer(Box::new(overlaid(Picker::new( + None, columns, 0, templates, @@ -729,7 +731,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) { let columns = [ui::PickerColumn::new("frame", |item: &StackFrame, _| { item.name.as_str().into() // TODO: include thread_states in the label })]; - let picker = Picker::new(columns, 0, frames, (), move |cx, frame, _action| { + let picker = Picker::new(None, columns, 0, frames, (), move |cx, frame, _action| { let debugger = debugger!(cx.editor); // TODO: this should be simpler to find let pos = debugger.stack_frames[&thread_id] diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index e52b2bf41..70dd4092f 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -281,6 +281,7 @@ fn diag_picker( } Picker::new( + Some("Diagnostics"), columns, primary_column, flat_diag, @@ -405,6 +406,7 @@ pub fn symbol_picker(cx: &mut Context) { ]; let picker = Picker::new( + Some("Document Symbols"), columns, 1, // name column symbols, @@ -516,6 +518,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ]; let picker = Picker::new( + Some("Workspace Symbols"), columns, 1, // name column [], @@ -854,6 +857,7 @@ impl Display for ApplyEditErrorKind { /// Precondition: `locations` should be non-empty. fn goto_impl( + title: &str, editor: &mut Editor, compositor: &mut Compositor, locations: Vec, @@ -880,9 +884,16 @@ fn goto_impl( }, )]; - let picker = Picker::new(columns, 0, locations, cwdir, move |cx, location, action| { - jump_to_location(cx.editor, location, offset_encoding, action) - }) + let picker = Picker::new( + Some(title), + columns, + 0, + locations, + cwdir, + move |cx, location, action| { + jump_to_location(cx.editor, location, offset_encoding, action) + }, + ) .with_preview(move |_editor, location| location_to_file_location(location)); compositor.push(Box::new(overlaid(picker))); } @@ -928,7 +939,13 @@ where if items.is_empty() { editor.set_error("No definition found."); } else { - goto_impl(editor, compositor, items, offset_encoding); + goto_impl( + "Goto Implementation", + editor, + compositor, + items, + offset_encoding, + ); } }, ); @@ -996,7 +1013,7 @@ pub fn goto_reference(cx: &mut Context) { if items.is_empty() { editor.set_error("No references found."); } else { - goto_impl(editor, compositor, items, offset_encoding); + goto_impl("Goto Reference", editor, compositor, items, offset_encoding); } }, ); diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 4a2546d7c..e89c38e0e 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1429,6 +1429,7 @@ fn lsp_workspace_command( }, )]; let picker = ui::Picker::new( + Some("Workspace Symbols"), columns, 0, commands, diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 92fa49dd4..edd6f1405 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -243,16 +243,23 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi .into() }, )]; - let picker = Picker::new(columns, 0, [], root, move |cx, path: &PathBuf, action| { - if let Err(e) = cx.editor.open(path, action) { - let err = if let Some(err) = e.source() { - format!("{}", err) - } else { - format!("unable to open \"{}\"", path.display()) - }; - cx.editor.set_error(err); - } - }) + let picker = Picker::new( + Some("Files"), + columns, + 0, + [], + root, + move |cx, path: &PathBuf, action| { + if let Err(e) = cx.editor.open(path, action) { + let err = if let Some(err) = e.source() { + format!("{}", err) + } else { + format!("unable to open \"{}\"", path.display()) + }; + cx.editor.set_error(err); + } + }, + ) .with_preview(|_editor, path| Some((path.as_path().into(), None))); let injector = picker.injector(); let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30); diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 3986ad479..2ca430c4a 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -268,6 +268,7 @@ pub struct Picker { /// An event handler for syntax highlighting the currently previewed file. preview_highlight_handler: Sender>, dynamic_query_handler: Option>, + title: Option, } impl Picker { @@ -296,6 +297,7 @@ impl Picker { } pub fn new( + title: Option<&str>, columns: C, primary_column: usize, options: O, @@ -321,6 +323,7 @@ impl Picker { inject_nucleo_item(&injector, &columns, item, &editor_data); } Self::with( + title, matcher, columns, primary_column, @@ -331,12 +334,14 @@ impl Picker { } pub fn with_stream( + title: Option<&str>, matcher: Nucleo, primary_column: usize, injector: Injector, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, ) -> Self { Self::with( + title, matcher, injector.columns, primary_column, @@ -347,6 +352,7 @@ impl Picker { } fn with( + title: Option<&str>, matcher: Nucleo, columns: Arc<[Column]>, default_column: usize, @@ -389,6 +395,7 @@ impl Picker { file_fn: None, preview_highlight_handler: PreviewHighlightHandler::::default().spawn(), dynamic_query_handler: None, + title: title.map(|title| title.into()), } } @@ -674,12 +681,14 @@ impl Picker { let background = cx.editor.theme.get("ui.background"); surface.clear_with(area, background); - const BLOCK: Block<'_> = Block::bordered(); + let block: Block<'_> = self.title.as_ref().map_or(Block::bordered(), |title| { + Block::bordered().title(title.to_string()) + }); // calculate the inner area inside the box - let inner = BLOCK.inner(area); + let inner = block.inner(area); - BLOCK.render(area, surface); + block.render(area, surface); // -- Render the input bar: @@ -988,7 +997,7 @@ impl Picker { impl Component for Picker { fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { - // +---------+ +---------+ + // +--title--+ +---------+ // |prompt | |preview | // +---------+ | | // |picker | | | From 32fd48927b00344791bec5fab556730c66bcbcd7 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Wed, 15 Jan 2025 20:54:57 +0000 Subject: [PATCH 02/11] fix: correct name for workspace command symbols --- helix-term/src/commands/typed.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index e89c38e0e..d548d6b82 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1429,7 +1429,7 @@ fn lsp_workspace_command( }, )]; let picker = ui::Picker::new( - Some("Workspace Symbols"), + Some("LSP Commands"), columns, 0, commands, From 76efd0e9125d01f9251b0b70d43637ca66e48bde Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Thu, 16 Jan 2025 10:30:38 +0000 Subject: [PATCH 03/11] refactor: use `with_title` --- helix-term/src/commands.rs | 78 ++++++++++++++------------------ helix-term/src/commands/dap.rs | 4 +- helix-term/src/commands/lsp.rs | 22 ++++----- helix-term/src/commands/typed.rs | 4 +- helix-term/src/ui/mod.rs | 30 +++++------- helix-term/src/ui/picker.rs | 12 ++--- 6 files changed, 62 insertions(+), 88 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 859886fa9..c6fef8260 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2538,7 +2538,6 @@ fn global_search(cx: &mut Context) { cx.editor.registers.last_search_register = reg; let picker = Picker::new( - Some("Global Search"), columns, 1, // contents [], @@ -2575,7 +2574,8 @@ fn global_search(cx: &mut Context) { Some((path.as_path().into(), Some((*line_num, *line_num)))) }) .with_history_register(Some(reg)) - .with_dynamic_query(get_files, Some(275)); + .with_dynamic_query(get_files, Some(275)) + .with_title("Global Search"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3101,16 +3101,9 @@ fn buffer_picker(cx: &mut Context) { .into() }), ]; - let picker = Picker::new( - Some("Buffers"), - columns, - 2, - items, - (), - |cx, meta, action| { - cx.editor.switch(meta.id, action); - }, - ) + let picker = Picker::new(columns, 2, items, (), |cx, meta, action| { + cx.editor.switch(meta.id, action); + }) .with_preview(|editor, meta| { let doc = &editor.documents.get(&meta.id)?; let lines = doc.selections().values().next().map(|selection| { @@ -3118,7 +3111,8 @@ fn buffer_picker(cx: &mut Context) { (cursor_line, cursor_line) }); Some((meta.id.into(), lines)) - }); + }) + .with_title("Buffers"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3186,7 +3180,6 @@ fn jumplist_picker(cx: &mut Context) { ]; let picker = Picker::new( - Some("Jump List"), columns, 1, // path cx.editor.tree.views().flat_map(|(view, _)| { @@ -3210,7 +3203,8 @@ fn jumplist_picker(cx: &mut Context) { let doc = &editor.documents.get(&meta.id)?; let line = meta.selection.primary().cursor_line(doc.text().slice(..)); Some((meta.id.into(), Some((line, line)))) - }); + }) + .with_title("Jump List"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3269,7 +3263,6 @@ fn changed_file_picker(cx: &mut Context) { ]; let picker = Picker::new( - Some("Changed Files"), columns, 1, // path [], @@ -3293,7 +3286,8 @@ fn changed_file_picker(cx: &mut Context) { } }, ) - .with_preview(|_editor, meta| Some((meta.path().into(), None))); + .with_preview(|_editor, meta| Some((meta.path().into(), None))) + .with_title("Changed Files"); let injector = picker.injector(); cx.editor @@ -3360,39 +3354,33 @@ pub fn command_palette(cx: &mut Context) { ui::PickerColumn::new("doc", |item: &MappableCommand, _| item.doc().into()), ]; - let picker = Picker::new( - Some("Commands"), - columns, - 0, - commands, - keymap, - move |cx, command, _action| { - let mut ctx = Context { - register, - count, - editor: cx.editor, - callback: Vec::new(), - on_next_key_callback: None, - jobs: cx.jobs, - }; - let focus = view!(ctx.editor).id; + let picker = Picker::new(columns, 0, commands, keymap, move |cx, command, _action| { + let mut ctx = Context { + register, + count, + editor: cx.editor, + callback: Vec::new(), + on_next_key_callback: None, + jobs: cx.jobs, + }; + let focus = view!(ctx.editor).id; - command.execute(&mut ctx); + command.execute(&mut ctx); - if ctx.editor.tree.contains(focus) { - let config = ctx.editor.config(); - let mode = ctx.editor.mode(); - let view = view_mut!(ctx.editor, focus); - let doc = doc_mut!(ctx.editor, &view.doc); + if ctx.editor.tree.contains(focus) { + let config = ctx.editor.config(); + let mode = ctx.editor.mode(); + let view = view_mut!(ctx.editor, focus); + let doc = doc_mut!(ctx.editor, &view.doc); - view.ensure_cursor_in_view(doc, config.scrolloff); + view.ensure_cursor_in_view(doc, config.scrolloff); - if mode != Mode::Insert { - doc.append_changes_to_history(view); - } + if mode != Mode::Insert { + doc.append_changes_to_history(view); } - }, - ); + } + }) + .with_title("Commands"); compositor.push(Box::new(overlaid(picker))); }, )); diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index 1d9112be2..83dd936cd 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -52,7 +52,6 @@ fn thread_picker( }), ]; let picker = Picker::new( - None, columns, 0, threads, @@ -257,7 +256,6 @@ pub fn dap_launch(cx: &mut Context) { )]; cx.push_layer(Box::new(overlaid(Picker::new( - None, columns, 0, templates, @@ -731,7 +729,7 @@ pub fn dap_switch_stack_frame(cx: &mut Context) { let columns = [ui::PickerColumn::new("frame", |item: &StackFrame, _| { item.name.as_str().into() // TODO: include thread_states in the label })]; - let picker = Picker::new(None, columns, 0, frames, (), move |cx, frame, _action| { + let picker = Picker::new(columns, 0, frames, (), move |cx, frame, _action| { let debugger = debugger!(cx.editor); // TODO: this should be simpler to find let pos = debugger.stack_frames[&thread_id] diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 70dd4092f..187663fa1 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -281,7 +281,6 @@ fn diag_picker( } Picker::new( - Some("Diagnostics"), columns, primary_column, flat_diag, @@ -294,6 +293,7 @@ fn diag_picker( }, ) .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) + .with_title("Diagnostics") .truncate_start(false) } @@ -406,7 +406,6 @@ pub fn symbol_picker(cx: &mut Context) { ]; let picker = Picker::new( - Some("Document Symbols"), columns, 1, // name column symbols, @@ -416,6 +415,7 @@ pub fn symbol_picker(cx: &mut Context) { }, ) .with_preview(move |_editor, item| location_to_file_location(&item.location)) + .with_title("Document Symbols") .truncate_start(false); compositor.push(Box::new(overlaid(picker))) @@ -518,7 +518,6 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ]; let picker = Picker::new( - Some("Workspace Symbols"), columns, 1, // name column [], @@ -529,6 +528,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ) .with_preview(|_editor, item| location_to_file_location(&item.location)) .with_dynamic_query(get_symbols, None) + .with_title("Workspace Symbols") .truncate_start(false); cx.push_layer(Box::new(overlaid(picker))); @@ -884,17 +884,11 @@ fn goto_impl( }, )]; - let picker = Picker::new( - Some(title), - columns, - 0, - locations, - cwdir, - move |cx, location, action| { - jump_to_location(cx.editor, location, offset_encoding, action) - }, - ) - .with_preview(move |_editor, location| location_to_file_location(location)); + let picker = Picker::new(columns, 0, locations, cwdir, move |cx, location, action| { + jump_to_location(cx.editor, location, offset_encoding, action) + }) + .with_preview(move |_editor, location| location_to_file_location(location)) + .with_title(title); compositor.push(Box::new(overlaid(picker))); } } diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index d548d6b82..d40bf8be4 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1429,7 +1429,6 @@ fn lsp_workspace_command( }, )]; let picker = ui::Picker::new( - Some("LSP Commands"), columns, 0, commands, @@ -1437,7 +1436,8 @@ fn lsp_workspace_command( move |cx, (ls_id, command), _action| { execute_lsp_command(cx.editor, *ls_id, command.clone()); }, - ); + ) + .with_title("LSP Commands"); compositor.push(Box::new(overlaid(picker))) }, )); diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index edd6f1405..05442c465 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -243,24 +243,18 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi .into() }, )]; - let picker = Picker::new( - Some("Files"), - columns, - 0, - [], - root, - move |cx, path: &PathBuf, action| { - if let Err(e) = cx.editor.open(path, action) { - let err = if let Some(err) = e.source() { - format!("{}", err) - } else { - format!("unable to open \"{}\"", path.display()) - }; - cx.editor.set_error(err); - } - }, - ) - .with_preview(|_editor, path| Some((path.as_path().into(), None))); + let picker = Picker::new(columns, 0, [], root, move |cx, path: &PathBuf, action| { + if let Err(e) = cx.editor.open(path, action) { + let err = if let Some(err) = e.source() { + format!("{}", err) + } else { + format!("unable to open \"{}\"", path.display()) + }; + cx.editor.set_error(err); + } + }) + .with_preview(|_editor, path| Some((path.as_path().into(), None))) + .with_title("Files"); let injector = picker.injector(); let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30); diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 2ca430c4a..1f5e13deb 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -297,7 +297,6 @@ impl Picker { } pub fn new( - title: Option<&str>, columns: C, primary_column: usize, options: O, @@ -323,7 +322,6 @@ impl Picker { inject_nucleo_item(&injector, &columns, item, &editor_data); } Self::with( - title, matcher, columns, primary_column, @@ -334,14 +332,12 @@ impl Picker { } pub fn with_stream( - title: Option<&str>, matcher: Nucleo, primary_column: usize, injector: Injector, callback_fn: impl Fn(&mut Context, &T, Action) + 'static, ) -> Self { Self::with( - title, matcher, injector.columns, primary_column, @@ -352,7 +348,6 @@ impl Picker { } fn with( - title: Option<&str>, matcher: Nucleo, columns: Arc<[Column]>, default_column: usize, @@ -395,7 +390,7 @@ impl Picker { file_fn: None, preview_highlight_handler: PreviewHighlightHandler::::default().spawn(), dynamic_query_handler: None, - title: title.map(|title| title.into()), + title: None, } } @@ -415,6 +410,11 @@ impl Picker { self } + pub fn with_title(mut self, title: &str) -> Self { + self.title = Some(title.to_string()); + self + } + pub fn with_preview( mut self, preview_fn: impl for<'a> Fn(&'a Editor, &'a T) -> Option> + 'static, From d69fdbe765b3de465c22e6523864680f258be7f6 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 24 Jan 2025 01:34:37 +0000 Subject: [PATCH 04/11] feat: add title to file browser --- helix-term/src/ui/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 05442c465..76ea43f7d 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -325,7 +325,8 @@ pub fn file_browser(root: PathBuf, editor: &Editor) -> Result Date: Fri, 24 Jan 2025 01:55:11 +0000 Subject: [PATCH 05/11] feat: show cwd of picker in file explorer --- helix-term/src/ui/mod.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 76ea43f7d..11a4ecfa7 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -285,6 +285,15 @@ type FileBrowser = Picker<(PathBuf, bool), (PathBuf, Style)>; pub fn file_browser(root: PathBuf, editor: &Editor) -> Result { let directory_style = editor.theme.get("ui.text.directory"); let directory_content = directory_content(&root)?; + let path = helix_stdx::path::get_relative_path(&root); + let path = if path.to_string_lossy() == "" { + // If helix's current working directory is the same as the `root`, + // then `path` will be an empty string. So we don't want to + // render the unnecessary ": " + "".to_string() + } else { + format!(": {}", path.display()) + }; let columns = [PickerColumn::new( "path", @@ -301,7 +310,7 @@ pub fn file_browser(root: PathBuf, editor: &Editor) -> Result Result Date: Fri, 24 Jan 2025 02:22:01 +0000 Subject: [PATCH 06/11] feat: use color for file explorer picker title directory --- helix-term/src/commands.rs | 10 +++++----- helix-term/src/commands/lsp.rs | 10 +++++----- helix-term/src/commands/typed.rs | 2 +- helix-term/src/ui/mod.rs | 21 +++++++++++---------- helix-term/src/ui/picker.rs | 8 ++++---- 5 files changed, 26 insertions(+), 25 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index c6fef8260..158c65f69 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2575,7 +2575,7 @@ fn global_search(cx: &mut Context) { }) .with_history_register(Some(reg)) .with_dynamic_query(get_files, Some(275)) - .with_title("Global Search"); + .with_title("Global Search".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3112,7 +3112,7 @@ fn buffer_picker(cx: &mut Context) { }); Some((meta.id.into(), lines)) }) - .with_title("Buffers"); + .with_title("Buffers".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3204,7 +3204,7 @@ fn jumplist_picker(cx: &mut Context) { let line = meta.selection.primary().cursor_line(doc.text().slice(..)); Some((meta.id.into(), Some((line, line)))) }) - .with_title("Jump List"); + .with_title("Jump List".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3287,7 +3287,7 @@ fn changed_file_picker(cx: &mut Context) { }, ) .with_preview(|_editor, meta| Some((meta.path().into(), None))) - .with_title("Changed Files"); + .with_title("Changed Files".into()); let injector = picker.injector(); cx.editor @@ -3380,7 +3380,7 @@ pub fn command_palette(cx: &mut Context) { } } }) - .with_title("Commands"); + .with_title("Commands".into()); compositor.push(Box::new(overlaid(picker))); }, )); diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 187663fa1..7f13b763b 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -293,7 +293,7 @@ fn diag_picker( }, ) .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) - .with_title("Diagnostics") + .with_title("Diagnostics".into()) .truncate_start(false) } @@ -415,7 +415,7 @@ pub fn symbol_picker(cx: &mut Context) { }, ) .with_preview(move |_editor, item| location_to_file_location(&item.location)) - .with_title("Document Symbols") + .with_title("Document Symbols".into()) .truncate_start(false); compositor.push(Box::new(overlaid(picker))) @@ -528,7 +528,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ) .with_preview(|_editor, item| location_to_file_location(&item.location)) .with_dynamic_query(get_symbols, None) - .with_title("Workspace Symbols") + .with_title("Workspace Symbols".into()) .truncate_start(false); cx.push_layer(Box::new(overlaid(picker))); @@ -857,7 +857,7 @@ impl Display for ApplyEditErrorKind { /// Precondition: `locations` should be non-empty. fn goto_impl( - title: &str, + title: &'static str, editor: &mut Editor, compositor: &mut Compositor, locations: Vec, @@ -888,7 +888,7 @@ fn goto_impl( jump_to_location(cx.editor, location, offset_encoding, action) }) .with_preview(move |_editor, location| location_to_file_location(location)) - .with_title(title); + .with_title(title.into()); compositor.push(Box::new(overlaid(picker))); } } diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index d40bf8be4..3914a6c6d 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1437,7 +1437,7 @@ fn lsp_workspace_command( execute_lsp_command(cx.editor, *ls_id, command.clone()); }, ) - .with_title("LSP Commands"); + .with_title("LSP Commands".into()); compositor.push(Box::new(overlaid(picker))) }, )); diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 11a4ecfa7..ad87faf39 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -254,7 +254,7 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePi } }) .with_preview(|_editor, path| Some((path.as_path().into(), None))) - .with_title("Files"); + .with_title("Files".into()); let injector = picker.injector(); let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30); @@ -285,15 +285,16 @@ type FileBrowser = Picker<(PathBuf, bool), (PathBuf, Style)>; pub fn file_browser(root: PathBuf, editor: &Editor) -> Result { let directory_style = editor.theme.get("ui.text.directory"); let directory_content = directory_content(&root)?; + let mut title: Vec = vec!["File Explorer".into()]; let path = helix_stdx::path::get_relative_path(&root); - let path = if path.to_string_lossy() == "" { - // If helix's current working directory is the same as the `root`, - // then `path` will be an empty string. So we don't want to - // render the unnecessary ": " - "".to_string() - } else { - format!(": {}", path.display()) - }; + + // if Helix's working directory is the same as the File Explorer's + // working directory, then we don't want to render a + // File Explorer: , but rather only render the picker title + if path.to_string_lossy() != "" { + title.push(": ".into()); + title.push(Span::styled(path.display().to_string(), directory_style)); + } let columns = [PickerColumn::new( "path", @@ -335,7 +336,7 @@ pub fn file_browser(root: PathBuf, editor: &Editor) -> Result { /// An event handler for syntax highlighting the currently previewed file. preview_highlight_handler: Sender>, dynamic_query_handler: Option>, - title: Option, + title: Option>, } impl Picker { @@ -410,8 +410,8 @@ impl Picker { self } - pub fn with_title(mut self, title: &str) -> Self { - self.title = Some(title.to_string()); + pub fn with_title(mut self, title: Spans<'static>) -> Self { + self.title = Some(title); self } @@ -682,7 +682,7 @@ impl Picker { surface.clear_with(area, background); let block: Block<'_> = self.title.as_ref().map_or(Block::bordered(), |title| { - Block::bordered().title(title.to_string()) + Block::bordered().title(title.clone()) }); // calculate the inner area inside the box From d4e7e0bd75377137efbeea1f878733d5ffa302a0 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 24 Jan 2025 02:48:38 +0000 Subject: [PATCH 07/11] feat: add diagnostic count information to picker title --- helix-term/src/commands/lsp.rs | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 7f13b763b..177323634 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -209,12 +209,23 @@ fn diag_picker( ) -> DiagnosticsPicker { // TODO: drop current_path comparison and instead use workspace: bool flag? + let mut title: Vec = vec!["Diagnostics".into()]; + + let mut errors_count = 0; + let mut warnings_count = 0; + // flatten the map to a vec of (url, diag) pairs let mut flat_diag = Vec::new(); for (uri, diags) in diagnostics { flat_diag.reserve(diags.len()); for (diag, ls) in diags { + match diag.severity { + Some(DiagnosticSeverity::ERROR) => errors_count += 1, + Some(DiagnosticSeverity::WARNING) => warnings_count += 1, + _ => (), + } + if let Some(ls) = cx.editor.language_server_by_id(ls) { flat_diag.push(PickerDiagnostic { location: Location { @@ -235,6 +246,23 @@ fn diag_picker( error: cx.editor.theme.get("error"), }; + if warnings_count != 0 || errors_count != 0 { + title.push(": ".into()); + } + + if warnings_count != 0 { + title.push(Span::styled("● ", styles.warning)); + title.push(warnings_count.to_string().into()); + } + + if errors_count != 0 { + if warnings_count != 0 { + title.push(" ".into()) + } + title.push(Span::styled("● ", styles.error)); + title.push(errors_count.to_string().into()); + } + let mut columns = vec![ ui::PickerColumn::new( "severity", @@ -293,7 +321,7 @@ fn diag_picker( }, ) .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) - .with_title("Diagnostics".into()) + .with_title(title.into()) .truncate_start(false) } From cf439ffe8503abfec8d3abe682857d8fc3847062 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 24 Jan 2025 20:42:19 +0000 Subject: [PATCH 08/11] feat: remove word --- helix-term/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 158c65f69..dfa87ea5d 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2575,7 +2575,7 @@ fn global_search(cx: &mut Context) { }) .with_history_register(Some(reg)) .with_dynamic_query(get_files, Some(275)) - .with_title("Global Search".into()); + .with_title("Search".into()); cx.push_layer(Box::new(overlaid(picker))); } From 1aa49adfccc20320f17ebf2e529e74b69f674d11 Mon Sep 17 00:00:00 2001 From: Nikita Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Fri, 24 Jan 2025 20:42:48 +0000 Subject: [PATCH 09/11] feat: add word --- helix-term/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index dfa87ea5d..7a16c6f34 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -3380,7 +3380,7 @@ pub fn command_palette(cx: &mut Context) { } } }) - .with_title("Commands".into()); + .with_title("Command Palette".into()); compositor.push(Box::new(overlaid(picker))); }, )); From a81a7994fd0088b35c33c924a044a252dbdc8163 Mon Sep 17 00:00:00 2001 From: Nik Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Wed, 26 Mar 2025 22:38:44 +0000 Subject: [PATCH 10/11] feat: simplify PR to only use static strings _ --- helix-term/src/commands.rs | 10 +++--- helix-term/src/commands/lsp.rs | 57 +++++++------------------------- helix-term/src/commands/typed.rs | 2 +- helix-term/src/ui/mod.rs | 14 ++------ helix-term/src/ui/picker.rs | 11 +++--- 5 files changed, 26 insertions(+), 68 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 0ad09de92..5d8e2ace9 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2641,7 +2641,7 @@ fn global_search(cx: &mut Context) { }) .with_history_register(Some(reg)) .with_dynamic_query(get_files, Some(275)) - .with_title("Search".into()); + .with_title("Search"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3178,7 +3178,7 @@ fn buffer_picker(cx: &mut Context) { }); Some((meta.id.into(), lines)) }) - .with_title("Buffers".into()); + .with_title("Buffers"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3270,7 +3270,7 @@ fn jumplist_picker(cx: &mut Context) { let line = meta.selection.primary().cursor_line(doc.text().slice(..)); Some((meta.id.into(), Some((line, line)))) }) - .with_title("Jump List".into()); + .with_title("Jump List"); cx.push_layer(Box::new(overlaid(picker))); } @@ -3353,7 +3353,7 @@ fn changed_file_picker(cx: &mut Context) { }, ) .with_preview(|_editor, meta| Some((meta.path().into(), None))) - .with_title("Changed Files".into()); + .with_title("Changed Files"); let injector = picker.injector(); cx.editor @@ -3446,7 +3446,7 @@ pub fn command_palette(cx: &mut Context) { } } }) - .with_title("Command Palette".into()); + .with_title("Command Palette"); compositor.push(Box::new(overlaid(picker))); }, )); diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 00a3ef8d3..3ad9954ba 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -209,24 +209,16 @@ fn diag_picker( ) -> DiagnosticsPicker { // TODO: drop current_path comparison and instead use workspace: bool flag? - let mut title: Vec = vec!["Diagnostics".into()]; - - let mut errors_count = 0; - let mut warnings_count = 0; - // flatten the map to a vec of (url, diag) pairs let mut flat_diag = Vec::new(); for (uri, diags) in diagnostics { flat_diag.reserve(diags.len()); - for (diag, ls) in diags { - match diag.severity { - Some(DiagnosticSeverity::ERROR) => errors_count += 1, - Some(DiagnosticSeverity::WARNING) => warnings_count += 1, - _ => (), - } - - if let Some(ls) = cx.editor.language_server_by_id(ls) { + for (diag, provider) in diags { + if let Some(ls) = provider + .language_server_id() + .and_then(|id| cx.editor.language_server_by_id(id)) + { flat_diag.push(PickerDiagnostic { location: Location { uri: uri.clone(), @@ -246,23 +238,6 @@ fn diag_picker( error: cx.editor.theme.get("error"), }; - if warnings_count != 0 || errors_count != 0 { - title.push(": ".into()); - } - - if warnings_count != 0 { - title.push(Span::styled("● ", styles.warning)); - title.push(warnings_count.to_string().into()); - } - - if errors_count != 0 { - if warnings_count != 0 { - title.push(" ".into()) - } - title.push(Span::styled("● ", styles.error)); - title.push(errors_count.to_string().into()); - } - let mut columns = vec![ ui::PickerColumn::new( "severity", @@ -321,7 +296,7 @@ fn diag_picker( }, ) .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) - .with_title(title.into()) + .with_title("Diagnostics") .truncate_start(false) } @@ -450,7 +425,7 @@ pub fn symbol_picker(cx: &mut Context) { }, ) .with_preview(move |_editor, item| location_to_file_location(&item.location)) - .with_title("Document Symbols".into()) + .with_title("Document Symbols") .truncate_start(false); compositor.push(Box::new(overlaid(picker))) @@ -578,7 +553,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ) .with_preview(|_editor, item| location_to_file_location(&item.location)) .with_dynamic_query(get_symbols, None) - .with_title("Workspace Symbols".into()) + .with_title("Workspace Symbols") .truncate_start(false); cx.push_layer(Box::new(overlaid(picker))); @@ -871,11 +846,9 @@ impl Display for ApplyEditErrorKind { /// Precondition: `locations` should be non-empty. fn goto_impl( title: &'static str, - editor: &mut Editor, compositor: &mut Compositor, locations: Vec, - offset_encoding: OffsetEncoding, ) { let cwdir = helix_stdx::env::current_working_dir(); @@ -901,8 +874,8 @@ fn goto_impl( let picker = Picker::new(columns, 0, locations, cwdir, |cx, location, action| { jump_to_location(cx.editor, location, action) }) - .with_title(title.into()) - .with_preview(move |_editor, location| location_to_file_location(location)); + .with_preview(|_editor, location| location_to_file_location(location)) + .with_title(title); compositor.push(Box::new(overlaid(picker))); } } @@ -961,13 +934,7 @@ where if locations.is_empty() { editor.set_error("No definition found."); } else { - goto_impl( - "Goto Implementation", - editor, - compositor, - items, - offset_encoding, - ); + goto_impl("Goto Implementation", editor, compositor, locations); } }; Ok(Callback::EditorCompositor(Box::new(call))) @@ -1044,7 +1011,7 @@ pub fn goto_reference(cx: &mut Context) { if locations.is_empty() { editor.set_error("No references found."); } else { - goto_impl("Goto Reference", editor, compositor, items, offset_encoding); + goto_impl("Goto Reference", editor, compositor, locations); } }; Ok(Callback::EditorCompositor(Box::new(call))) diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 592b41094..57e41ecc3 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1459,7 +1459,7 @@ fn lsp_workspace_command( cx.editor.execute_lsp_command(command.clone(), *ls_id); }, ) - .with_title("LSP Commands".into()); + .with_title("LSP Commands"); compositor.push(Box::new(overlaid(picker))) }, )); diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index c05f016a1..d679cb287 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -275,7 +275,7 @@ pub fn file_picker(editor: &Editor, root: PathBuf) -> FilePicker { } }) .with_preview(|_editor, path| Some((path.as_path().into(), None))) - .with_title("Files".into()); + .with_title("Files"); let injector = picker.injector(); let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30); @@ -306,16 +306,6 @@ type FileExplorer = Picker<(PathBuf, bool), (PathBuf, Style)>; pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result { let directory_style = editor.theme.get("ui.text.directory"); let directory_content = directory_content(&root)?; - let mut title: Vec = vec!["File Explorer".into()]; - let path = helix_stdx::path::get_relative_path(&root); - - // if Helix's working directory is the same as the File Explorer's - // working directory, then we don't want to render a - // File Explorer: , but rather only render the picker title - if path.to_string_lossy() != "" { - title.push(": ".into()); - title.push(Span::styled(path.display().to_string(), directory_style)); - } let columns = [PickerColumn::new( "path", @@ -357,7 +347,7 @@ pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result { /// An event handler for syntax highlighting the currently previewed file. preview_highlight_handler: Sender>, dynamic_query_handler: Option>, - title: Option>, + title: Option<&'static str>, } impl Picker { @@ -410,7 +410,7 @@ impl Picker { self } - pub fn with_title(mut self, title: Spans<'static>) -> Self { + pub fn with_title(mut self, title: &'static str) -> Self { self.title = Some(title); self } @@ -681,9 +681,10 @@ impl Picker { let background = cx.editor.theme.get("ui.background"); surface.clear_with(area, background); - let block: Block<'_> = self.title.as_ref().map_or(Block::bordered(), |title| { - Block::bordered().title(title.clone()) - }); + let block: Block<'_> = self + .title + .as_ref() + .map_or(Block::bordered(), |title| Block::bordered().title(title)); // calculate the inner area inside the box let inner = block.inner(area); From 46f6a62aeaed57701cb78f96001b68e621a9b4b1 Mon Sep 17 00:00:00 2001 From: Nik Revenco <154856872+NikitaRevenco@users.noreply.github.com> Date: Wed, 26 Mar 2025 22:49:37 +0000 Subject: [PATCH 11/11] fix: use Spans<&'static> --- helix-term/src/commands.rs | 10 +++++----- helix-term/src/commands/lsp.rs | 8 ++++---- helix-term/src/commands/typed.rs | 2 +- helix-term/src/ui/mod.rs | 4 ++-- helix-term/src/ui/picker.rs | 11 +++++------ 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 5d8e2ace9..0ad09de92 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2641,7 +2641,7 @@ fn global_search(cx: &mut Context) { }) .with_history_register(Some(reg)) .with_dynamic_query(get_files, Some(275)) - .with_title("Search"); + .with_title("Search".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3178,7 +3178,7 @@ fn buffer_picker(cx: &mut Context) { }); Some((meta.id.into(), lines)) }) - .with_title("Buffers"); + .with_title("Buffers".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3270,7 +3270,7 @@ fn jumplist_picker(cx: &mut Context) { let line = meta.selection.primary().cursor_line(doc.text().slice(..)); Some((meta.id.into(), Some((line, line)))) }) - .with_title("Jump List"); + .with_title("Jump List".into()); cx.push_layer(Box::new(overlaid(picker))); } @@ -3353,7 +3353,7 @@ fn changed_file_picker(cx: &mut Context) { }, ) .with_preview(|_editor, meta| Some((meta.path().into(), None))) - .with_title("Changed Files"); + .with_title("Changed Files".into()); let injector = picker.injector(); cx.editor @@ -3446,7 +3446,7 @@ pub fn command_palette(cx: &mut Context) { } } }) - .with_title("Command Palette"); + .with_title("Command Palette".into()); compositor.push(Box::new(overlaid(picker))); }, )); diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 3ad9954ba..068f52025 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -296,7 +296,7 @@ fn diag_picker( }, ) .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) - .with_title("Diagnostics") + .with_title("Diagnostics".into()) .truncate_start(false) } @@ -425,7 +425,7 @@ pub fn symbol_picker(cx: &mut Context) { }, ) .with_preview(move |_editor, item| location_to_file_location(&item.location)) - .with_title("Document Symbols") + .with_title("Document Symbols".into()) .truncate_start(false); compositor.push(Box::new(overlaid(picker))) @@ -553,7 +553,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { ) .with_preview(|_editor, item| location_to_file_location(&item.location)) .with_dynamic_query(get_symbols, None) - .with_title("Workspace Symbols") + .with_title("Workspace Symbols".into()) .truncate_start(false); cx.push_layer(Box::new(overlaid(picker))); @@ -875,7 +875,7 @@ fn goto_impl( jump_to_location(cx.editor, location, action) }) .with_preview(|_editor, location| location_to_file_location(location)) - .with_title(title); + .with_title(title.into()); compositor.push(Box::new(overlaid(picker))); } } diff --git a/helix-term/src/commands/typed.rs b/helix-term/src/commands/typed.rs index 57e41ecc3..592b41094 100644 --- a/helix-term/src/commands/typed.rs +++ b/helix-term/src/commands/typed.rs @@ -1459,7 +1459,7 @@ fn lsp_workspace_command( cx.editor.execute_lsp_command(command.clone(), *ls_id); }, ) - .with_title("LSP Commands"); + .with_title("LSP Commands".into()); compositor.push(Box::new(overlaid(picker))) }, )); diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index d679cb287..c87d4c63e 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -275,7 +275,7 @@ pub fn file_picker(editor: &Editor, root: PathBuf) -> FilePicker { } }) .with_preview(|_editor, path| Some((path.as_path().into(), None))) - .with_title("Files"); + .with_title("Files".into()); let injector = picker.injector(); let timeout = std::time::Instant::now() + std::time::Duration::from_millis(30); @@ -347,7 +347,7 @@ pub fn file_explorer(root: PathBuf, editor: &Editor) -> Result { /// An event handler for syntax highlighting the currently previewed file. preview_highlight_handler: Sender>, dynamic_query_handler: Option>, - title: Option<&'static str>, + title: Option>, } impl Picker { @@ -410,7 +410,7 @@ impl Picker { self } - pub fn with_title(mut self, title: &'static str) -> Self { + pub fn with_title(mut self, title: Spans<'static>) -> Self { self.title = Some(title); self } @@ -681,10 +681,9 @@ impl Picker { let background = cx.editor.theme.get("ui.background"); surface.clear_with(area, background); - let block: Block<'_> = self - .title - .as_ref() - .map_or(Block::bordered(), |title| Block::bordered().title(title)); + let block: Block<'_> = self.title.as_ref().map_or(Block::bordered(), |title| { + Block::bordered().title(title.clone()) + }); // calculate the inner area inside the box let inner = block.inner(area);