Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Merge Picker and FilePicker #5801

Closed

Conversation

sudormrfbin
Copy link
Member

@sudormrfbin sudormrfbin commented Feb 3, 2023

Merges the code for the Picker and FilePicker into a single Picker that can show a file preview if a preview callback is provided. This change was mainly made to facilitate refactoring out a simple skeleton of a picker that does not do any filtering to be reused in a normal Picker and a DynamicPicker (see #5714; in particular @the-mikedavis's comment and @sudormrfbin's comment).

The crux of the issue is that a picker maintains a list of predefined options (eg. list of files in the directory) and (re-)filters them every time the picker prompt changes, while a dynamic picker (eg. interactive global search, #4687) recalculates the full list of options on every prompt change. Using a filtering picker to drive a dynamic picker hence does duplicate work of filtering thousands of matches for no reason. It could also cause problems like interfering with the regex pattern in the global search.

I tried to directly extract a PickerBase to be reused in Picker, FilePicker and DynamicPicker, but the problem is that DynamicPicker is actually a DynamicFilePicker (i.e. it can preview file contents) which means we would need PickerBase, Picker, FilePicker, DynamicPicker and DynamicFilePicker and then another way of sharing the previewing code between a FilePicker and a DynamicFilePicker. By merging Picker and FilePicker into Picker, we only need PickerBase, Picker and DynamicPicker.


The PR has been organized into commits that can be easily reviewed. Each commit moves a set of related functionality from Picker into FilePicker and keeps a placeholder unimplemented!() call in the original region. When all methods have been moved into FilePicker, the original Picker struct and impl are deleted and FilePicker is renamed to Picker. There's close to no new code, save for some new methods like Picker::with_preview and Picker::without_preview.

@sudormrfbin sudormrfbin changed the title Move FilePicker::render from Component impl to normal impl refactor: Merge Picker and FilePicker Feb 3, 2023
Merges the code for the Picker and FilePicker into a single Picker that
can show a file preview if a preview callback is provided. This change
was mainly made to facilitate refactoring out a simple skeleton of a
picker that does not do any filtering to be reused in a normal Picker
and a DynamicPicker (see helix-editor#5714; in particular [mikes-comment] and
[gokuls-comment]).

The crux of the issue is that a picker maintains a list of predefined
options (eg. list of files in the directory) and (re-)filters them every
time the picker prompt changes, while a dynamic picker (eg. interactive
global search, helix-editor#4687) recalculates the full list of options on every
prompt change. Using a filtering picker to drive a dynamic picker hence
does duplicate work of filtering thousands of matches for no reason. It
could also cause problems like interfering with the regex pattern in the
global search.

I tried to directly extract a PickerBase to be reused in Picker and
FilePicker and DynamicPicker, but the problem is that DynamicPicker is
actually a DynamicFilePicker (i.e. it can preview file contents) which
means we would need PickerBase, Picker, FilePicker, DynamicPicker and
DynamicFilePicker and then another way of sharing the previewing code
between a FilePicker and a DynamicFilePicker. By merging Picker and
FilePicker into Picker, we only need PickerBase, Picker and
DynamicPicker.

[gokuls-comment]: helix-editor#5714 (comment)
[mikes-comment]: helix-editor#5714 (comment)
When Picker and FilePicker are merged, not all Pickers
will be able to show a preview
@sudormrfbin sudormrfbin force-pushed the merge-picker-and-filepicker branch from 15b8c3e to 792c8f9 Compare February 3, 2023 06:55
@pascalkuthe pascalkuthe added A-helix-term Area: Helix term improvements E-medium Call for participation: Experience needed to fix: Medium / intermediate S-waiting-on-review Status: Awaiting review from a maintainer. labels Feb 3, 2023
@pascalkuthe pascalkuthe added this to the next milestone Feb 9, 2023
Copy link
Member

@the-mikedavis the-mikedavis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The commit layout is awesome, it feels like I just watched you make this change live 😀

This refactor makes sense to me - I think I see where you're going for making filtering/sorting optional 👍

@@ -883,15 +863,15 @@ pub type DynQueryCallback<T> =
/// A picker that updates its contents via a callback whenever the
/// query string changes. Useful for live grep, workspace symbols, etc.
pub struct DynamicPicker<T: ui::menu::Item + Send> {
file_picker: FilePicker<T>,
file_picker: Picker<T>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be renamed to just "picker" now?

@Proful
Copy link

Proful commented Feb 10, 2023

The commit layout is awesome, it feels like I just watched you make this change live 😀

any video link?

options: Vec<T>,
editor_data: T::Data,
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
callback_fn: Box<dyn Fn(&mut Context, &T, Action) + 'static>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reason behind changing from static dispatch to dynamic dispatch?

impl Fn -> Box<dyn Fn

options: Vec<T>,
editor_data: T::Data,
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
callback_fn: Box<dyn Fn(&mut Context, &T, Action) + 'static>,
preview_fn: Option<FilePreviewFn<T>>,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As Picker is generic now File prefix can be renamed from FilePreviewFn?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the preview only works for files so I think this name fits. This type also didn't exist before this change

options: Vec<T>,
editor_data: T::Data,
callback_fn: impl Fn(&mut Context, &T, Action) + 'static,
preview_fn: impl Fn(&Editor, &T) -> Option<FileLocation> + 'static,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better Preview can be any content not only File content.
FileLocation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changing what the preview can show would be out of scope for this refactor PR I think - https://github.com/helix-editor/helix/pull/5492/files#r1070336613 is looking to change that anyways

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just calling it PreviewFn now would be easy enough so we don't have to rename in the future?

I don't think the capability itself should be added in this PR but it would be a small change to future proof here to avoid renames (and larger diffs/merge conflicts) in the future

@@ -2616,7 +2616,7 @@ pub fn command_palette(cx: &mut Context) {
}
}));

let picker = Picker::new(commands, keymap, move |cx, command, _action| {
let picker = Picker::without_preview(commands, keymap, move |cx, command, _action| {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd still name this new() we could also make the with_preview() a builder function that takes `self‘ so you'd chain these: new(..).with_preview(..)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think beside this, everything else looks okay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-helix-term Area: Helix term improvements E-medium Call for participation: Experience needed to fix: Medium / intermediate S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants