Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vim window resizing repetitively

I have key bindings in tmux which I really enjoy to manage split panes:

bind -r H resize-pane -L 5
bind -r J resize-pane -D 5
bind -r K resize-pane -U 5
bind -r L resize-pane -R 5

This allows me to hit L wit multiple Ls in a row. It also allows me to say the border (left, right, etc) I want to increase.

I'd like to have the same thing in vim however, vim does not seem to have the context of border:

"attempt 1
nnoremap <leader>L :vertical resize +5<cr><leader>
"attempt 2
nnoremap <leader>L :vertical resize +5<cr>

However, this only works if on the left most pane as when on the right pane, I'd like it to be decreasing the size by 5. Also, this does not allow me to do it repetitively. (I'd like to hit key once, then as many times as I need the "L".

I was wondering if anyone had found a way to do this.

Note: I put the tmux config so someone could play with it to see exactly what I meant.

like image 550
Max Avatar asked Dec 03 '14 06:12

Max


1 Answers

I've made myself a vim script to make the resizing similar to Tmux' behavior. It might be what you are looking for.

" Tmux-like window resizing
function! IsEdgeWindowSelected(direction)
    let l:curwindow = winnr()
    exec "wincmd ".a:direction
    let l:result = l:curwindow == winnr()

    if (!l:result)
        " Go back to the previous window
        exec l:curwindow."wincmd w"
    endif

    return l:result
endfunction

function! GetAction(direction)
    let l:keys = ['h', 'j', 'k', 'l']
    let l:actions = ['vertical resize -', 'resize +', 'resize -', 'vertical resize +']
    return get(l:actions, index(l:keys, a:direction))
endfunction

function! GetOpposite(direction)
    let l:keys = ['h', 'j', 'k', 'l']
    let l:opposites = ['l', 'k', 'j', 'h']
    return get(l:opposites, index(l:keys, a:direction))
endfunction

function! TmuxResize(direction, amount)
    " v >
    if (a:direction == 'j' || a:direction == 'l')
        if IsEdgeWindowSelected(a:direction)
            let l:opposite = GetOpposite(a:direction)
            let l:curwindow = winnr()
            exec 'wincmd '.l:opposite
            let l:action = GetAction(a:direction)
            exec l:action.a:amount
            exec l:curwindow.'wincmd w'
            return
        endif
    " < ^
    elseif (a:direction == 'h' || a:direction == 'k')
        let l:opposite = GetOpposite(a:direction)
        if IsEdgeWindowSelected(l:opposite)
            let l:curwindow = winnr()
            exec 'wincmd '.a:direction
            let l:action = GetAction(a:direction)
            exec l:action.a:amount
            exec l:curwindow.'wincmd w'
            return
        endif
    endif

    let l:action = GetAction(a:direction)
    exec l:action.a:amount
endfunction

" Map to buttons
nnoremap <M-h> :call TmuxResize('h', 1)<CR>
nnoremap <M-j> :call TmuxResize('j', 1)<CR>
nnoremap <M-k> :call TmuxResize('k', 1)<CR>
nnoremap <M-l> :call TmuxResize('l', 1)<CR>

You can use the TmuxResize function to map other keys to it. The first argument is the direction ('h', 'j', 'k' or 'l'), the second argument is how much should the split border move.

like image 125
Limeth Avatar answered Nov 16 '22 12:11

Limeth