Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

feat: keep nnn open #61

Closed
PartyLich opened this issue May 25, 2020 · 21 comments
Closed

feat: keep nnn open #61

PartyLich opened this issue May 25, 2020 · 21 comments
Labels
enhancement New feature or request

Comments

@PartyLich
Copy link

Is your feature request related to a problem? Please describe.
Coming from more graphical editors and IDEs, I'm used to having a file explorer open all the time.

Describe the solution you'd like

Using netrw in nvim I can get roughly equivalent behavior:
asciicast
Is it possible to do this with nnn instead?

Describe alternatives you've considered
Seems feasible to pass the file list back to vimscript on some bindable keypress and then process it as usual. I dont have the familiarity with nnn or vimscript to implement it myself atm.

@PartyLich PartyLich added the enhancement New feature or request label May 25, 2020
@PartyLich PartyLich changed the title Keep nnn open feat: keep nnn open May 25, 2020
@mcchrish
Copy link
Owner

Seems to be a popular request to have a nerdtree like persistent session/window. #55
#43

It might be possible to implement this features by communicating with nnn via stdout. I don't have much free time to implement it, but I welcome anyone who wants to submit a PR.

@PartyLich
Copy link
Author

I think #43 and #55 are different from my request in that they expect nnn to close, but want the open directory to persist/be remembered.

  • Naively, if we have access to the path currently visible in nnn, perhaps it could be stored in a script variable (again, im not versed in vimscript).
    For Use one instance for nnn or remember nnn paths #43,

    "When i reopen nnn in those buffers. It should open the current path of that buffer."

    sounds to me like getting the current head (something like expand('%:p:h')) and using it as the l:directory in nnn#pick(...), if the command is called without its own directory argument.
    A little playing around with setting a g:nnn#last_dir sort of works, but perhaps there's a more suitable scope for this sort of thing. I tried setting it in s:eval_temp_file, and that setup causes nnn to open to the dir of whichever file is opened, which in my brief test was the last item selected. That approach doesn't really involve nnn at all, so I imagine there's some case(s) where it doesnt behave as desired.
    I also just realized that this wasnt default behavior; my vim config is set to change the cwd to the open buffer (autocmd BufEnter * lcd %:p:h), so nnn always opens to the buffer directory for me without any plugin modification.

    "remember path of each context [1][2][3][4], it's the best."

    sounds like Persistent nnn session for a vim session #55 and using nnn's session options as that issue's poster suggests.

My personal desire is to have nnn stay open and visible. I'm not asking the plugin to store session data at all, so as I understand the requests in those other two issues implementing them wouldn't give me the behavior I want.

Perhaps I'm just not (yet) adapted to a vim-centric workflow. When I can see the dir tree, i tend to structure around that tree. As I've been using nvim primarily the past few weeks, I've found myself creating a lot more gigantic files and trying to navigate within files instead of between files.

In any case, I understand that your time constrained, and I'll continue looking for other solutions/workflows/etc

@vhristev
Copy link

Im also interested in NNN persistant pane. You describe it very well like NerdTREE no matter if you open the file the File Browser do not close after opening the file.

@vhristev
Copy link

Still nothing about that. It would be very helpful to have persistent pane.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

Please be patient.

Anyway, taking a look over this, the first thing I question is, when a file is selected from the nnn file explorer, which existing window should it replace in case there are multiple? Should it be the window that was in focus before focus transferred to the nnn window? And if the nnn window is the only open window, should it open in a vertical split of some sort?

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

Since nnn (not nnn.vim) only writes to the picker file on exit, there is currently no way to use a persistent nnn window to navigate files and open corresponding files as buffers. One possibility I can foresee is nnn "flushing" to the picker file on some event/keypress, or some variation where there is an option where <Enter> can flush to the file without quitting the process. The issue, however, is that you would need to poll the file at a very quick interval (not optimal) or, if possible, something like kqueue within Vim, but I doubt it is doable.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

It might be possible to implement this features by communicating with nnn via stdout. I don't have much free time to implement it, but I welcome anyone who wants to submit a PR.

@mcchrish This is an interesting idea, but could you elaborate a tad more? I have never quite thought about a curses process communicating via stdout. I guess it would be an alternative to the picker file, maybe -p - with Vim waiting for input.

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

I think what the user is looking for is, nnn should not quit when files are picked using Enter and should stay put in the original buffer where it was opened.

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

User provides the picker output file and whenever she acts (presses Enter on a file), nnn writes to it. No need to keep watching.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

I guess we can have some keybind that is intercepted before it reaches nnn. But this would not interact with the picker file. Or if it would, Vim, would essentially act as a middle-man for the keybind.

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

