Skip to content

Commit

Permalink
Refactor Picker in terms of columns
Browse files Browse the repository at this point in the history
`menu::Item` is replaced with column configurations for each picker
which control how a column is displayed and whether it is passed to
nucleo for filtering. (This is used for dynamic pickers so that we can
filter those items with the dynamic picker callback rather than nucleo.)

The picker has a new lucene-like syntax that can be used to filter the
picker only on certain criteria. If a filter is not specified, the text
in the prompt applies to the picker's configured "primary" column.

Adding column configurations for each picker is left for the child
commit.
  • Loading branch information
the-mikedavis committed Sep 4, 2023
1 parent 61814fe commit 2817049
Show file tree
Hide file tree
Showing 7 changed files with 449 additions and 156 deletions.
14 changes: 11 additions & 3 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2172,7 +2172,9 @@ fn global_search(cx: &mut Context) {
return;
}

let (picker, injector) = Picker::stream(current_path);
// TODO
let columns = vec![];
let (picker, injector) = Picker::stream(columns, current_path);

let dedup_symlinks = file_picker_config.deduplicate_links;
let absolute_root = search_root
Expand Down Expand Up @@ -2268,6 +2270,7 @@ fn global_search(cx: &mut Context) {
let call = move |_: &mut Editor, compositor: &mut Compositor| {
let picker = Picker::with_stream(
picker,
0,
injector,
move |cx, FileResult { path, line_num }, action| {
let doc = match cx.editor.open(path, action) {
Expand Down Expand Up @@ -2735,7 +2738,8 @@ fn buffer_picker(cx: &mut Context) {
// mru
items.sort_unstable_by_key(|item| std::cmp::Reverse(item.focused_at));

let picker = Picker::new(items, (), |cx, meta, action| {
let columns = vec![];
let picker = Picker::new(columns, 0, items, (), |cx, meta, action| {
cx.editor.switch(meta.id, action);
})
.with_preview(|editor, meta| {
Expand Down Expand Up @@ -2812,7 +2816,10 @@ fn jumplist_picker(cx: &mut Context) {
}
};

let columns = vec![];
let picker = Picker::new(
columns,
0,
cx.editor
.tree
.views()
Expand Down Expand Up @@ -2889,7 +2896,8 @@ pub fn command_palette(cx: &mut Context) {
}
}));

let picker = Picker::new(commands, keymap, move |cx, command, _action| {
let columns = vec![];
let picker = Picker::new(columns, 0, commands, keymap, move |cx, command, _action| {
let mut ctx = Context {
register,
count,
Expand Down
18 changes: 14 additions & 4 deletions helix-term/src/commands/dap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,14 @@ fn thread_picker(
let debugger = debugger!(editor);

let thread_states = debugger.thread_states.clone();
let picker = Picker::new(threads, thread_states, move |cx, thread, _action| {
callback_fn(cx.editor, thread)
})
let columns = vec![];
let picker = Picker::new(
columns,
0,
threads,
thread_states,
move |cx, thread, _action| callback_fn(cx.editor, thread),
)
.with_preview(move |editor, thread| {
let frames = editor.debugger.as_ref()?.stack_frames.get(&thread.id)?;
let frame = frames.get(0)?;
Expand Down Expand Up @@ -268,7 +273,11 @@ pub fn dap_launch(cx: &mut Context) {

let templates = config.templates.clone();

let columns = vec![];

cx.push_layer(Box::new(overlaid(Picker::new(
columns,
0,
templates,
(),
|cx, template, _action| {
Expand Down Expand Up @@ -730,7 +739,8 @@ pub fn dap_switch_stack_frame(cx: &mut Context) {

let frames = debugger.stack_frames[&thread_id].clone();

let picker = Picker::new(frames, (), move |cx, frame, _action| {
let columns = vec![];
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]
Expand Down
35 changes: 24 additions & 11 deletions helix-term/src/commands/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,18 +238,25 @@ fn jump_to_location(
}
}

type SymbolPicker = Picker<SymbolInformationItem>;
type SymbolPicker = Picker<SymbolInformationItem, Option<lsp::Url>>;

fn sym_picker(symbols: Vec<SymbolInformationItem>, current_path: Option<lsp::Url>) -> SymbolPicker {
// TODO: drop current_path comparison and instead use workspace: bool flag?
Picker::new(symbols, current_path, move |cx, item, action| {
jump_to_location(
cx.editor,
&item.symbol.location,
item.offset_encoding,
action,
);
})
let columns = vec![];
Picker::new(
columns,
0,
symbols,
current_path,
move |cx, item, action| {
jump_to_location(
cx.editor,
&item.symbol.location,
item.offset_encoding,
action,
);
},
)
.with_preview(move |_editor, item| Some(location_to_file_location(&item.symbol.location)))
.truncate_start(false)
}
Expand All @@ -260,12 +267,14 @@ enum DiagnosticsFormat {
HideSourcePath,
}

type DiagnosticsPicker = Picker<PickerDiagnostic, (DiagnosticStyles, DiagnosticsFormat)>;

fn diag_picker(
cx: &Context,
diagnostics: BTreeMap<lsp::Url, Vec<(lsp::Diagnostic, usize)>>,
_current_path: Option<lsp::Url>,
format: DiagnosticsFormat,
) -> Picker<PickerDiagnostic> {
) -> DiagnosticsPicker {
// TODO: drop current_path comparison and instead use workspace: bool flag?

// flatten the map to a vec of (url, diag) pairs
Expand All @@ -291,7 +300,10 @@ fn diag_picker(
error: cx.editor.theme.get("error"),
};

let columns = vec![];
Picker::new(
columns,
0,
flat_diag,
(styles, format),
move |cx,
Expand Down Expand Up @@ -1029,7 +1041,8 @@ fn goto_impl(
editor.set_error("No definition found.");
}
_locations => {
let picker = Picker::new(locations, cwdir, move |cx, location, action| {
let columns = vec![];
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| Some(location_to_file_location(location)));
Expand Down
8 changes: 5 additions & 3 deletions helix-term/src/commands/typed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1388,9 +1388,11 @@ fn lsp_workspace_command(
let callback = async move {
let call: job::Callback = Callback::EditorCompositor(Box::new(
move |_editor: &mut Editor, compositor: &mut Compositor| {
let picker = ui::Picker::new(commands, (), move |cx, command, _action| {
execute_lsp_command(cx.editor, language_server_id, command.clone());
});
let columns = vec![];
let picker =
ui::Picker::new(columns, 0, commands, (), move |cx, command, _action| {
execute_lsp_command(cx.editor, language_server_id, command.clone());
});
compositor.push(Box::new(overlaid(picker)))
},
));
Expand Down
33 changes: 21 additions & 12 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use completion::{Completion, CompletionItem};
pub use editor::EditorView;
pub use markdown::Markdown;
pub use menu::Menu;
pub use picker::{DynamicPicker, FileLocation, Picker};
pub use picker::{Column as PickerColumn, DynamicPicker, FileLocation, Picker};
pub use popup::Popup;
pub use prompt::{Prompt, PromptEvent};
pub use spinner::{ProgressSpinners, Spinner};
Expand Down Expand Up @@ -155,7 +155,9 @@ pub fn regex_prompt(
cx.push_layer(Box::new(prompt));
}

pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker<PathBuf> {
type FilePicker = Picker<PathBuf, PathBuf>;

pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> FilePicker {
use ignore::{types::TypesBuilder, WalkBuilder};
use std::time::Instant;

Expand Down Expand Up @@ -199,16 +201,23 @@ pub fn file_picker(root: PathBuf, config: &helix_view::editor::Config) -> Picker
});
log::debug!("file_picker init {:?}", Instant::now().duration_since(now));

let picker = Picker::new(Vec::new(), 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 columns = vec![];
let picker = Picker::new(
columns,
0,
Vec::new(),
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.clone().into(), None)));
let injector = picker.injector();
std::thread::spawn(move || {
Expand Down
Loading

0 comments on commit 2817049

Please sign in to comment.