tpope / vim-vinegar

vinegar.vim: Combine with netrw to create a delicious salad dressing
https://www.vim.org/scripts/script.php?script_id=5671
2.23k stars 87 forks source link

'-' goes back to the netrw explorer but in a non unlisted buffer. #74

Open jshort opened 8 years ago

jshort commented 8 years ago

Using :Ex directly opens netrw with an unlisted buffer. This allows me to use :bp/:bn to hop around between buffers without issue (and wraps when I get to the end). If at anytime I hit '-', it goes to a netrw explorer buffer that is listed, which causes some very odd :bp/:bn behavior.

Is there some config to force vinegar/netrw to always open in an unlisted buffer?

Note this seems to happen in 2 circumstances:

In both of those cases there is at least 1 file explorer buffer that is not unlisted, which causes the - and :bn/:bp to misbehave.

I'm wondering if there is a work around to this?

jshort commented 8 years ago

More info:

So I wrote a wrapper functions (vimdir) that does arg checking (1 arg and said arg is a directory) and then calls:

vim -c ':Ex' -c ':bwipe 1' ${dir}

After vim opens, I see a netrw screen and :ls! displays:

:ls!
  2u%a-  "[No Name]"                    line 1

Compared to just vim .:

:ls!
  1  h   "~/gitworkspaces/vim-setup" line 1
  2u%a-  "[No Name]"                         line 1

With this wrapper, if I open a file in the directory that I passed to vim (in this case '.'), it will open in a listed buffer. However if I use -, it will bring me back to netrw in a listed buffer (undesirable). If I instead had traversed down to another directory in netrw, opened a file in said directory and use -, it goes back to netrw in an unlisted buffer (desirable).

So I thought I had worked around the issue, but in the case that the file I'm opening in netrw is in the directory that I called vim upon, then - brings me to a listed netrw buffer, which is not what I want.

EDIT: removing set hidden in my vimrc fixes this issue, but I'm not quite willing to give up that setting.

kiryph commented 7 years ago

I can reproduce this without vinegar. IMHO this is netrw related.

  1. with set hidden:
$ vim .
open .vimrc
:ls
  1  h   "~/"                           line 1
  3 %a   "~/.vimrc"                     line 1
$ vim
:Explore
open .vimrc
:ls
  2 %a   "~/.vimrc"                     line 1
  1. without set hidden
$ vim .
open .vimrc
:ls
  3 %a   "~/.vimrc"                     line 1
$ vim
:Explore
open .vimrc
:ls
  2 %a   "~/.vimrc"                     line 1

UPDATE You can fix vinegars '-' with

diff --git a/vinegar-edit.vim b/vinegar-Explore.vim
index f471141..529d620 100644
--- a/vinegar-edit.vim
+++ b/vinegar-Explore.vim
@@ -26,7 +26,7 @@ if !exists("g:netrw_banner")
 endif
 let s:netrw_up = ''

-nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('edit')<CR>
+nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('Explore')<CR>
 if empty(maparg('-', 'n'))
   nmap - <Plug>VinegarUp
 endif
@@ -47,6 +47,7 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let @# = expand('%')
     execute a:cmd '%:h/'
     call s:seek(expand('#:t'))
   endif

As far as I can see, the only use of edit is for folders: either . or %:h/

function! s:opendir(cmd) abort
  let df = ','.s:dotfiles
  if expand('%:t')[0] ==# '.' && g:netrw_list_hide[-strlen(df):-1] ==# df
    let g:netrw_list_hide = g:netrw_list_hide[0 : -strlen(df)-1]
  endif
  if &filetype ==# 'netrw'
    let currdir = fnamemodify(b:netrw_curdir, ':t')
    execute s:netrw_up
    call s:seek(currdir)
  elseif expand('%') =~# '^$\|^term:[\/][\/]' " Handle nvim term:// buffers
    execute a:cmd '.'
  else
    execute a:cmd '%:h/'
    call s:seek(expand('#:t'))
  endif
endfunction

However, if there is a reason to use :edit instead of :Explore, please report this here.

manasthakur commented 7 years ago

I checked with alternating between edit and Explore, and found a difference that annoys me.