Yes, it seems so. We would need to change the behaviour of nnn closing when files are picked.

So maybe a switch or something.

@mcchrish
Copy link
Owner

It might be possible to implement this features by communicating with nnn via stdout. I don't have much free time to implement it, but I welcome anyone who wants to submit a PR.

@mcchrish This is an interesting idea, but could you elaborate a tad more? I have never quite thought about a curses process communicating via stdout. I guess it would be an alternative to the picker file, maybe -p - with Vim waiting for input.

Exactly -p - will output the selected files to stdout. And aside from exit callback, vim/nvim also accepts stdout callback that can handle stdout events, :h termopen().

However, nnn -p - exits after selection. nnn probably should have an option to not exit and just rather clear the selection after pushing them to stdout.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

I think we would need to use the stdout method since Vim must communicate with nnn first, them nnn communicates back with Vim.

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

Sure!

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

I would love to help make the -p - feature work, and I am working on getting familiar with the nnn codebase. Do you have any ideas on which specific parts of the source code need to be changed?

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

You'll have to follow the picker variable. Give me a day, I am getting rid of the other variable.

@jarun
Copy link
Collaborator

jarun commented May 18, 2021

Done with the change at jarun/nnn@2bd72d1.

Now you can follow the picker and picked variables. picker says nnn should write selection to picker output file/stdout before exit. picked says some files were picked by a plugin.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

I've tested it on both Vim8 (out_cb) and Neovim (on_stdout) and the issue is that for both of those, their callback prints a part of the buffer every time I move around the nnn buffer with escape codes and all, not a separate stdout channel like I'd expect.

My only change to nnn was to comment out line 6290:

https://github.com/jarun/nnn/blob/2bd72d1b29d968204421e9a479bc1c159a9dc490/src/nnn.c#L6290

which is probably incorrect for most purposes but was just a test.

My logging output looks like this:

image

Maybe the help page for :h job-out_cb for Vim will be useful:

Callback for when there is something to read on
stdout. Only for when the channel uses pipes. When
"out_cb" wasn't set the channel callback is used.
The two arguments are the channel and the message.

Emphasis mine.

I suspect I may be doing something wrong, but I do not know how to proceed.

@mcchrish
Copy link
Owner

mcchrish commented May 18, 2021

I'm trying some experiments a bit and see if might be helpful. I'm using neovim 0.4.4 and nnn 4.0.

A small vimscript to test out:

function! s:callback(id, data, name)
  echom string([a:id, a:data])
endfunction

function! s:test_nnn()
  call termopen('nnn -p -',  {'on_stdout': function('s:callback') })
endfunction

I'm getting the same result:

