diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 15e4b47b2..5b3ce68ec 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -5,7 +5,7 @@ pub(crate) mod typed; pub use dap::*; use helix_vcs::Hunk; pub use lsp::*; -use tui::text::Spans; +use tui::widgets::Row; pub use typed::*; use helix_core::{ @@ -1864,7 +1864,7 @@ fn global_search(cx: &mut Context) { impl ui::menu::Item for FileResult { type Data = Option; - fn label(&self, current_path: &Self::Data) -> Spans { + fn format(&self, current_path: &Self::Data) -> Row { let relative_path = helix_core::path::get_relative_path(&self.path) .to_string_lossy() .into_owned(); @@ -2312,7 +2312,7 @@ fn buffer_picker(cx: &mut Context) { impl ui::menu::Item for BufferMeta { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { let path = self .path .as_deref() @@ -2381,7 +2381,7 @@ fn jumplist_picker(cx: &mut Context) { impl ui::menu::Item for JumpMeta { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { let path = self .path .as_deref() @@ -2454,7 +2454,7 @@ fn jumplist_picker(cx: &mut Context) { impl ui::menu::Item for MappableCommand { type Data = ReverseKeymap; - fn label(&self, keymap: &Self::Data) -> Spans { + fn format(&self, keymap: &Self::Data) -> Row { let fmt_binding = |bindings: &Vec>| -> String { bindings.iter().fold(String::new(), |mut acc, bind| { if !acc.is_empty() { diff --git a/helix-term/src/commands/dap.rs b/helix-term/src/commands/dap.rs index b182f28c4..b3166e395 100644 --- a/helix-term/src/commands/dap.rs +++ b/helix-term/src/commands/dap.rs @@ -12,7 +12,7 @@ use helix_view::editor::Breakpoint; use serde_json::{to_value, Value}; use tokio_stream::wrappers::UnboundedReceiverStream; -use tui::text::Spans; +use tui::{text::Spans, widgets::Row}; use std::collections::HashMap; use std::future::Future; @@ -25,7 +25,7 @@ use helix_view::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select impl ui::menu::Item for StackFrame { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { self.name.as_str().into() // TODO: include thread_states in the label } } @@ -33,7 +33,7 @@ impl ui::menu::Item for StackFrame { impl ui::menu::Item for DebugTemplate { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { self.name.as_str().into() } } @@ -41,7 +41,7 @@ impl ui::menu::Item for DebugTemplate { impl ui::menu::Item for Thread { type Data = ThreadStates; - fn label(&self, thread_states: &Self::Data) -> Spans { + fn format(&self, thread_states: &Self::Data) -> Row { format!( "{} ({})", self.name, diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 86b0c5fa7..90b6d76c0 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -5,7 +5,10 @@ use helix_lsp::{ util::{diagnostic_to_lsp_diagnostic, lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range}, OffsetEncoding, }; -use tui::text::{Span, Spans}; +use tui::{ + text::{Span, Spans}, + widgets::Row, +}; use super::{align_view, push_jump, Align, Context, Editor, Open}; @@ -46,7 +49,7 @@ impl ui::menu::Item for lsp::Location { /// Current working directory. type Data = PathBuf; - fn label(&self, cwdir: &Self::Data) -> Spans { + fn format(&self, cwdir: &Self::Data) -> Row { // The preallocation here will overallocate a few characters since it will account for the // URL's scheme, which is not used most of the time since that scheme will be "file://". // Those extra chars will be used to avoid allocating when writing the line number (in the @@ -80,7 +83,7 @@ impl ui::menu::Item for lsp::SymbolInformation { /// Path to currently focussed document type Data = Option; - fn label(&self, current_doc_path: &Self::Data) -> Spans { + fn format(&self, current_doc_path: &Self::Data) -> Row { if current_doc_path.as_ref() == Some(&self.location.uri) { self.name.as_str().into() } else { @@ -110,7 +113,7 @@ struct PickerDiagnostic { impl ui::menu::Item for PickerDiagnostic { type Data = (DiagnosticStyles, DiagnosticsFormat); - fn label(&self, (styles, format): &Self::Data) -> Spans { + fn format(&self, (styles, format): &Self::Data) -> Row { let mut style = self .diag .severity @@ -149,6 +152,7 @@ impl ui::menu::Item for PickerDiagnostic { Span::styled(&self.diag.message, style), Span::styled(code, style), ]) + .into() } } @@ -467,7 +471,7 @@ pub fn workspace_diagnostics_picker(cx: &mut Context) { impl ui::menu::Item for lsp::CodeActionOrCommand { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { match self { lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str().into(), lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(), @@ -662,7 +666,7 @@ pub fn code_action(cx: &mut Context) { impl ui::menu::Item for lsp::Command { type Data = (); - fn label(&self, _data: &Self::Data) -> Spans { + fn format(&self, _data: &Self::Data) -> Row { self.title.as_str().into() } } diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs index 11d7886a3..824bafd8d 100644 --- a/helix-term/src/ui/completion.rs +++ b/helix-term/src/ui/completion.rs @@ -1,7 +1,6 @@ use crate::compositor::{Component, Context, Event, EventResult}; use helix_view::{apply_transaction, editor::CompleteAction, ViewId}; use tui::buffer::Buffer as Surface; -use tui::text::Spans; use std::borrow::Cow; @@ -33,11 +32,7 @@ impl menu::Item for CompletionItem { .into() } - fn label(&self, _data: &Self::Data) -> Spans { - self.label.as_str().into() - } - - fn row(&self, _data: &Self::Data) -> menu::Row { + fn format(&self, _data: &Self::Data) -> menu::Row { menu::Row::new(vec![ menu::Cell::from(self.label.as_str()), menu::Cell::from(match self.kind { diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs index b9c1f9ded..e92578c5a 100644 --- a/helix-term/src/ui/menu.rs +++ b/helix-term/src/ui/menu.rs @@ -4,7 +4,7 @@ use crate::{ compositor::{Callback, Component, Compositor, Context, Event, EventResult}, ctrl, key, shift, }; -use tui::{buffer::Buffer as Surface, text::Spans, widgets::Table}; +use tui::{buffer::Buffer as Surface, widgets::Table}; pub use tui::widgets::{Cell, Row}; @@ -18,28 +18,24 @@ pub trait Item { /// Additional editor state that is used for label calculation. type Data; - fn label(&self, data: &Self::Data) -> Spans; + fn format(&self, data: &Self::Data) -> Row; fn sort_text(&self, data: &Self::Data) -> Cow { - let label: String = self.label(data).into(); + let label: String = self.format(data).cell_text().collect(); label.into() } fn filter_text(&self, data: &Self::Data) -> Cow { - let label: String = self.label(data).into(); + let label: String = self.format(data).cell_text().collect(); label.into() } - - fn row(&self, data: &Self::Data) -> Row { - Row::new(vec![Cell::from(self.label(data))]) - } } impl Item for PathBuf { /// Root prefix to strip. type Data = PathBuf; - fn label(&self, root_path: &Self::Data) -> Spans { + fn format(&self, root_path: &Self::Data) -> Row { self.strip_prefix(root_path) .unwrap_or(self) .to_string_lossy() @@ -144,10 +140,10 @@ impl Menu { let n = self .options .first() - .map(|option| option.row(&self.editor_data).cells.len()) + .map(|option| option.format(&self.editor_data).cells.len()) .unwrap_or_default(); let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| { - let row = option.row(&self.editor_data); + let row = option.format(&self.editor_data); // maintain max for each column for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) { let width = cell.content.width(); @@ -331,7 +327,9 @@ impl Component for Menu { (a + b - 1) / b } - let rows = options.iter().map(|option| option.row(&self.editor_data)); + let rows = options + .iter() + .map(|option| option.format(&self.editor_data)); let table = Table::new(rows) .style(style) .highlight_style(selected) diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 05738ccf5..ccf37eb2b 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -410,10 +410,10 @@ impl Picker { let n = options .first() - .map(|option| option.row(&editor_data).cells.len()) + .map(|option| option.format(&editor_data).cells.len()) .unwrap_or_default(); let max_lens = options.iter().fold(vec![0; n], |mut acc, option| { - let row = option.row(&editor_data); + let row = option.format(&editor_data); // maintain max for each column for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) { let width = cell.content.width(); @@ -729,7 +729,7 @@ impl Component for Picker { .skip(offset) .take(rows as usize) .map(|pmatch| &self.options[pmatch.index]) - .map(|option| option.row(&self.editor_data)) + .map(|option| option.format(&self.editor_data)) .map(|mut row| { const TEMP_CELL_SEP: &str = " "; diff --git a/helix-tui/src/widgets/table.rs b/helix-tui/src/widgets/table.rs index 2983072d6..400f65e0a 100644 --- a/helix-tui/src/widgets/table.rs +++ b/helix-tui/src/widgets/table.rs @@ -127,6 +127,12 @@ impl<'a> Row<'a> { } } +impl<'a, T: Into>> From for Row<'a> { + fn from(cell: T) -> Self { + Row::new(vec![cell.into()]) + } +} + /// A widget to display data in formatted columns. /// /// It is a collection of [`Row`]s, themselves composed of [`Cell`]s: