1

I was playing around with the MiniBufExplorer plugin, and I thought it would be nice if the MBE window could stick to the bottom of my ViM screen, even if I specifically open a new window with e.g. :bot split xyz. If I can get that working, then as a bonus I can set laststatus=0 when the MBE window is active, because having a statusline on it doesn't really accomplish anything. I already have an autocmd that customizes my statusline that I could piggyback off of, so at first I thought I could make a quick tweak to that function like so:

function! s:RefreshStatus()
    let l:mbe = 2
    for nr in range(1, winnr('$'))
        if '-MiniBufExplorer-' == expand('%')
            let l:mbe = 0
            wincmd J
        else
            call setwinvar(nr, '&statusline', '%!Status(' . nr . ')')
        endif
    endfor
    call setwinvar (0, '&laststatus', l:mbe)
endfunction

Oops, of course that didn't work. I'm not actually jumping through the buffers to set the status line, so expand('%') and wincmd J don't actually behave correctly. So my biggest question is, how do I execute wincmd J in window #nr? EDIT: I found the bufname() function, which solves the problem of correctly identifying the MBE window, but I'd still like to be able to move the window to the bottom when something has snuck in under it.

EDIT 2: MiniBufExplorer seems to have some logic for window positioning built in that interferes with what I am attempting to accomplish, even when using noautocmd. Here's the function I ended up with, following Ingo's answer:

function! FixMBE()  " Now a separate function
    let l:mbenr = 0
    for nr in range(1, winnr('$'))
        if '-MiniBufExplorer-' == bufname(nr)
            call setwinvar(nr, '&statusline', '')
            let l:mbenr = nr
        endif
    endfor
    if l:mbenr
        set laststatus=0
        let l:active = winnr()
        try
            exe 'noautocmd ' . l:mbenr . 'wincmd w'
            wincmd J
            if l:active > l:mbenr
                let l:active = l:active -1   " window numbers will change after we move MBE
            endif
        finally
            exe 'noautocmd ' . l:active . 'wincmd w'
        endtry
    else
        set laststatus=2
    endif
endfunction

It mostly works with horizontal splits, but goes badly belly up when vertical splits are added to the mix. However, if I disable the MBE plugin and create a normal window with that name, this script behaves exactly as expected.

3

Vim has no means to execute command in a non-active window, and the internal implementation also mostly depends on being in the active one, so it would be hard to implement such. You actually have to briefly move to that window, and then back:

let currentWinNr = winnr()
execute targetWinNr . 'wincmd w'
try
    execute command " This could be your wincmd J
finally
silent execute currentWinNr . 'wincmd w'
endtry

Note that this still clobbers the previous window (i.e. <C-W>p); additional commands would be necessary to restore that, too. And autocmds might be triggered, which can be avoided via :noautocmd wincmd w.

  • Thanks. I suspected the answer was somewhere along those lines, although i couldn't quite work out the sequence of commands to get it right. I'm not too worried about the previous window, but the noautocmd warning was definitely helpful. – Drew Apr 15 '15 at 16:17
0

Rather than attempting to find and move the MiniBufExplorer window, you can ensure it's in the correct position by closing and reopening it. I do this by invoking the toggle command :TMiniBufExplorer twice in succession.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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