[6, ['^[[?1049h^[[1;38r^[(B^[[m^[[4l^[[?7h^[[?1h^[=^[[?1000h']]
[6, ['^[[?25l']]
[6, ['^[[39;49m^[[39;49m^[(B^[[m^[[H^[[2J[^[(B^[[0;1;7m^[[34m1^[[39m^[(B^[[m 2 3 4] ^[(B^[[0;4m^[[34m~/vimming/nnn.vim^[[3;2H^[(B^[[0;1;7m^[[38;5;39mautoload^[[
39m^[(B^[[m/^M^[[4d ^[(B^[[0;1m^[[38;5;39mdoc^[[39m^[(B^[[m/^M^[[5d ^[(B^[[0;1m^[[38;5;39mftplugin^[[39m^[(B^[[m/^M^[[6d ^[(B^[[0;1m^[[38;5;39mpathtofolder^[[39
m^[(B^[[m/^M^[[7d ^[(B^[[0;1m^[[38;5;39mplugin^[[39m^[(B^[[m/^M^[[8d LICENSE^M^[[9d README.md^M^[[10d minimalvimrc^M^[[38d^[[34m1/8 2021-05-18 16:41 drwxr-xr-x
96B^[[39m^[(B^[[m']]
[6, ['^M^[[3d ^[(B^[[0;1m^[[38;5;39mautoload^[[4;2H^[(B^[[0;1;7m^[[38;5;39mdoc^M^[[38d^[(B^[[0m^[[34m2^[[8G0-09-27 09:29^[[38;33H128B^[[39m^[(B^[[m']]
[6, ['^M^[[4d ^[(B^[[0;1m^[[38;5;39mdoc^[[5;2H^[(B^[[0;1;7m^[[38;5;39mftplugin^M^[[38d^[(B^[[0m^[[34m3^[[38;11H5-25 07:53^[[38;33H96B^[[39m^[(B^[[m^[[K']]
[6, ['^M^[[5d ^[(B^[[0;1m^[[38;5;39mftplugin^[[6;2H^[(B^[[0;1;7m^[[38;5;39mpathtofolder^M^[[38d^[(B^[[0m^[[34m4/8 2019-02-27 17:49^[[38;33H128B^[[39m^[(B^[[m']]

[6, ['^M^[[6d ^[(B^[[0;1m^[[38;5;39mpathtofolder^[[7;2H^[(B^[[0;1;7m^[[38;5;39mplugin^M^[[38d^[(B^[[0m^[[34m5/8 2020-09-27 09:17^[[38;33H96B^[[39m^[(B^[[m^[[K']
]
[6, ['^M^[[7d ^[(B^[[0;1m^[[38;5;39mplugin^[[8;2H^[[39m^[(B^[[0;7mLICENSE^M^[[38d^[(B^[[0m^[[34m6^[[8G1-02-28 09:39 -rw-r--r-- 1.3K^[[39m^[(B^[[m']]
[6, ['^M^[[8d+^[[38;4H^[[34m ^[(B^[[0;7m^[[34m 1 ^[(B^[[0m^[[34m 2021-02-28 09:39 -rw-r--r-- 1.3K^[[39m^[(B^[[m']]
[6, ['^[[?1000l']]
[6, ['^[[38;1H^[[?12l^[[?25h^[[?1049l^M^[[?1l^[>/Users/mcchris/vimming/nnn.vim/LICENSE^M', '/Users/mcchris/vimming/nnn.vim/LICENSE^M', '']]
[6, ['']]

But if you take a look at the end, the selected files are found in the output:

[6, ['^[[38;1H^[[?12l^[[?25h^[[?1049l^M^[[?1l^[>/Users/mcchris/vimming/nnn.vim/LICENSE^M', '/Users/mcchris/vimming/nnn.vim/LICENSE^M', '']]

It just seems like nnn outputs some other UI data/escape codes to stdout.

If I changed termopen command with a simple echo:

  call termopen('echo "hello"',  {'on_stdout': function('s:callback') })

The output is simply:

[6, ['hello^M', '']]

If I try using ranger, I'm met with a similar output as nnn:

[4, ['^[[?1049h^[[1;38r^[(B^[[m^[[4l^[[?7h^[[?1h^[=']]
[4, ['^[[?25l^[[39;49m^[[?1000h']]
[4, ['^[[39;49m^[(B^[[m^[[H^[[2J']]
[4, ['', '^[[J^[[Aloading...^[[K^[kranger^[\^[[?1h^[=']]
[4, ['^[[?1000h^[kranger^[\']]
[4, ['^M^[(B^[[0;1m^[[32mmcchris@mc-mbp.local ^[[34m/Users/mcchris/vimming/nnn.vim/^[[39mautoload^[[K^M', '^[[91m ^[[94mbabbled.nvim     ^[[39m^[(B^[[m ^[(B^[[0
;1;7m^[[94m autoload                                               1 ^[[39m^[(B^[[m ...^M', '^[(B^[[0;1m^[[91m ^[[94minfo-window.nvim ^[[39m^[(B^[[m ^[(B^[[0;1m
^[[91m ^[[94mdoc^[[52X^[[3;76H2 ^M', '^[(B^[[0;1;7m^[[94m nnn.vim          ^[[39m^[(B^[[m ^[(B^[[0;1m^[[91m ^[[94mftplugin^[[47X^[[4;76H1 ^M', '^[[91m ^[[94mtex
tmate.nvim    ^[[39m^[(B^[[m ^[(B^[[0;1m^[[91m ^[[94mpathtofolder^[[43X^[[5;76H2 ^M', '^[[91m ^[[94mvim-closer       ^[[39m^[(B^[[m ^[(B^[[0;1m^[[91m ^[[94mplug
in^[[49X^[[6;76H1 ^M', '^[[91m ^[[94mvim-no-color-col~^[[39m^[(B^[[m ^[(B^[[0;1m^[[91m ^[(B^[[0mLICENSE^[[7;71H1.34 K^[[8;20H^[(B^[[0;1m^[[91m ^[(B^[[0mminimalv
imrc^[[8;72H291 B^[[9;20H^[(B^[[0;1m^[[91m ^[(B^[[0mREADME.md^[[9;71H3.44 K^[[10;20H^[(B^[[0;1m^[[91m ^[(B^[[0mtest.txt^[[10;73H24 B^M^[[38d^[[36mdrwxr-xr-x^[[3
9m 3 mcchris staff 1 2021-05-18 16:41^[[38;128H11.1K sum, 19.5G free  1/9  Al^[[?7ll^[[?7h^[[1;11H^[(B^[[m^[[2;20H']]
[4, ['^[[2;79H^[(B^[[0;7m nnn.vim                                                                        ^[[2;20H^[(B^[[m']]
[4, ['^[[1;53H^[(B^[[0;1mdoc^[[K^[[2;20H^[[91m ^[[94mautoload^[[47X^[[2;76H1 ^[[39m^[(B^[[m ...^[(B^[[m^[[K^[[3;20H^[(B^[[0;1;7m^[[94m doc
                              2 ^[[38;12H^[(B^[[0m4^[[38;28H2 2020-09-27 09:29^[[151G2^[[2;20H^[(B^[[m', '']]
[4, ['^[[2;79H^[(B^[[0;7m nnn.txt                                                                        ^[[3;79H^[(B^[[0;1m^[[91m ^[(B^[[0mtags^[[3;20H^[(B^[[m
']]
[4, ['^[[1;53H^[(B^[[0;1mftplugin^[[2;79H^[(B^[[0m...^[(B^[[m^[[K^[[3;20H^[(B^[[0;1m^[[91m ^[[94mdoc^[[52X^[[3;76H2 ^[[39m^[(B^[[m^[[K^[[4;20H^[(B^[[0;1;7m^[[94
m ftplugin                                               1 ^[[38;12H^[(B^[[0m3^[[38;28H1^[[36G5-25 07:53^[[151G3^[[3;20H^[(B^[[m', '']]
[4, ['^[[2;79H^[(B^[[0;7m nnn.vim                                                                        ^[[4;20H^[(B^[[m']]
[4, ['^[[1;53H^[(B^[[0;1mpathtofolder^[[2;79H^[(B^[[0m...^[(B^[[m^[[K^[[4;20H^[(B^[[0;1m^[[91m ^[[94mftplugin^[[47X^[[4;76H1 ^[[5;20H^[(B^[[0;1;7m^[[94m pathtof
older                                           2 ^[[38;12H^[(B^[[0m4^[[38;28H2 2019-02-27 17:49^[[151G4^[[4;20H^[(B^[[m', '']]
[4, ['^[[2;79H^[(B^[[0;7m fileone.txt                                                                    ^[[3;79H^[(B^[[0;1m^[[91m ^[(B^[[0mfiletwo.txt^[[5;20H^
[(B^[[m']]

So it looks like this is just how curses programs deal with stdout?

And finally I tried running nnn again but this time with the option 'stdout_buffered': v:true (see: :h channel-buffered in neovim):

  call termopen('nnn -p -',  {'on_stdout': function('s:callback'), 'stdout_buffered': v:true })

Where I get a single list as output:

[4, ['^[[?1049h^[[1;38r^[(B^[[m^[[4l^[[?7h^[[?1h^[=^[[?1000h^[[?25l^[[39;49m^[[39;49m^[(B^[[m^[[H^[[2J[^[(B^[[0;1;7m^[[34m1^[[39m^[(B^[[m 2 3 4] ^[(B^[[0;4m^[[3
4m~/vimming/nnn.vim^[[3;2H^[(B^[[0;1;7m^[[38;5;39mautoload^[[39m^[(B^[[m/^M^[[4d ^[(B^[[0;1m^[[38;5;39mdoc^[[39m^[(B^[[m/^M^[[5d ^[(B^[[0;1m^[[38;5;39mftplugin^
[[39m^[(B^[[m/^M^[[6d ^[(B^[[0;1m^[[38;5;39mpathtofolder^[[39m^[(B^[[m/^M^[[7d ^[(B^[[0;1m^[[38;5;39mplugin^[[39m^[(B^[[m/^M^[[8d LICENSE^M^[[9d README.md^M^[[1
0d minimalvimrc^M^[[11d test.txt^M^[[38d^[[34m1/9 2021-05-18 16:41 drwxr-xr-x 96B^[[39m^[(B^[[m^M^[[3d ^[(B^[[0;1m^[[38;5;39mautoload^[[4;2H^[(B^[[0;1;7m^[[38;5
;39mdoc^M^[[38d^[(B^[[0m^[[34m2^[[8G0-09-27 09:29^[[38;33H128B^[[39m^[(B^[[m^M^[[4d ^[(B^[[0;1m^[[38;5;39mdoc^[[5;2H^[(B^[[0;1;7m^[[38;5;39mftplugin^M^[[38d^[(B
^[[0m^[[34m3^[[38;11H5-25 07:53^[[38;33H96B^[[39m^[(B^[[m^[[K^M^[[5d ^[(B^[[0;1m^[[38;5;39mftplugin^[[6;2H^[(B^[[0;1;7m^[[38;5;39mpathtofolder^M^[[38d^[(B^[[0m^
[[34m4/9 2019-02-27 17:49^[[38;33H128B^[[39m^[(B^[[m^M^[[6d ^[(B^[[0;1m^[[38;5;39mpathtofolder^[[7;2H^[(B^[[0;1;7m^[[38;5;39mplugin^M^[[38d^[(B^[[0m^[[34m5/9 20
20-09-27 09:17^[[38;33H96B^[[39m^[(B^[[m^[[K^M^[[7d ^[(B^[[0;1m^[[38;5;39mplugin^[[8;2H^[[39m^[(B^[[0;7mLICENSE^M^[[38d^[(B^[[0m^[[34m6^[[8G1-02-28 09:39 -rw-r-
-r-- 1.3K^[[39m^[(B^[[m^M^[[8d+^[[38;4H^[[34m ^[(B^[[0;7m^[[34m 1 ^[(B^[[0m^[[34m 2021-02-28 09:39 -rw-r--r-- 1.3K^[[39m^[(B^[[m^M^[[8d+LICENSE^M^[[9d ^[(B^[[0;
7mREADME.md^M^[[38d^[(B^[[0m^[[34m7^[[38;37H3.4K .md^[[39m^[(B^[[m^M^[[9d+^[[38;6H^[(B^[[0;7m^[[34m2^[[38;45H^[[39m^[(B^[[m^M^[[9d+README.md^M^[[10d ^[(B^[[0;7m
minimalvimrc^M^[[38d^[(B^[[0m^[[34m8^[[38;15H3-22 08:05^[[38;37H291B^[[39m^[(B^[[m^[[K^M^[[10d+^[[38;6H^[(B^[[0;7m^[[34m3^[[38;41H^[[39m^[(B^[[m^M^[[10d+minimal
vimrc^M^[[11d ^[(B^[[0;7mtest.txt^M^[[38d^[(B^[[0m^[[34m9^[[38;15H5-18 17:49^[[38;38H4B .txt^[[39m^[(B^[[m^M^[[11d+^[[38;6H^[(B^[[0;7m^[[34m4^[[38;45H^[[39m^[(B
^[[m^M^[[11d ^[[38;6H^[(B^[[0;7m^[[34m3^[[38;45H^[[39m^[(B^[[m^M^[[10d+^[(B^[[0;7mminimalvimrc^[[11;2H^[(B^[[mtest.txt^M^[[38d^[[34m8^[[38;15H3-22 08:05^[[38;38
H91B^[[39m^[(B^[[m^[[K^[[?1000l^[[38;1H^[[?12l^[[?25h^[[?1049l^M^[[?1l^[>/Users/mcchris/vimming/nnn.vim/LICENSE^M', '/Users/mcchris/vimming/nnn.vim/README.md^M'
, '/Users/mcchris/vimming/nnn.vim/minimalvimrc^M', '/Users/mcchris/vimming/nnn.vim/minimalvimrc^M', '']]

This looks like something that we can parse where the items in the list are the actual selected files outputted by nnn except for the first item. The first item is a string containing escape codes and the first selected item at the end of it.

....[[?1000l^[[38;1H^[[?12l^[[?25h^[[?1049l^M^[[?1l^[>/Users/mcchris/vimming/nnn.vim/LICENSE^M', '/Users/mcchris/vimming/nnn.vim/README.md^M'
, '/Users/mcchris/vimming/nnn.vim/minimalvimrc^M', '/Users/mcchris/vimming/nnn.vim/minimalvimrc^M', '']]

This could be something that can be work on for now but I hope there is something from the nnn or neovim side that could make it easier.

Note that I have not tried nnn with the jarun/nnn@2bd72d1 patch yet and only tried neovim.

I hope this will be of help.

@mizlan
Copy link
Contributor

mizlan commented May 18, 2021

Thank you so much! Not sure if we should proceed with the stdout_buffered idea since I don't think Vim8 has an equivalent.

Have you considered the possibility of having -p output to a FIFO (named pipe)? I do not know too much about how this works but I suspect it may be easier.

@mcchrish
Copy link
Owner

I'm not that familiar with named pipes and I look at some usage from other plugins and it looks promising.
https://github.com/vifm/vifm.vim/blob/dbe8050b137341e70ea9cf95194803b674144530/plugin/vifm.vim#L205-L237
We could create a named pipe where nnn picker will pipe the selected files to then vim/nvim runs a job that waits and reads (via stdout callback) from that named pipes.

Repository owner locked and limited conversation to collaborators May 30, 2021

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants