0

I have NERDTree and MiniBufExplorer open at the launch of vim, so I have three windows. Whenever I use the aforementioned plugins the files/buffers are presented in the correct window, which is the initial one. However whenever I use a command such as :e ~/.vimrc the command works on the window which contains the cursor. This means I have to always remember to move the cursor over to the window used for editing. I was wondering if there was a way to have commands work on that window regardless of where the cursor is, or if file buffers would automatically present themselves in that window?

I was looking at a way to have the cursor move over to the right window when : (or some other key I could use) is pressed, but I couldn't figure out a way as there is no way to identify windows (or is there?).

Matthew Mitchell
  • 5,293
  • 14
  • 70
  • 122
  • 2
    I suggest you take a look at Vimcast's [Oil and vinegar - split windows and the project drawer](http://vimcasts.org/blog/2013/01/oil-and-vinegar-split-windows-and-project-drawer/) post – Peter Rincker Apr 16 '14 at 17:48
  • Thanks for that suggestion, though I like it better when I have the files on the left at all times. And I like to be able to see the buffers at the top at all times too. Maybe that's from being too used to other editors which use such an interface. – Matthew Mitchell Apr 16 '14 at 19:47
  • You'll find out soon enough that not everything you are used to from other editors is worth importing to Vim. "Always-on" lists being the most obvious. – romainl Apr 16 '14 at 22:21

2 Answers2

7

Files, Buffers, and Splits Oh My!

You are asking Vim to change how every single file and buffer command to change to accommodate your plugin choice and workflow. You are going against the vim way here and it will hinder your use of Vim's splits.

First things first is to realize that Vim has no concept of Project drawers, only splits/windows. This means that NerdTree and other plugins go to great lengths to emulate Project Drawer behavior and ultimately fail.

Lets look at problems with using NerdTree and MiniBufExplorer as always open windows:

NerdTree:

  • Wasted space. How often do you look at your file structure? 10% of the time? Less?
  • Splits - open up a few split now switch to the bottom right most split via <c-w>b. Open up a file via NerdTree in this window. Did you use <c-w>t to go to the top left most window? Feels like quite a nuance to use so many window commands just to open a file
  • NerdTree doesn't play well when rearranging splits. Create some splits then do <c-w>J or <c-w>H. See how it messed up your layout

MiniBufExplorer

  • Scale - MiniBufExplorer just doesn't scale with the number of buffers. I have opened up over a hundred buffers without issue. I can not imagine the waste of space this would cause with MiniBufExplorer
  • There is little to be gained by seeing all your open buffers all the time. You only need to see them when you are switching to a different buffer
  • Switching buffers - You can switch buffers just as easily by mapping the :bnext and :bprev commands
  • More on switching buffers - Moving to the MiniBufExplorer window is tedious and annoy if that is how you want to switch buffers
  • Rearranging windows - Same as NerdTree
  • MiniBufExplorer is akin to using Vim's tabs for each file in vim see: Use buffer effectively

The Vim Way

As laid out in the Vimcast post, Oil and vinegar - split windows and the project drawer, Vim prefers to just open a file explorer when you need it then switch away from it when it isn't needed. You can user NerdTree in this fashion too, just forget the alway on file explorer bit. There are other ways of opening files in vim:

  • Use file completion, via <tab>, with commands like :e and :sp
  • Use <c-d> instead of <tab> to get a list of completions
  • :e and :sp commands take globs. e.g. :e *.c and :e foo/**/bar.c
  • :find and setup 'path' and 'suffix' options
  • Ctags or cscope to jump to tags
  • gf will go to a file under the cursor
  • Look into fuzzy finders like CtrlP or Command-T
  • Create project specific navigation via Projectile (Rails is a good example of this)

There are plenty of ways to switch buffers in Vim:

  • :b and :sb take buffer numbers but also names that will complete and glob
  • Use :ls to see a list of your buffers then use :b to switch directly
  • <c-6> will go the the previous buffer
  • Map :bnext and :bprev example [b and ]b are Unimpaired.vim mappings
  • set hidden make switching buffers easier. Don't worry vim will let you know if you have unwritten buffer before exiting
  • Once again look into fuzzy finder plugsin like CtrlP and Command-T to switch buffers

Vim is split happy. Make sure you use splits as effectively as you can. There are many split commmands, see :h opening-window. Better yet read the whole :h window help file, there are many treasure in there.

Community
  • 1
  • 1
Peter Rincker
  • 43,539
  • 9
  • 74
  • 101
  • Hmmm, thanks for the in-depth answer or more of a rebuttal against the premise of my question. I might use NERDTree as a "split explorer". I'm already using CtrlP to search for files, I could use it for buffers too, though one thing I do like about MiniBufExplorer is that it gives you a visual indication of which files have unwritten modifications, and which ones you are working on at a glance. Maybe it's best I try to change my way of thinking though. – Matthew Mitchell Apr 16 '14 at 22:47
  • `:ls` will show you which files are have changes. It is a right of passage for every vimmer to discover Vim's workflows and which work for them – Peter Rincker Apr 16 '14 at 22:59
  • I don't really like using `:ls`. I might try BufExplorer as an alternative to MiniBufExplorer. Also one problem with using netrw or NERDTree in a window is that there appears to be no easy built-in way to switch back to the previous buffer. It would be good to setup a key mapping to open and close the file browser in the window as a toggle. – Matthew Mitchell Apr 17 '14 at 15:15
  • `` will switch back to the previous window. This assumes you are switching to the NerdTree window directly. However as stated in the article you should be opening your file explorer you current window. You may find this mapping inspired by vim-vinegar helpful: `nnoremap - :e %:p:h` – Peter Rincker Apr 17 '14 at 15:39
  • What does `:e %:p:h` do? works to go back to the last file, though it wont work if you for instance go to the file browser and then to the buffer browser and then wish to return to the file you were working on. I doubt that will be an issue very often so is probably the best solution. – Matthew Mitchell Apr 17 '14 at 16:29
  • `:e %:p:h` will open up your file explorer to the current file's directory. See `:h :_%` – Peter Rincker Apr 17 '14 at 16:59
  • Ah right, I'll probably only want to open NERDTree for the pwd, but thanks. C-6 isn't always working nicely, so I'll have to find another solution for that... :bp works nicely from the BufExplorer plugin. So I created a toggle function which switches between NERDTree and the buffer I was on. – Matthew Mitchell Apr 17 '14 at 17:42
0

The core of a solution can be found in the NERDTree source via s:Opener._firstUsableWindow, which I then edited some to get the id and include modified buffers:

" Returns the first window ID containing a file buffer
"
" Iterates through window numbers until the last (winnr('$')),
" Skipping special buffer types & preview windows
function! FirstFileWindowID()
    let i = 1
    while i <= winnr('$')
        let bnum = winbufnr(i)
        if bnum !=# -1 && getbufvar(bnum, '&buftype') ==# ''
                    \ && !getwinvar(i, '&previewwindow')
            " TODO I don't know what excluding &hidden does in the original,
            " but may be desirable for correctness
            return win_getid(i)
        endif
        let i += 1
    endwhile
    return -1
endfunction

This can then be used with win_execute to target recent file buffers, gaining tab-like behavior with buffers:

"tab movement (ctrl-n for next tab, ctrl-p for previous)
map <c-n> :call win_execute(FirstFileWindowID(), 'bnext')<CR>
map <c-p> :call win_execute(FirstFileWindowID(), 'bprev')<CR>

I use tmux for all my pane management, so while I'm sure leveraging the full range of vim's tab / window / buffer paradigm is best for many, I personally don't use it to is fullest extent.

micimize
  • 904
  • 9
  • 16