neo-tree.nvim icon indicating copy to clipboard operation
neo-tree.nvim copied to clipboard

feat: add preview command and position handling

Open mrbjarksen opened this issue 2 years ago • 4 comments

This PR adds commands to preview nodes which correspond to files or file positions. It also allows the standard open commands to open files at positions given by position nodes.

A position node is defined as a node with the field extra.position, which is an array-like table of the form { <line>, <column> }, where the line and column numbers are 0-based (it might be more sensible to change this to (1, 0)-based indexing). If the field extra.end_position is present, previewing the node will highlight the range between position and end_positions.

The code is adapted from mrbjarksen/neo-tree-diagnostics.nvim#1. It is likely that this feature will need some tweaking and testing before it can be merged. I have added the branch native-open-and-preview to neo-tree-diagnostics.nvim to test this feature using position nodes.

mrbjarksen avatar Aug 13 '22 19:08 mrbjarksen

Codecov Report

Merging #482 (8665fac) into main (5bb0a38) will decrease coverage by 0.94%. The diff coverage is 14.85%.

@@            Coverage Diff             @@
##             main     #482      +/-   ##
==========================================
- Coverage   52.60%   51.66%   -0.95%     
==========================================
  Files          46       47       +1     
  Lines        5714     5888     +174     
==========================================
+ Hits         3006     3042      +36     
- Misses       2708     2846     +138     
Impacted Files Coverage Δ
lua/neo-tree/defaults.lua 96.87% <ø> (ø)
lua/neo-tree/events/init.lua 100.00% <ø> (ø)
lua/neo-tree/utils.lua 48.26% <4.16%> (-0.91%) :arrow_down:
lua/neo-tree/sources/common/commands.lua 8.30% <5.26%> (-0.44%) :arrow_down:
lua/neo-tree/sources/common/preview.lua 18.18% <18.18%> (ø)
lua/neo-tree/setup/init.lua 73.24% <100.00%> (-0.07%) :arrow_down:
lua/neo-tree/ui/highlights.lua 93.68% <100.00%> (+0.06%) :arrow_up:
lua/neo-tree/sources/common/file-items.lua 67.40% <0.00%> (-1.02%) :arrow_down:
lua/neo-tree/sources/common/components.lua 61.60% <0.00%> (-0.22%) :arrow_down:
... and 5 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

codecov[bot] avatar Aug 13 '22 19:08 codecov[bot]

I played around with it and I found that I intuitively wanted it to work a different way. I am picturing a "preview mode", where once activated, it previews whatever my cursor is focused on and follows that focus, until the "preview mode" is toggle off.

When the preview goes off, I'm not sure if it should stick on the last file or go back to the file that was open beforehand.

I would also prefer if there were a single mapping that toggled it off and on.

I think there also needs to be some visual indication that preview mode is enabled.

One way to accomplish the above is if it previews in a floating window where the title bar has some text to indicate that it is a preview window. Then when it is closed it is clear that it should just disappear and you will be left with the original windows underneath it. Then hitting enter, or any other command that normally opens a file will close that preview window and open the file as normal.

What do you think?

cseickel avatar Aug 14 '22 00:08 cseickel

I agree that it would be great to have the preview follow the focused node, and that is how I envisioned it at first. At the time, I had some issues with CursorMoved events (switching windows caused errors). It might be time to revisit this. The suggestions in #134 to use vim.loop sound promising, but I'll admit the API has gone over my head when I've tried to learn to use it.

In my mind, the preview should ideally be a sort of answer to 'What happens if I open this?', showing exactly which window will be used and the view within said window if you choose to press enter, while changing nothing about the state of the user space (e.g. listed buffers, cursor positions, etc.) while it is active. Note that the preview commands in their current state do not entirely accomplish this.

Using a floating window might be more sensible, being less complex and only losing the ability to see which window will be used. I'm also not sure how to show visual indication using the method above. Another option, although less ideal, is using the built-in preview window.

I'd imagine the behavior of a preview is very opinionated and it may be worth implementing multiple options to choose from. I don't know if that is worth the extra maintenance though.

I'll look into making the preview follow the focus for now.

mrbjarksen avatar Aug 14 '22 13:08 mrbjarksen

I agree that it would be great to have the preview follow the focused node, and that is how I envisioned it at first. At the time, I had some issues with CursorMoved events (switching windows caused errors).

Ideally showing the preview should not have to focus that preview window, so the focus should stay in the Neo-tree window. AT least that's how I picture it.

I'd imagine the behavior of a preview is very opinionated and it may be worth implementing multiple options to choose from. I don't know if that is worth the extra maintenance though.

I think in this case it is worthwhile because I'd imagine the preference will be pretty evenly split. If you want, I can add the floating window code (my preference) while you focus on the current "where it would normally open" code.

I'm also not sure how to show visual indication using the method above.

I was thinking that we could just add a window local variable that acts as a flag, then it could be added to someone's customized statusline or winbar. Something like 'vim.w.neo_tree_preview = 1'. Not everyone digs that deep into customizing their statusline/winbar, but for those of us that do then this would be enough.

