ap / vim-buftabline

Forget Vim tabs – now you can have buffer tabs
http://www.vim.org/scripts/script.php?script_id=5057
MIT License
791 stars 72 forks source link

No buffer shown for netrw #25

Open gibfahn opened 7 years ago

gibfahn commented 7 years ago

Say I have the following directory listing:

.
├── a
├── b
├── c
└── dir
    ├── a2
    ├── b2
    └── c2

1 directory, 6 files

I open everything with vim *:

image

I get my files and the dir/ listing as expected. But if I change to the dir buffer, the dir/ option in the tabline isn't highlighted.

image

I assume this is because that buffer is listed as "no name". Is this something that's actually possible to fix? If there's no buffer name, I can imagine that with multiple directories open it might not be possible to work out which was highlighted.

ap commented 7 years ago

It uses the buffer number, not the buffer name. So I have no idea how this situation can happen.

What does :echo buftabline#user_buffers() say? And :echo winbufnr(0) when you’re in the netrw buffer?

gibfahn commented 7 years ago

:echo buftabline#user_buffers() shows [1, 2, 3, 4] :echo winbufnr(0) shows 5

ap commented 7 years ago

Ohhh, I think I remember now… this is one of these bizarro aspects of netrw. When you open a directory, netrw creates an unlisted unnamed alternative buffer for it and renders the directory into that buffer, and then (if I still have the details right) intercepts switches into the regular (and named) buffer and flips you over to the rendered version in the alternative buffer. This is not something that can be handled without specific support for netrw… and I think I didn’t find a way to detect it reliably at the time (my memory is really hazy at this point…).

I vaguely remember this being among the things that drove me to write readdir (“gee, this has to be doable in a less crazy way”).

Edit: jinx…

gibfahn commented 7 years ago

Okay, that would make sense, so netrw is in buffer 4 but is randomly also working in buffer 5 somehow?

If you're saying the easiest way to fix this is to use readdir, then fair enough, I'll try it out!

ap commented 7 years ago

Well buffer 4 has the directory name but there is nothing in it. And buffer 5 has no name and is not listed but has the directory contents in it. And when you switch to buffer 4, netrw forces you into buffer 5.

I must admit that after having written readdir and run into the same design issues, I can now appreciate why netrw chose this design. I addressed those issues by modifying the buffer name instead, but that creates a variety of other design problems that I then had to work around. I’m not wild about either design.

The fundamental problem is that in Vim, no two buffers can have the same name. So if you render a directory into the buffer directly named after the directory, you cannot have two directory browser buffers showing the same directory. E.g. if you are browsing your home directory in one buffer and ~/.vim/ in the other, you cannot go up one directory in the ~/.vim/ buffer because you already have ~/ open in another buffer.

In readdir I reacted to this by setting buftype to nofile to divorce the buffer name from the filesystem, and then adding a unique ID to it. That way multiple readdir buffers can never have the same name even when they’re showing the same directory. But then this has to be undone to open a file, and also, changing the name of a buffer interacts a little weirdly with later opening a file into that same buffer, so I had to find a workaround for that, etc etc.

In netrw they solved all this by doing this alternative unlisted buffer dance instead. In some ways this is less crazy – using multiple buffers isolates the state of each of them, so it’s simpler and more robust compared to readdir, which has to carefully track each bit of buffer state that it relies on. But the netrw bodge is also more visible to the user.

Both approaches suck in different ways. But under Vim’s constraint that buffer names must be unique, I can’t think of any better alternative.

gibfahn commented 7 years ago

Hmm, could you just switch buffers when the user tries to cd into a directory that is already open in another buffer? If I have Buffer 1 open at ~, and Buffer 2 open at ~/.vim, and I try to open .. in Buffer 2, you could just leave Buffer 2 as is and switch me into Buffer 1. Or would that not work?

Also, in readdir is there a way to open a file without closing the directory buffer? Put another way, is there a way to open multiple files from a single readdir buffer? I was thinking something like <S-Enter>.

ap commented 7 years ago

You can hit o on a file to open it in a new buffer, or t to open it into a new tab. Other operations are not yet supported but I intend to add them.

Switching buffers does work – it’s what readdir does when you try to open an already-open file. But I found it rather disorienting for directories, because your navigation actions suddenly affect a different directory browser than the one you started with. It would only make sense if you could never change directory within a browser but only open directories, as new buffers. That would make some amount of sense, even… but navigating around your filesystem would quickly accumulate lots of open directory buffers. Dunno if that would really be usable.