If I keep the default @tpope has right now, the selected entry on pressing - is the name of the file currently loaded into the buffer from which netrw was popped out. Which is as expected.

When I use Explore in the mapping, the selected entry is always the first buffer that was opened by me (may be long time ago), and it is the one that gets loaded if I close netrw without selecting a file, thus landing me onto a file that I wasn't editing.

Thus the problem of a stray netrw buffer stays for me even now. Any suggestions?

kiryph commented 7 years ago

@manasthakur: Does following help you?

diff --git a/plugin/vinegar.vim b/plugin/vinegar.vim
index 85ed2a4..d61cc10 100644
--- a/plugin/vinegar.vim
+++ b/plugin/vinegar.vim
@@ -50,7 +50,7 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
-    execute a:cmd '%:h/'
+    execute a:cmd
     call s:seek(expand('#:t'))
   endif
 endfunction

UPDATE Sorry, I haven't looked into your issue properly. Afaik my proposal above does not help. However, the command :Rexplore might be of help (see :h netrw-:Rexplore). But it is not sufficient to replace simply :Explore by it.

manasthakur commented 7 years ago

Yes, I checked. The problem persists.

kiryph commented 7 years ago

Another try:

diff --git a/plugin/vinegar.vim b/plugin/vinegar.vim
index 85ed2a4..c3f8a10 100644
--- a/plugin/vinegar.vim
+++ b/plugin/vinegar.vim
@@ -50,7 +50,11 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
-    execute a:cmd '%:h/'
+    if exists(":Rexplore")
+      execute "Rexplore"
+    else
+      execute a:cmd '%:h/'
+    endif
     call s:seek(expand('#:t'))
   endif
 endfunction
manasthakur commented 7 years ago

Hi @kiryph . No, the behaviour still remains the same. Rexplore will be available the second time onwards, right? However, this problem happens even when netrw is opened the first time.

kiryph commented 7 years ago

Hi @manasthakur,

did I get you right:

  1. open vim with a file $ vim ~/.vimrc
  2. open netrw window with :Explore or -. Now your issue occurs: the file ~/.vimrc is not selected which you expected.

I can confirm this.

:Rexplore can't be used for the first time you use netrw. The docs of netrw do not say how to get what you want. You should report this to the plugin netrw of Charles Campbell. I am quite certain that this has nothing to do with vinegar.

manasthakur commented 7 years ago

Hi @kiryph ,

The issue I am mentioning is the same as the title. If I use edit, I have a non-unlisted buffer in the bufferlist, which disrupts :bnext and :bprevious. If I use Explore (as suggested above), I don't get the equivalent behaviour as edit (wrong file highlighted).

I understand that these anomalies have nothing much to do with vinegar, though.

kiryph commented 7 years ago

tpope added a seek function s:seek(file) to get the cursor to the right line. However, using Explore instead of edit

-nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('edit')<CR>
+nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('Explore')<CR>

empties the alternate file stored in # which the seek invocation uses:

call s:seek(expand('#:t'))

Storing the filename in a temporary variable circumvents this problem and should resolve your issue when using Explore instead of edit

@@ -50,8 +50,9 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let alt_file = expand('%:t')
     execute a:cmd '%:h/'
-    call s:seek(expand('#:t'))
+    call s:seek(alt_file)
   endif
 endfunction

However, I do not like that Ctrl-^ does not work after using :Explore. So I am still not happy with it.

manasthakur commented 7 years ago

Hi @kiryph,

Thanks for this. It works but still has an issue: if we close netrw using :bdelete, is restores the alternate buffer, instead of the previously active one.

kiryph commented 7 years ago

Hi @manasthakur,

should following steps reproduce your issue with :bdelete in netrw returning to the wrong file:

  1. $ vim ~/.vim/vimrc
  2. :e ~/.vim/gvimrc (open second file so vimrc becomes the alternate buffer)
  3. :registers (check current alternate buffer)
    --- Registers ---
    ":   e ~/.vim/gvimrc
    "%   ~/.vim/gvimrc
    "#   vimrc
  4. Open netrw with - (the cursor should be in the line of gvimrc)
  5. :registers
    --- Registers ---
    ":   registers
    "#   gvimrc
  6. Close netrw with :bdelete and it should return to gvimrc but you end up in vimrc.

I cannot reproduce it.

Did you try

@@ -50,8 +50,9 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let alt_file = expand('%:t')
     execute a:cmd '%:h/'
-    call s:seek(expand('#:t'))
+    call s:seek(alt_file)
   endif
 endfunction

or

@@ -47,6 +47,7 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let @# = expand('%')
     execute a:cmd '%:h/'
     call s:seek(expand('#:t'))
   endif
manasthakur commented 7 years ago

Hi @kiryph,

Thanks for the detailed steps. I have used the first code-block, along with Explore instead of edit in the mapping for <Plug>VinegarUp (code here).

After step 4, when I ran :registers, I am getting # vimrc, instead of # gvimrc. I disabled all my plugins except vinegar to see if any of them is changing the alternate buffer, and still ran into this issue. I don't what is happening there!

p.s. However, I won't stretch this further if you are not able to reproduce this. Thanks again.

kiryph commented 7 years ago

Sorry I had an issue identifying which vinegar.vim script file was sourced by vim. I recently switched to dein.vim which caches plugins in an additional folder where you have to watchout which file is actually sourced.

Now, I can reproduce your issue with

@@ -50,8 +50,9 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let alt_file = expand('%:t')
     execute a:cmd '%:h/'
-    call s:seek(expand('#:t'))
+    call s:seek(alt_file)
   endif
 endfunction

However, it should be resolved when you use instead

@@ -47,6 +47,7 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let @# = expand('%')
     execute a:cmd '%:h/'
     call s:seek(expand('#:t'))
   endif

UPDATE Well, again it is more complicated. Despite that the alternate file is the right one, :h :bdelete describes that the jumplist determines which file is opened again. So the issue remains and a further change has to be made. However, I am sorry I won't proceed here due to time limitations. If you can figure it out, please post it here.

UPDATE 2 Does following help?

@@ -47,6 +47,7 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let @# = expand('%')
+    normal! m`
     execute a:cmd '%:h/'
     call s:seek(expand('#:t'))
   endif
kiryph commented 7 years ago

I add a complete patch with another addition taking the variable g:netrw_altfile into account. However, I am not sure about this.

diff --git a/vinegar.vim b/vinegar-Explore.vim
index f471141..e16898c 100644
--- a/vinegar.vim
+++ b/vinegar-Explore.vim
@@ -26,7 +26,7 @@ if !exists("g:netrw_banner")
 endif
 let s:netrw_up = ''

-nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('edit')<CR>
+nnoremap <silent> <Plug>VinegarUp :call <SID>opendir('Explore')<CR>
 if empty(maparg('-', 'n'))
   nmap - <Plug>VinegarUp
 endif
@@ -47,8 +47,13 @@ function! s:opendir(cmd) abort
   elseif expand('%') =~# '^$\|^term:[\/][\/]'
     execute a:cmd '.'
   else
+    let alt_file = expand('%:t')
+    if !exists("g:netrw_altfile") || g:netrw_altfile == 0
+        let @# = expand('%')
+    endif
+    normal! m`
     execute a:cmd '%:h/'
-    call s:seek(expand('#:t'))
+    call s:seek(alt_file)
   endif
 endfunction

Hopefully, this

  1. reduces stray netrw buffers (more precise :bnext/:bprevious),
  2. always puts the cursor in the correct line of a netrw buffer (call s:seek(alt_file)),
  3. returns to the correct buffer on :bdelete called in a netrw buffer.

The behavior for the alternate buffer has to be clarified and should possibly be improved.

Note, netrw intends to keep remote netrw buffers for speed reasons.

manasthakur commented 7 years ago

It seems there is no variable g:netrw_altfile.

If I change it to alt_file, things work perfectly 👍

The patched fork is available here.

snoblenet commented 3 years ago

I just came across the same issue.

I had to change this...

nmap ;s :Vex<CR>

...to this...

nmap ;s :vert exec("edit ".expand("%:p:h"))<CR>

...to avoid the bug where pressing - - took me to a seemingly random directory instead of the one two levels up.