cseickel avatar Aug 14 '22 13:08 cseickel

Ideally showing the preview should not have to focus that preview window, so the focus should stay in the Neo-tree window. AT least that's how I picture it.

I agree. What I meant was that manually switching windows while the preview was active caused issues. Sorry if I wasn't clear.

I think in this case it is worthwhile because I'd imagine the preference will be pretty evenly split. If you want, I can add the floating window code (my preference) while you focus on the current "where it would normally open" code.

That sounds good. It shouldn't be too much trouble to hook into my existing preview module, opening a new floating window instead of using findWindow. I'll leave it to you if you want to go that route or implement it separately.

I was thinking that we could just add a window local variable that acts as a flag, then it could be added to someone's customized statusline or winbar. Something like 'vim.w.neo_tree_preview = 1'. Not everyone digs that deep into customizing their statusline/winbar, but for those of us that do then this would be enough.

That's a good idea, I hadn't thought of that. It's probably the best way to go.

mrbjarksen avatar Aug 14 '22 14:08 mrbjarksen

I just added a toggle_preview command. It was simpler than I thought and I'm not having the same issues I had before. I've only tested it a small amount though. Let me know if you find anything.

mrbjarksen avatar Aug 14 '22 15:08 mrbjarksen

I've implemented the fixes you mentioned. It was more trouble than I was expecting as I ran into a mess of autocommands, mostly triggered by jumping windows in get_appropriate_window, which took a while to debug. It seems to be fixed now.

One thing I noticed was that entering a neo-tree buffer from another neo-tree buffer does not trigger NeoTreeBufferLeave, since the event handler for BufEnter returns early if the entered buffer belongs to neo-tree. I'm not sure if this is intentional or not, so I haven't touched it, but it means that the preview mode will not be turned off when switching sources. This could be fixed by adding an event handler for NeoTreeBufferEnter as well, if you don't want to change this.

mrbjarksen avatar Aug 16 '22 15:08 mrbjarksen

One thing I noticed was that entering a neo-tree buffer from another neo-tree buffer does not trigger NeoTreeBufferLeave, since the event handler for BufEnter returns early if the entered buffer belongs to neo-tree. I'm not sure if this is intentional or not, so I haven't touched it,

No, that's not intentional. I just never considered that situation before. It should trigger a NeoTreeBufferLeave followed by a NeoTreeBufferEnter. I'll put that in as a bug.

cseickel avatar Aug 16 '22 15:08 cseickel

Greatest feature! When there's no open buffer (such as starting with the alpha-nvim greeting), disabling preview causes some errors: Other than that, it works great.

E5108: Error executing lua: ...rt/neo-tree.nvim/lua/neo-tree/sources/common/preview.lua:150: Vim(append):Error executing lua callback: ..
.are/nvim/site/pack/packer/start/alpha-nvim/lua/alpha.lua:550: Cursor position outside buffer
stack traceback:
        [C]: in function 'nvim_win_set_cursor'
        ...are/nvim/site/pack/packer/start/alpha-nvim/lua/alpha.lua:550: in function 'draw'
        ...are/nvim/site/pack/packer/start/alpha-nvim/lua/alpha.lua:566: in function 'redraw'
        ...are/nvim/site/pack/packer/start/alpha-nvim/lua/alpha.lua:473: in function <...are/nvim/site/pack/packer/start/alpha-nvim/lua/a
lpha.lua:473>
        [C]: in function 'nvim_win_set_buf'
        ...rt/neo-tree.nvim/lua/neo-tree/sources/common/preview.lua:150: in function 'setBuffer'
        ...rt/neo-tree.nvim/lua/neo-tree/sources/common/preview.lua:73: in function 'revert'
        ...t/neo-tree.nvim/lua/neo-tree/sources/common/commands.lua:400: in function 'func'
        .../packer/start/neo-tree.nvim/lua/neo-tree/ui/renderer.lua:695: in function <.../packer/start/neo-tree.nvim/lua/neo-tree/ui/rend
erer.lua:693>
stack traceback:
        [C]: in function 'nvim_win_set_buf'
        ...rt/neo-tree.nvim/lua/neo-tree/sources/common/preview.lua:150: in function 'setBuffer'
        ...rt/neo-tree.nvim/lua/neo-tree/sources/common/preview.lua:73: in function 'revert'
        ...t/neo-tree.nvim/lua/neo-tree/sources/common/commands.lua:400: in function 'func'
        .../packer/start/neo-tree.nvim/lua/neo-tree/ui/renderer.lua:695: in function <.../packer/start/neo-tree.nvim/lua/neo-tree/ui/rend
erer.lua:693>

barreiroleo avatar Aug 16 '22 19:08 barreiroleo

😱 OH NO! A stack trace that includes two different plugins! 😱

Seriously though, I'm going to open a new issue for this.

cseickel avatar Aug 16 '22 20:08 cseickel

Maybe a check before reverting the buffer is all, if there isn't a previous buffer open a new one... Just thinking out loud, haven't read the code yet.

barreiroleo avatar Aug 16 '22 20:08 barreiroleo