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

Add file browser #11285

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Conversation

drybalka
Copy link

@drybalka drybalka commented Jul 23, 2024

This is a minimal implementation of the file browser, which would probably cover a lot of requirements in #200. The whole thing works analogous to the https://github.com/nvim-telescope/telescope-file-browser.nvim as suggested in this comment. Even though the resolution of the discussion seems to be "file tree/browser is too hard, it should be implemented as a plugin", I feel like my changes are quite small and natural to be considered for adding to the core nonetheless.

The implementation simply builds on the existing file picker and only modifies 3 files, so the added maintenance burden should be quite small. The code itself is not particularly elegant (in my rather inexperienced opinion), but I did not want to over-complicate things. This is also the reason why some features might be missing.

Feel free to modify this PR or simply make suggestions, I'd be happy to improve it. This is also my first PR here, so sorry if I miss anything.

@kirawi kirawi added the A-command Area: Commands label Jul 24, 2024
@daedroza
Copy link
Contributor

Would it be possible to implement a file browser with this methodology instead? https://github.com/stevearc/oil.nvim

It uses a buffer/pop to navigate and edit files like you're inside a buffer.

@gj1118
Copy link
Contributor

gj1118 commented Jul 25, 2024

@drybalka this is awesome.. thanks for the effort. Can you please post a screenshot as to how it looks ? Basically I am interested to show how nested directories/files are being presented.
Thanks

@drybalka
Copy link
Author

Would it be possible to implement a file browser with this methodology instead? https://github.com/stevearc/oil.nvim

It uses a buffer/pop to navigate and edit files like you're inside a buffer.

I am not a maintainer of helix, but in my opinion this is rather a plugin functionality. First of all, it would be hard-ish to implement and therefore to maintain. Secondly, buffers are primarily used for text editing and one does not usually need to create/delete/rename files so much.

@drybalka
Copy link
Author

drybalka commented Jul 25, 2024

@drybalka this is awesome.. thanks for the effort. Can you please post a screenshot as to how it looks ? Basically I am interested to show how nested directories/files are being presented. Thanks

Well, the idea was to make it look and behave like the original telescope-file-browser, so you may look at the showcase video there (just without all pretty-niceness as this is just a proof-of-concept). As for a real screenshot it looks (quite bare bones) like this:
image

In other words, both the picker and the preview (if a dir is selected) show the contents at depth 1, similar to how ls works.

@archseer
Copy link
Member

I kind of like just how simple this change is! It reuses existing UI components and allows exploring the file tree without adding any of the heavier features.

