on master help sign in
Replace menu::Item::{row, label} with format()
5c7db7aGokul Soumya
helix-term/src/commands.rs+5−5
@@ -5,7 +5,7 @@ pub(crate) mod typed;
5pub use dap::*;
5pub use dap::*;
6use helix_vcs::Hunk;
6use helix_vcs::Hunk;
7pub use lsp::*;
7pub use lsp::*;
8−use tui::text::Spans;
8+use tui::widgets::Row;
9pub use typed::*;
9pub use typed::*;
10
10
11use helix_core::{
11use helix_core::{
@@ -1864,7 +1864,7 @@ fn global_search(cx: &mut Context) {
1864 impl ui::menu::Item for FileResult {
1864 impl ui::menu::Item for FileResult {
1865 type Data = Option<PathBuf>;
1865 type Data = Option<PathBuf>;
1866
1866
1867− fn label(&self, current_path: &Self::Data) -> Spans {
1867+ fn format(&self, current_path: &Self::Data) -> Row {
1868 let relative_path = helix_core::path::get_relative_path(&self.path)
1868 let relative_path = helix_core::path::get_relative_path(&self.path)
1869 .to_string_lossy()
1869 .to_string_lossy()
1870 .into_owned();
1870 .into_owned();
@@ -2312,7 +2312,7 @@ fn buffer_picker(cx: &mut Context) {
2312 impl ui::menu::Item for BufferMeta {
2312 impl ui::menu::Item for BufferMeta {
2313 type Data = ();
2313 type Data = ();
2314
2314
2315− fn label(&self, _data: &Self::Data) -> Spans {
2315+ fn format(&self, _data: &Self::Data) -> Row {
2316 let path = self
2316 let path = self
2317 .path
2317 .path
2318 .as_deref()
2318 .as_deref()
@@ -2381,7 +2381,7 @@ fn jumplist_picker(cx: &mut Context) {
2381 impl ui::menu::Item for JumpMeta {
2381 impl ui::menu::Item for JumpMeta {
2382 type Data = ();
2382 type Data = ();
2383
2383
2384− fn label(&self, _data: &Self::Data) -> Spans {
2384+ fn format(&self, _data: &Self::Data) -> Row {
2385 let path = self
2385 let path = self
2386 .path
2386 .path
2387 .as_deref()
2387 .as_deref()
@@ -2454,7 +2454,7 @@ fn jumplist_picker(cx: &mut Context) {
2454impl ui::menu::Item for MappableCommand {
2454impl ui::menu::Item for MappableCommand {
2455 type Data = ReverseKeymap;
2455 type Data = ReverseKeymap;
2456
2456
2457− fn label(&self, keymap: &Self::Data) -> Spans {
2457+ fn format(&self, keymap: &Self::Data) -> Row {
2458 let fmt_binding = |bindings: &Vec<Vec<KeyEvent>>| -> String {
2458 let fmt_binding = |bindings: &Vec<Vec<KeyEvent>>| -> String {
2459 bindings.iter().fold(String::new(), |mut acc, bind| {
2459 bindings.iter().fold(String::new(), |mut acc, bind| {
2460 if !acc.is_empty() {
2460 if !acc.is_empty() {
helix-term/src/commands/dap.rs+4−4
@@ -12,7 +12,7 @@ use helix_view::editor::Breakpoint;
12
12
13use serde_json::{to_value, Value};
13use serde_json::{to_value, Value};
14use tokio_stream::wrappers::UnboundedReceiverStream;
14use tokio_stream::wrappers::UnboundedReceiverStream;
15−use tui::text::Spans;
15+use tui::{text::Spans, widgets::Row};
16
16
17use std::collections::HashMap;
17use std::collections::HashMap;
18use std::future::Future;
18use std::future::Future;
@@ -25,7 +25,7 @@ use helix_view::handlers::dap::{breakpoints_changed, jump_to_stack_frame, select
25impl ui::menu::Item for StackFrame {
25impl ui::menu::Item for StackFrame {
26 type Data = ();
26 type Data = ();
27
27
28− fn label(&self, _data: &Self::Data) -> Spans {
28+ fn format(&self, _data: &Self::Data) -> Row {
29 self.name.as_str().into() // TODO: include thread_states in the label
29 self.name.as_str().into() // TODO: include thread_states in the label
30 }
30 }
31}
31}
@@ -33,7 +33,7 @@ impl ui::menu::Item for StackFrame {
33impl ui::menu::Item for DebugTemplate {
33impl ui::menu::Item for DebugTemplate {
34 type Data = ();
34 type Data = ();
35
35
36− fn label(&self, _data: &Self::Data) -> Spans {
36+ fn format(&self, _data: &Self::Data) -> Row {
37 self.name.as_str().into()
37 self.name.as_str().into()
38 }
38 }
39}
39}
@@ -41,7 +41,7 @@ impl ui::menu::Item for DebugTemplate {
41impl ui::menu::Item for Thread {
41impl ui::menu::Item for Thread {
42 type Data = ThreadStates;
42 type Data = ThreadStates;
43
43
44− fn label(&self, thread_states: &Self::Data) -> Spans {
44+ fn format(&self, thread_states: &Self::Data) -> Row {
45 format!(
45 format!(
46 "{} ({})",
46 "{} ({})",
47 self.name,
47 self.name,
helix-term/src/commands/lsp.rs+10−6
@@ -5,7 +5,10 @@ use helix_lsp::{
5 util::{diagnostic_to_lsp_diagnostic, lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range},
5 util::{diagnostic_to_lsp_diagnostic, lsp_pos_to_pos, lsp_range_to_range, range_to_lsp_range},
6 OffsetEncoding,
6 OffsetEncoding,
7};
7};
8+use tui::{
8−use tui::text::{Span, Spans};
9+ text::{Span, Spans},
10+ widgets::Row,
11+};
9
12
10use super::{align_view, push_jump, Align, Context, Editor, Open};
13use super::{align_view, push_jump, Align, Context, Editor, Open};
11
14
@@ -46,7 +49,7 @@ impl ui::menu::Item for lsp::Location {
46 /// Current working directory.
49 /// Current working directory.
47 type Data = PathBuf;
50 type Data = PathBuf;
48
51
49− fn label(&self, cwdir: &Self::Data) -> Spans {
52+ fn format(&self, cwdir: &Self::Data) -> Row {
50 // The preallocation here will overallocate a few characters since it will account for the
53 // The preallocation here will overallocate a few characters since it will account for the
51 // URL's scheme, which is not used most of the time since that scheme will be "file://".
54 // URL's scheme, which is not used most of the time since that scheme will be "file://".
52 // Those extra chars will be used to avoid allocating when writing the line number (in the
55 // 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 {
80 /// Path to currently focussed document
83 /// Path to currently focussed document
81 type Data = Option<lsp::Url>;
84 type Data = Option<lsp::Url>;
82
85
83− fn label(&self, current_doc_path: &Self::Data) -> Spans {
86+ fn format(&self, current_doc_path: &Self::Data) -> Row {
84 if current_doc_path.as_ref() == Some(&self.location.uri) {
87 if current_doc_path.as_ref() == Some(&self.location.uri) {
85 self.name.as_str().into()
88 self.name.as_str().into()
86 } else {
89 } else {
@@ -110,7 +113,7 @@ struct PickerDiagnostic {
110impl ui::menu::Item for PickerDiagnostic {
113impl ui::menu::Item for PickerDiagnostic {
111 type Data = (DiagnosticStyles, DiagnosticsFormat);
114 type Data = (DiagnosticStyles, DiagnosticsFormat);
112
115
113− fn label(&self, (styles, format): &Self::Data) -> Spans {
116+ fn format(&self, (styles, format): &Self::Data) -> Row {
114 let mut style = self
117 let mut style = self
115 .diag
118 .diag
116 .severity
119 .severity
@@ -149,6 +152,7 @@ impl ui::menu::Item for PickerDiagnostic {
149 Span::styled(&self.diag.message, style),
152 Span::styled(&self.diag.message, style),
150 Span::styled(code, style),
153 Span::styled(code, style),
151 ])
154 ])
155+ .into()
152 }
156 }
153}
157}
154
158
@@ -467,7 +471,7 @@ pub fn workspace_diagnostics_picker(cx: &mut Context) {
467
471
468impl ui::menu::Item for lsp::CodeActionOrCommand {
472impl ui::menu::Item for lsp::CodeActionOrCommand {
469 type Data = ();
473 type Data = ();
470− fn label(&self, _data: &Self::Data) -> Spans {
474+ fn format(&self, _data: &Self::Data) -> Row {
471 match self {
475 match self {
472 lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str().into(),
476 lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str().into(),
473 lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(),
477 lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(),
@@ -662,7 +666,7 @@ pub fn code_action(cx: &mut Context) {
662
666
663impl ui::menu::Item for lsp::Command {
667impl ui::menu::Item for lsp::Command {
664 type Data = ();
668 type Data = ();
665− fn label(&self, _data: &Self::Data) -> Spans {
669+ fn format(&self, _data: &Self::Data) -> Row {
666 self.title.as_str().into()
670 self.title.as_str().into()
667 }
671 }
668}
672}
helix-term/src/ui/completion.rs+1−6
@@ -1,7 +1,6 @@
1use crate::compositor::{Component, Context, Event, EventResult};
1use crate::compositor::{Component, Context, Event, EventResult};
2use helix_view::{apply_transaction, editor::CompleteAction, ViewId};
2use helix_view::{apply_transaction, editor::CompleteAction, ViewId};
3use tui::buffer::Buffer as Surface;
3use tui::buffer::Buffer as Surface;
4−use tui::text::Spans;
5
4
6use std::borrow::Cow;
5use std::borrow::Cow;
7
6
@@ -33,11 +32,7 @@ impl menu::Item for CompletionItem {
33 .into()
32 .into()
34 }
33 }
35
34
36− fn label(&self, _data: &Self::Data) -> Spans {
37− self.label.as_str().into()
38− }
39−
40− fn row(&self, _data: &Self::Data) -> menu::Row {
35+ fn format(&self, _data: &Self::Data) -> menu::Row {
41 menu::Row::new(vec![
36 menu::Row::new(vec![
42 menu::Cell::from(self.label.as_str()),
37 menu::Cell::from(self.label.as_str()),
43 menu::Cell::from(match self.kind {
38 menu::Cell::from(match self.kind {
helix-term/src/ui/menu.rs+10−12
@@ -4,7 +4,7 @@ use crate::{
4 compositor::{Callback, Component, Compositor, Context, Event, EventResult},
4 compositor::{Callback, Component, Compositor, Context, Event, EventResult},
5 ctrl, key, shift,
5 ctrl, key, shift,
6};
6};
7−use tui::{buffer::Buffer as Surface, text::Spans, widgets::Table};
7+use tui::{buffer::Buffer as Surface, widgets::Table};
8
8
9pub use tui::widgets::{Cell, Row};
9pub use tui::widgets::{Cell, Row};
10
10
@@ -18,28 +18,24 @@ pub trait Item {
18 /// Additional editor state that is used for label calculation.
18 /// Additional editor state that is used for label calculation.
19 type Data;
19 type Data;
20
20
21− fn label(&self, data: &Self::Data) -> Spans;
21+ fn format(&self, data: &Self::Data) -> Row;
22
22
23 fn sort_text(&self, data: &Self::Data) -> Cow<str> {
23 fn sort_text(&self, data: &Self::Data) -> Cow<str> {
24− let label: String = self.label(data).into();
24+ let label: String = self.format(data).cell_text().collect();
25 label.into()
25 label.into()
26 }
26 }
27
27
28 fn filter_text(&self, data: &Self::Data) -> Cow<str> {
28 fn filter_text(&self, data: &Self::Data) -> Cow<str> {
29− let label: String = self.label(data).into();
29+ let label: String = self.format(data).cell_text().collect();
30 label.into()
30 label.into()
31 }
31 }
32−
33− fn row(&self, data: &Self::Data) -> Row {
34− Row::new(vec![Cell::from(self.label(data))])
35− }
36}
32}
37
33
38impl Item for PathBuf {
34impl Item for PathBuf {
39 /// Root prefix to strip.
35 /// Root prefix to strip.
40 type Data = PathBuf;
36 type Data = PathBuf;
41
37
42− fn label(&self, root_path: &Self::Data) -> Spans {
38+ fn format(&self, root_path: &Self::Data) -> Row {
43 self.strip_prefix(root_path)
39 self.strip_prefix(root_path)
44 .unwrap_or(self)
40 .unwrap_or(self)
45 .to_string_lossy()
41 .to_string_lossy()
@@ -144,10 +140,10 @@ impl<T: Item> Menu<T> {
144 let n = self
140 let n = self
145 .options
141 .options
146 .first()
142 .first()
147− .map(|option| option.row(&self.editor_data).cells.len())
143+ .map(|option| option.format(&self.editor_data).cells.len())
148 .unwrap_or_default();
144 .unwrap_or_default();
149 let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| {
145 let max_lens = self.options.iter().fold(vec![0; n], |mut acc, option| {
150− let row = option.row(&self.editor_data);
146+ let row = option.format(&self.editor_data);
151 // maintain max for each column
147 // maintain max for each column
152 for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
148 for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
153 let width = cell.content.width();
149 let width = cell.content.width();
@@ -331,7 +327,9 @@ impl<T: Item + 'static> Component for Menu<T> {
331 (a + b - 1) / b
327 (a + b - 1) / b
332 }
328 }
333
329
330+ let rows = options
331+ .iter()
334− let rows = options.iter().map(|option| option.row(&self.editor_data));
332+ .map(|option| option.format(&self.editor_data));
335 let table = Table::new(rows)
333 let table = Table::new(rows)
336 .style(style)
334 .style(style)
337 .highlight_style(selected)
335 .highlight_style(selected)
helix-term/src/ui/picker.rs+3−3
@@ -410,10 +410,10 @@ impl<T: Item> Picker<T> {
410
410
411 let n = options
411 let n = options
412 .first()
412 .first()
413− .map(|option| option.row(&editor_data).cells.len())
413+ .map(|option| option.format(&editor_data).cells.len())
414 .unwrap_or_default();
414 .unwrap_or_default();
415 let max_lens = options.iter().fold(vec![0; n], |mut acc, option| {
415 let max_lens = options.iter().fold(vec![0; n], |mut acc, option| {
416− let row = option.row(&editor_data);
416+ let row = option.format(&editor_data);
417 // maintain max for each column
417 // maintain max for each column
418 for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
418 for (acc, cell) in acc.iter_mut().zip(row.cells.iter()) {
419 let width = cell.content.width();
419 let width = cell.content.width();
@@ -729,7 +729,7 @@ impl<T: Item + 'static> Component for Picker<T> {
729 .skip(offset)
729 .skip(offset)
730 .take(rows as usize)
730 .take(rows as usize)
731 .map(|pmatch| &self.options[pmatch.index])
731 .map(|pmatch| &self.options[pmatch.index])
732− .map(|option| option.row(&self.editor_data))
732+ .map(|option| option.format(&self.editor_data))
733 .map(|mut row| {
733 .map(|mut row| {
734 const TEMP_CELL_SEP: &str = " ";
734 const TEMP_CELL_SEP: &str = " ";
735
735
helix-tui/src/widgets/table.rs+6
@@ -127,6 +127,12 @@ impl<'a> Row<'a> {
127 }
127 }
128}
128}
129
129
130+impl<'a, T: Into<Cell<'a>>> From<T> for Row<'a> {
131+ fn from(cell: T) -> Self {
132+ Row::new(vec![cell.into()])
133+ }
134+}
135+
130/// A widget to display data in formatted columns.
136/// A widget to display data in formatted columns.
131///
137///
132/// It is a collection of [`Row`]s, themselves composed of [`Cell`]s:
138/// It is a collection of [`Row`]s, themselves composed of [`Cell`]s: