helix icon indicating copy to clipboard operation
helix copied to clipboard

Add file browser

Open drybalka opened this issue 1 year ago โ€ข 20 comments

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.

drybalka avatar Jul 23 '24 15:07 drybalka

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.

daedroza avatar Jul 25 '24 14:07 daedroza

@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

gj1118 avatar Jul 25 '24 15:07 gj1118

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 avatar Jul 25 '24 16:07 drybalka

@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.

drybalka avatar Jul 25 '24 16:07 drybalka

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.

archseer avatar Jul 30 '24 20:07 archseer

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)));
    }
}

zegervdv avatar Aug 30 '24 05:08 zegervdv

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.

drybalka avatar Aug 30 '24 18:08 drybalka

@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!

baldwindavid avatar Sep 02 '24 15:09 baldwindavid

@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 avatar Sep 06 '24 11:09 zegervdv

@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?

drybalka avatar Sep 06 '24 16:09 drybalka

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:

https://github.com/user-attachments/assets/22113048-2d31-4382-acd0-0cc5d43ee9d7

thomasaarholt avatar Sep 10 '24 06:09 thomasaarholt

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

https://github.com/user-attachments/assets/c787a6eb-03bc-44a1-9e71-2a044a49a5c8

Here is the log from hx -vvv .

thomasaarholt avatar Sep 10 '24 06:09 thomasaarholt

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.

drybalka avatar Sep 10 '24 06:09 drybalka

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.

L-Trump avatar Sep 13 '24 17:09 L-Trump

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)

summersz avatar Sep 18 '24 20:09 summersz

So stoked to see this @drybalka! :heart_hands:

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 :)

m0ar avatar Sep 26 '24 10:09 m0ar

@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.

drybalka avatar Oct 03 '24 08:10 drybalka

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).

thomasaarholt avatar Oct 04 '24 10:10 thomasaarholt

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

Akselmo avatar Oct 09 '24 21:10 Akselmo

That's https://github.com/helix-editor/helix/discussions/10215

the-mikedavis avatar Oct 09 '24 21:10 the-mikedavis

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

Akselmo avatar Oct 21 '24 22:10 Akselmo

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!

peteringram0 avatar Nov 14 '24 21:11 peteringram0

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 avatar Nov 19 '24 10:11 irh

@peteringram0 The flicker is an unfortunate limitation of the current picker design. The problem is that I could not find any way to update the currently opened picker, so to switch a folder it actually has to close the current picker with a callback to open a new one in the new folder. Depending on the build profile of your helix (development vs production) and the folder size this may or may not be visible. The solution is not the most elegant, but I was lucky that it exists at all without a major refactoring. I think not so many pickers actually need to update themselves and so this functionality was not yet implemented. Hopefully after the refactoring of the pickers this can be improved.

drybalka avatar Nov 26 '24 20:11 drybalka

@peteringram0 The flicker is an unfortunate limitation of the current picker design. The problem is that I could not find any way to update the currently opened picker, so to switch a folder it actually has to close the current picker with a callback to open a new one in the new folder. Depending on the build profile of your helix (development vs production) and the folder size this may or may not be visible. The solution is not the most elegant, but I was lucky that it exists at all without a major refactoring. I think not so many pickers actually need to update themselves and so this functionality was not yet implemented. Hopefully after the refactoring of the pickers this can be improved.

Makes sense and I don't think this issue should merge. Thank you for your time on this!

peteringram0 avatar Nov 26 '24 20:11 peteringram0

@peteringram0

I don't think this issue should merge

What did you mean here?

thomasaarholt avatar Nov 26 '24 21:11 thomasaarholt

@peteringram0

I don't think this issue should merge

What did you mean here?

Sorry i was supposed to write that I don't think the issue with the flicking should prevent the PR getting merged.

peteringram0 avatar Nov 26 '24 21:11 peteringram0

@irh As you and several people already requested it I think it indeed makes sense to make file_browser symmetric to file_picker and so one can now map separately file_browser, file_browser_in_current_buffer_directory and file_browser_in_current_directory to behave exactly like file_picker.

drybalka avatar Nov 27 '24 07:11 drybalka

@drybalka That's awesome, thanks ๐Ÿ™

I'm using it like this:

[keys.normal.space]
"e" = "file_browser"
"E" = "file_browser_in_current_buffer_directory"

(b is used for the buffer picker, so I've gone with 'e' for 'explorer' ๐Ÿ˜€)

This behaves exactly as I'd like, great work, no notes ๐Ÿ‘

irh avatar Nov 27 '24 14:11 irh

braced myself to try merging this into my fork and... it was seamless?
clean commit history, no merge conflicts, or conflicts with my fork, majestically

thank you very much! <3

although I'd love for helix to have a proper file browser (not powered by a classic picker, I mean), this is still very very useful, and I think should be in core!

Axlefublr avatar Nov 30 '24 13:11 Axlefublr