Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

If I open vim with: $ vim -o a.ext b.ext

I get a window that looks like this

+----------------------+
|           a          |
|                      |
| a.ext ---------------+
|           b          |
|                      |
+ b.ext ---------------+

Say I want to open another file, c.ext. So I do something like :e c.ext on the top panel.

+----------------------+
|           c          |
|                      |
| c.ext ---------------+
|           b          |
|                      |
+ b.ext ---------------+

But now the a.ext file is inaccessible, and I can't get back to it using :n. What is the proper way to open c.ext so I can get back to a.ext using :n?

share|improve this question
    
You question says vim but the command that you are using indicates you are using vi. Which is it? –  Chris Knadler Jul 21 '11 at 22:44
    
vim (...15 characters) –  Matt Jul 21 '11 at 22:52

3 Answers 3

up vote 5 down vote accepted

I think your are already opening your files fine but they are in separate buffers and you need to use the :bn (or full :bnext and :bprev) commands to navigate to the next and previous buffers in a given pane.

share|improve this answer
    
Is there a way to make it loop through only files that were in that pane (not every file currently open)? –  Matt Jul 21 '11 at 23:34
    
Without setting up some kind of matching system of your own using buffer labels, I don't think so. This doesn't work in your original example either. All the open files in vim are in a set of buffers that doesn't have any particular relation to the panes you have setup. Using next/prev commands cycles through the buffers. You could manually tweak this by setting up macros for specific buffers. –  Caleb Jul 22 '11 at 9:41

I'd try ':e #' which returns to the file previously opened.

share|improve this answer

In a comment you asked the following:

Is there a way to make it loop through only files that were in that pane (not every file currently open)?

I do not think that Vim keeps track of all the buffers that a window (“pane”) has previously accessed. However, Vim is scriptable

Here is an implementation that provides a version of this functionality by using autocommands to record (in a window-local variable) which buffers have been activate in a window.

The (abbreviated) commands are:

  • :Hb List the historical buffers for this window.
  • :Hbn[!] [N] Switch to the Nth next historical buffer.
    (like :bn, but limited to the “historical” buffers of the current window)
  • :Hbp[!] [N] Switch to the Nth previous historical buffer.
    (like :bp, but limited to the “historical” buffers of the current window)
  • :Hbf [N] (“forget”) Remove the current buffer (or buffer number N) from the current window’s list of historical buffers.
    If you do not switch to another buffer for leaving and re-entering this window the current buffer will be re-added to the list of historical buffers.

The following code could be put into your .vimrc or in a separate file (e.g. plugin/buffer-history/buffer-history.vim somewhere under one of your runtimepath directories):

augroup UL17179_BufferHistory
    autocmd!
    autocmd BufEnter * call s:RecordBufEnter(0)
    " Grab WinEnter, since BufEnter is not triggered when doing
    " a bare ':split'. This also means that 'forgetting' a buffer is
    " only effective if you switch to another buffer before
    " switching away from the window.
    autocmd WinEnter * call s:RecordBufEnter(1)
augroup END

function! s:EnsureBufferHistory()
    if ! exists('w:BufferHistory')
        let w:BufferHistory = []
    endif
    return w:BufferHistory
endfunction

function! s:RecordBufEnter(w)
    let l = s:EnsureBufferHistory()
    let b = winbufnr(0)
    let i = index(l, b)
    if i >= 0
        unlet l[i]
    endif
    let l += [b]
    redraw
endfunction

function! s:ForgetBuffer(...)
    let l = s:EnsureBufferHistory()
    for b in a:000
        let b = b ? b+0 : winbufnr(0)
        let i = index(l, b)
        if i >= 0
            call remove(l, i)
        else
            try
                echohl WarningMsg
                echomsg 'Buffer' b 'not in history list.'
            finally
                echohl None
            endtry
        endif
    endfor
endfunction

function! s:ShowBuffers()
    let l = s:EnsureBufferHistory()
    for b in l
        echomsg b bufname(b)
    endfor
endfunction

function! s:HistoricalBufferNr(...)
    let  direction = a:0 >= 1 && !a:1 ? -1 : 1
    let move_count = a:0 >= 2 ? max([1, a:2]) : 1

    let current_bn = winbufnr(0)
    let historical_buffers = copy(filter(s:EnsureBufferHistory(),
                \ 'bufexists(v:val)'))
    let i = index(historical_buffers, current_bn)
    if i < 0
        let other_historical_buffers = historical_buffers
    elseif i == 0
        let other_historical_buffers = historical_buffers[1:]
    else
        let other_historical_buffers = historical_buffers[i+1:] +
                    \ historical_buffers[:i-1]
    endif

    if len(other_historical_buffers) <= 0
        try
            echohl ErrorMsg
            echomsg 'This window has no historical buffers!'
        finally
            echohl None
        endtry
        return 0
    endif
    if direction > 0
        let i = (move_count - 1) % len(other_historical_buffers)
    else
        let l = len(other_historical_buffers)
        let i = ((l - 1) * move_count ) % l
    endif
    return other_historical_buffers[i]
endfunction

" If the 1) user does not give a bang and
"        2) we run 'buffer N' (no bang) from inside the function and 
"        3) switching away from the buffer would require a bang,
" then the user will see an ugly 'Error detected while processing
" function' prefix before the usual E37 error message. Hoisting the
" 'buffer<bang> N' into the user-defined command means the user will
" just see a normal E37 message.
command! -nargs=0 -count=1 -bang -bar
            \ HistoricalBufferNext
            \ let s:new_bn = s:HistoricalBufferNr(1, <count>)
            \ | if s:new_bn | exe 'buffer<bang>' s:new_bn | endif
command! -nargs=0 -count=1 -bang -bar
            \ Hbn
            \ HistoricalBufferNext<bang> <count>
command! -nargs=0 -count=1 -bang -bar
            \ HistoricalBufferPrev
            \ let s:new_bn = s:HistoricalBufferNr(0, <count>)
            \ | if s:new_bn | exe 'buffer<bang>' s:new_bn | endif
command! -nargs=0 -count=1 -bang -bar
            \ Hbp
            \ HistoricalBufferPrev<bang> <count>
command! -nargs=* -count=0 -bar
            \ HistoricalBufferForget
            \ call s:ForgetBuffer(<count>, <f-args>)
command! -nargs=* -count=0 -bar
            \ Hbf
            \ HistoricalBufferForget <count> <args>
command! -nargs=0 -bar
            \ HistoricalBuffers
            \ call s:ShowBuffers()
command! -nargs=0 -bar
            \ Hb
            \ HistoricalBuffers
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.