Comment on lines 305 to 311
if let Ok(files) = directory_content {
for file in files {
if injector.push(file).is_err() {
break;
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

This style is used by the file picker because finding files is a potentially long-running iterator and we might use the injector to push some files asynchronously after a timeout. Since you've already collected the directory contents above you should pass that vec as the third argument to Picker::new

Copy link
Member

Choose a reason for hiding this comment

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

Also I believe this function should return a result and pass up the error from directory_content. Currently if you fail to list the directory contents a blank picker opens

Copy link
Author

Choose a reason for hiding this comment

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

Great suggestions, simplified the code, thank you!

helix-term/src/commands.rs Show resolved Hide resolved
helix-term/src/ui/mod.rs Show resolved Hide resolved
@kirawi kirawi added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 3, 2024
@the-mikedavis the-mikedavis added S-waiting-on-review Status: Awaiting review from a maintainer. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 11, 2024
@zegervdv
Copy link

I think it would be useful to have the equivalent version of file_picker_in_current_buffer_directory. I often use this, only to realize I need to go one or more levels up. The file_browser would solve that perfectly :).

It could be something like this:

fn file_browser_in_current_buffer_directory(cx: &mut Context) {
    let doc_dir = doc!(cx.editor)
        .path()
        .and_then(|path| path.parent().map(|path| path.to_path_buf()));

    let path = match doc_dir {
        Some(path) => path,
        None => {
            cx.editor.set_error("current buffer has no path or parent");
            return;
        }
    };

    if let Ok(picker) = ui::file_browser(path) {
        cx.push_layer(Box::new(overlaid(picker)));
    }
}

@drybalka
Copy link
Author

I think it would be useful to have the equivalent version of file_picker_in_current_buffer_directory. I often use this, only to realize I need to go one or more levels up. The file_browser would solve that perfectly :).

I think this can even be the default behavior, thanks for suggesting! Not sure when I would even need to open a file browser in the project root. I deliberately wanted to keep this PR simple and feature-poor, but your suggestion is quite simple and I think it is worth it.

@baldwindavid
Copy link

baldwindavid commented Sep 2, 2024

@drybalka This is perfect with the change to the current buffer directory. It's similar to good ol' netrw for quick navigation and covers 95% of the needs for me. The more advanced stuff (copy, paste, create, delete, etc) can be covered by a mix of #11164, shell scripts, wezterm, and the yazi file explorer. Thanks for your work!

@zegervdv
Copy link

zegervdv commented Sep 6, 2024

@drybalka found a small issue when testing: if the cursor is on a binary file, the preview will mess up the view and leave random characters everywhere. Maybe binary files can be excluded from preview somehow?
These files are normally excluded from the file_picker, so maybe this is a more general issue with the preview.

@drybalka
Copy link
Author

drybalka commented Sep 6, 2024

@drybalka found a small issue when testing: if the cursor is on a binary file, the preview will mess up the view and leave random characters everywhere. Maybe binary files can be excluded from preview somehow? These files are normally excluded from the file_picker, so maybe this is a more general issue with the preview.

@zegervdv I am using the same file previewer as file_picker, so the problem is probably in the previewer itself. Although as far as I tested the usual .jpg, .pdf, and executables are all correctly previewed as <Binary file>. Maybe you're using some exotic file formats?

@thomasaarholt
Copy link
Contributor

It would be nice to add support for going straight to the root of the project if the current buffer hasn't been saved yet. I went to test the file browser functionality by escaping the file picker when calling hx ., but then it didn't work:

Screen.Recording.2024-09-10.at.08.18.51.mov

@thomasaarholt
Copy link
Contributor

Actually, I can't get this to work at all? Running on MacOS.

Screen.Recording.2024-09-10.at.08.47.35.mov

Here is the log from hx -vvv .

@drybalka
Copy link
Author

drybalka commented Sep 10, 2024

Actually, I can't get this to work at all? Running on MacOS.

Well, this is actually the behavior I get when using the command palette for the file_picker as well, I guess the palette is somehow buggy in this regard. I just mapped it to some keymap and tested like that.

But anyway, even if you map it correctly and then try to open the file_browser after hx . then it will probably still would not work. The behavior is the same as file_picker and requires an opened document to get the current path where to open the browser. I guess it would make sense to default it to the current working directory.

@L-Trump
Copy link

L-Trump commented Sep 13, 2024

Actually, I can't get this to work at all? Running on MacOS.
Screen.Recording.2024-09-10.at.08.47.35.mov

Here is the log from hx -vvv .

Actually in current latest version of helix, no file picker can open from the command pallete (tried in nixos and archlinux). It seems like another bug.

@summersz
Copy link

I have the same reported issue when trying to open the browser from the command palette. Works great when opened from a keymap though.

I do have a couple of suggestions to consider

  1. Can directory names be appended with a '/' to distinguish them (like netrw)

  2. Can left and right keys be used to navigate down and up directories, respectively? ( I have gotten used to this in yazi and find it very intuitive)

@m0ar
Copy link

m0ar commented Sep 26, 2024

So stoked to see this @drybalka! 🫶

Probably not worth it at this stage as merging the base feature is higher priority, but it'd be cool be be able to classify the entries with icons. Having a trailing slash on dirs makes sense, but hugely useful IMO to when something is linked, and being able to visually filter on filetypes.

Kinda like lsd, which has a default set of unicode chars, but being able to opt in to using nerdfont glyphs for extra gloss.

image

I could probably take a look at doing this when this is in if you aren't feeling it :)

@drybalka
Copy link
Author

drybalka commented Oct 3, 2024

@summersz Adding slash to dirs is a great idea, thank you! Using other keys in a picker is harder. The current design does not allow picker-specific keymaps, and even remapping the existing keys is not allowed yet. I will leave this idea for the future, as pickers refactor should come at some point.

@m0ar I also really like the idea with icons! The file_browser picker shares a lot of code with the file_picker, so if the icons would work there then most probably they will also work here. I don't want to complicate this PR with icons at this point, but you may already try implementing them for the file_picker.

helix-term/src/ui/picker.rs Outdated Show resolved Hide resolved
helix-term/src/ui/mod.rs Outdated Show resolved Hide resolved
@the-mikedavis the-mikedavis added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from a maintainer. labels Oct 3, 2024
@thomasaarholt
Copy link
Contributor

thomasaarholt commented Oct 4, 2024

To use this, you can add the following keybinding to your config (:config-open, and then after saving :config-reload):

[keys.normal.space.space]
f = "file_browser"

Now, you can double-tap space and then press f to open the file browser.

Note that you cannot open the file browser from the command palette due to #4508 (as discussed above).

@the-mikedavis the-mikedavis added S-waiting-on-review Status: Awaiting review from a maintainer. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Oct 4, 2024
@Akselmo
Copy link
Contributor

Akselmo commented Oct 9, 2024

I love this feature. Could it also change the working-directory too, if for example i navigate to completely different project? Though that is probably for something like autochdir

@the-mikedavis
Copy link
Member

That's #10215

@Akselmo
Copy link
Contributor

Akselmo commented Oct 21, 2024

To use this, you can add the following keybinding to your config (:config-open, and then after saving :config-reload):

[keys.normal.space.space]
f = "file_browser"

Now, you can double-tap space and then press f to open the file browser.

Note that you cannot open the file browser from the command palette due to #4508 (as discussed above).

Alternatively if you want to use the file_browser as default, you can replace file_picker with file_browser in helix-term/src/keymap/default.rs

Copy link

@ryanabx ryanabx left a comment

Choose a reason for hiding this comment

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

Simple and relatively clean impl. Also tested it, and other than #4508, which is a separate issue, looks good to me!

It may just be personal preference to me, but I actually preferred having it open in the root of the cwd, as opposed to the directory of the currently open buffer. I'd be fine having any hierarchical file browser over none though, so that's not a blocker for me! Perhaps in the future, having an "open file browser at current working directory" would be a nice-to-have.

It may also be worth considering adding a default keybinding for the file browser, but that might be worth doing in a separate PR to not prolong this one

@peteringram0
Copy link

I tested your branch and it solves a large problem for me in a very large repo!! I was planning to recommend using the right/left arrows on dir's like @summersz comment but accept your reply on this matter. Im not sure why but there is a flicker when navigating directories, its almost like the window opens and closes quickly which looks jaring but apart form that I think you got a really nice branch here, hope this one makes it in!

@irh
Copy link
Contributor

irh commented Nov 19, 2024

I just tried this out and it's great, nice work! 👏

@drybalka
To offer my 2¢ on the working vs. buffer directory topic, we already have file_picker/file_picker_in_current_buffer_directory, so personally I would expect to see file_browser/file_browser_in_current_buffer_directory, with the file_browser picker opening in the current working directory.

Not sure when I would even need to open a file browser in the project root.

This would be useful for me when I'm working with a large project, especially one that I'm not familiar with. e.g. I'm looking at some file deep in the tree and I want to reorient myself and start navigating again from the root.

@peteringram0

Im not sure why but there is a flicker when navigating directories

I noticed this too when trying it out with cargo run, but the flicker doesn't show for me at all in a release build.

irh pushed a commit to irh/helix that referenced this pull request Nov 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-command Area: Commands S-waiting-on-review Status: Awaiting review from a maintainer.
Projects
None yet
Development

Successfully merging this pull request may close these issues.