:vsplit (short form: :vs) split the Vim viewport vertically. :30vs splits the viewport, making the new window 30 characters wide. Once this 30 char window is created, how would one change it's size to 31 or 29?
With horizontal windows Ctrl-W + increases the number of lines by one. What is the equivalent command to increase the columns by one?
CTRL-W >
and
CTRL-W <
to make the window wider or narrower.
And Ctr-W =
will make them equal
In case you need HORIZONTAL SPLIT resize as well:
The command is the same for all splits, just the parameter changes:
- + instead of < >
Examples:
Decrease horizontal size by 10 columns
:10winc -
Increase horizontal size by 30 columns
:30winc +
or within normal mode:
Horizontal splits
10 CTRL+w -
30 CTRL+w +
Vertical splits
10 CTRL+w < (decrease)
30 CTRL+w > (increase)
Another tip from my side:
In order to set the window's width to let's say exactly 80 columns, use
80 CTRL+W |
In order to set it to maximum width, just omit the preceding number:
CTRL+W |
I have these mapped in my .gvimrc to let me hit command-[arrow] to move the height and width of my current window around:
" resize current buffer by +/- 5
nnoremap <D-left> :vertical resize -5<cr>
nnoremap <D-down> :resize +5<cr>
nnoremap <D-up> :resize -5<cr>
nnoremap <D-right> :vertical resize +5<cr>
For MacVim, you have to put them in your .gvimrc (and not your .vimrc) as they'll otherwise get overwritten by the system .gvimrc
Along the same lines, I use the following in my .vimrc to let me move through the splits, automatically expanding the one I'm moving to to its full size and shrinking all the rest to their minimum height or width:
" Switch between window splits using big J or K and expand the split to its
" full size.
"
" Move vertically in the window through the horizontal splits...
map <C-J> <C-w>j<C-w>_
map <C-K> <C-w>k<C-w>_
" Move horizontally in the window through the vertical splits...
map <C-H> <C-w>h<C-w>\|
map <C-L> <C-w>l<C-w>\|
This is what I am using as of now:
nnoremap <silent> <Leader>= :exe "resize " . (winheight(0) * 3/2)<CR>
nnoremap <silent> <Leader>- :exe "resize " . (winheight(0) * 2/3)<CR>
nnoremap <silent> <Leader>0 :exe "vertical resize " . (winwidth(0) * 3/2)<CR>
nnoremap <silent> <Leader>9 :exe "vertical resize " . (winwidth(0) * 2/3)<CR>
For changing width use "vertical resize" and for changing height use "resize".
I have done following mapping in my .vimrc
ALT→ will increase width of the selected split
ALT← will decrease width of the selected split
ALT↓ will increase height of the selected split
ALT↑ will decrease height of the selected split
My .vimrc code:
nmap <M-Right> :vertical resize +1<CR>
nmap <M-Left> :vertical resize -1<CR>
nmap <M-Down> :resize +1<CR>
nmap <M-Up> :resize -1<CR>
Vim Resize Splits more quickly
I am using numbers to resize by mapping the following in .vimrc
nmap 7 :res +2<CR> " increase pane by 2
nmap 8 :res -2<CR> " decrease pane by 2
nmap 9 :vertical res +2<CR> " vertical increase pane by 2
nmap 0 :vertical res -2<CR> " vertical decrease pane by 2
I am using the below commands for this:
set lines=50 " For increasing the height to 50 lines (vertical)
set columns=200 " For increasing the width to 200 columns (horizontal)
Related
I am trying to set the + and _ keys to increase or decrease the size of a window pane in vim. Here is what I have so far in my .vimrc:
nnoremap + :res +5
nnoremap _ :res -5
However it doesn't appear to work. What would be the proper way to map the resize pane in vim? Also, is there a way to press [enter] automatically after entering the command so that it executes automatically?
The :res commands are fine, but you need to append <CR> (for Carriage Return) to the mappings to actually execute them when you press + or _ . So, your mappings should look like this:
nnoremap + :res +5<CR>
nnoremap _ :res -5<CR>
It should be noted that there are built-in hotkeys in Vim to increase and decrease the window height and width, with the default number being 1:
Increase height (by 1): Ctrl-W +
Decrease height (by 1): Ctrl-W -
Increase width (by 1): Ctrl-W >
Decrease width (by 1): Ctrl-W <
To use the above hotkeys with values other than 1, simply prepend the hotkey with the value:
Increase height by 5: 5 Ctrl-W +
Alternative: use a "mode" where normal arrow keys can resize the current window.
either map to + or
:call ToggleResizeMode()
"
" + toggle remap arrow keys to resize windows
"
nnoremap + :call ToggleResizeMode()<CR>
let s:KeyResizeEnabled = 0
function! ToggleResizeMode()
if s:KeyResizeEnabled
call NormalArrowKeys()
let s:KeyResizeEnabled = 0
else
call ResizeArrowKeys()
let s:KeyResizeEnabled = 1
endif
endfunction
function! NormalArrowKeys()
" unmap arrow keys
echo 'normal arrow keys'
nunmap <Up>
nunmap <Down>
nunmap <Left>
nunmap <Right>
endfunction
function! ResizeArrowKeys()
" Remap arrow keys to resize window
echo 'Resize window with arrow keys'
nnoremap <Up> :resize +2<CR>
nnoremap <Down> :resize -2<CR>
nnoremap <Left> :vertical resize -2<CR>
nnoremap <Right> :vertical resize +2<CR>
endfunction
Or better: someone already implemented a window submode, there is probably a plugin for it somewhere.
https://ddrscott.github.io/blog/2016/making-a-window-submode/
Whenever I move the cursor left or right using h or l, the fold under the cursor opens automatically. By the way, moving top or down does not have this problem. Is there any way to prevent automatically opening fold when moving horizontally?
You can create the auto command:
autocmd! CursorMoved * if foldclosed('.') != -1 |
\ nnoremap h <nop>|
\ nnoremap l <nop>|
\ else |
\ silent! unmap h|
\ silent! unmap l|
\ endif
Here foldclosed('.') returns -1 if current line is unfolded. Instead of using this auto command just avoid pressing h or l over folds.
The default value of :help 'foldopen' has hor in it; this causes horizontal movements (like l, h) to open folds.
To disable this, simply add this to your ~/.vimrc:
set foldopen-=hor
I generally like the shiftround option in Vim, but there are a couple of
situations where it doesn't work very well. For instance, take this example:
f(x,
y)
Selecting the two lines and shifting with > and the two lines selected gives
me (and shiftwidth set to 4):
f(x,
y)
When I really wanted:
f(x,
y)
In other words, Vim advanced each line of the block to the next tabstop, when I
really wanted it to insert the same amount of inserted on each line--but I want
the least indented line to end up on the next tabstop.
Is there an easy way to get this behavior in Vim? My goal is to have this work
for < and > (with a visual selection) rather than other workarounds.
Ctrl+V, select vertical column before the text you need to shift (j in your case of just two lines), Shift+I, insert needed number of tabs or spaces, Esc.
You can actually use this method to insert arbitrary text, for example you can insert # or // to comment some code. More info in :help blockwise-operators.
I would solve this via a separate set of mappings that enclose the >> commands with a temporary clearing of 'shiftround'. Here's an implementation:
" g>> Shift [count] lines one 'shiftwidth' rightwards, without
" 'shiftround'.
"{Visual}[count]> Shift the highlighted lines [count] 'shiftwidth'
" rightwards (for {Visual} see |Visual-mode|), without
" 'shiftround'.
" g<<, {Visual}[count]<
function! s:Shift( command )
let s:save_shiftround = &shiftround
set noshiftround
return a:command
endfunction
function! s:RestoreShiftRound()
let &shiftround = s:save_shiftround
return ''
endfunction
nnoremap <expr> <SID>(RestoreShiftRound) <SID>RestoreShiftRound()
nnoremap <expr> <SID>(ShiftRight) <SID>Shift('>>')
xnoremap <expr> <SID>(ShiftRight) <SID>Shift('>')
nnoremap <expr> <SID>(ShiftLeft) <SID>Shift('<<')
xnoremap <expr> <SID>(ShiftLeft) <SID>Shift('<')
nnoremap <silent> <script> <Plug>(ShiftRightNoRound) <SID>(ShiftRight)<SID>(RestoreShiftRound)
xnoremap <silent> <script> <Plug>(ShiftRightNoRoundSelection) <SID>(ShiftRight)<SID>(RestoreShiftRound)
nnoremap <silent> <script> <Plug>(ShiftLeftNoRound) <SID>(ShiftLeft)<SID>(RestoreShiftRound)
xnoremap <silent> <script> <Plug>(ShiftLeftNoRoundSelection) <SID>(ShiftLeft)<SID>(RestoreShiftRound)
nmap g>> <Plug>(ShiftRightNoRound)
xmap g> <Plug>(ShiftRightNoRoundSelection)
nmap g<< <Plug>(ShiftLeftNoRound)
xmap g< <Plug>(ShiftLeftNoRoundSelection)
I didn't cover the >{motion} command, as that would be more complex.
I want to push one button in Vim and fold all the code so only code up to a specific (and variable) indent level is showing. Very useful when I want to only see method names for example and not their indented routines.
The “Vim: Fold top level folds only” question has a solution to an indent level, but it requires an environment set each time you change levels.
When my cursor is at an indent level (say level 2), I want the entire file to fold to that indent level across all methods.
Is this built into Vim somewhere? Does anyone know of a good plugin that does this?
Configure folding to be defined by indentation:
:setl foldmethod=indent
and try the following command:
:let &l:foldlevel = indent('.') / &shiftwidth
To quickly access this command, create a mapping for it as follows:
:nnoremap <silent> <leader>z :let&l:fdl=indent('.')/&sw<cr>
Because foldnestmax doesn't apply when foldmethod is expr, I looked for something else when I came across your question. Here is what I came up with, which doubtless can be improved:
function! <sid>CloseFoldOpens(opens_level)
let lineno = 2
let last = line("$")
while lineno < last
if foldclosed(lineno) != -1
let lineno = foldclosedend(lineno) + 1
elseif foldlevel(lineno) > foldlevel(lineno - 1)
\ && foldlevel(lineno) == a:opens_level
execute lineno."foldclose"
let lineno = foldclosedend(lineno) + 1
else
let lineno = lineno + 1
end
endwhile
endfunction
nnoremap <silent> z1 :%foldclose<cr>
nnoremap <silent> z2 :call <sid>CloseFoldOpens(2)<cr>
nnoremap <silent> z3 :call <sid>CloseFoldOpens(3)<cr>
nnoremap <silent> z4 :call <sid>CloseFoldOpens(4)<cr>
nnoremap <silent> z5 :call <sid>CloseFoldOpens(5)<cr>
I prefer the numbered maps, but for yours based on indentation of the current line, something along these lines:
nnoremap <silent> z. :call <sid>CloseFoldOpens(foldlevel('.'))<cr>zv
No need of a plugin, it is builtin in Vim.
'foldlevel' (or shorter 'fdl') and 'foldnestmax' ('fdn') seems to be what we were looking for. You only have to set the 'foldmethod' (or shorter 'fdm') and a 'foldnestmax' (or 'fdn') in you .vimrc file:
set foldmethod=indent foldlevelstart=2 foldnestmax=2
OR the shorter version:
set fdm=indent fdls=2 fdn=2
Then you can change the fold level with direct commands: zm or zr.
Can you have Vim expand a fold automatically when the cursor touches it?
See the foldopen option. It controls which groups of commands will lead to
opening a fold if the cursor is moved into a closed fold.
Note that vertical movements do not open a closed fold, though. Moreover,
there is no setting in foldopen to enable this behavior. When hor item is
set in foldopen option, to open a fold one can use h, l or other
horizontal movement commands. In case if it is crucial to automatically open
a fold on any cursor movement that touches it, one can approach this problem
by remapping some subset of vertical movement commands like it is shown below.
nnoremap <silent> j :<c-u>call MoveUpDown('j', +1, 1)<cr>
nnoremap <silent> k :<c-u>call MoveUpDown('k', -1, 1)<cr>
nnoremap <silent> gj :<c-u>call MoveUpDown('gj', +1, 1)<cr>
nnoremap <silent> gk :<c-u>call MoveUpDown('gk', -1, 1)<cr>
nnoremap <silent> <c-d> :<c-u>call MoveUpDown("\<lt>c-d>", +1, '&l:scroll')<cr>
nnoremap <silent> <c-u> :<c-u>call MoveUpDown("\<lt>c-u>", -1, '&l:scroll')<cr>
nnoremap <silent> <c-f> :<c-u>call MoveUpDown("\<lt>c-f>", +1, 'winheight("%")')<cr>
nnoremap <silent> <c-b> :<c-u>call MoveUpDown("\<lt>c-b>", -1, 'winheight("%")')<cr>
function! MoveUpDown(cmd, dir, ndef)
let n = v:count == 0 ? eval(a:ndef) : v:count
let l = line('.') + a:dir * n
silent! execute l . 'foldopen!'
execute 'norm! ' . n . a:cmd
endfunction
An inferior, but a bit thriftier solution would be to open a fold on every
cursor movement.
autocmd CursorMoved,CursorMovedI * silent! foldopen
Unfortunately, this solution is not general one. After the fold under the
cursor is opened, the cursor is positioned on the first line of that fold. If
this behavior is undesirable, one can follow the vertical direction of
a movement, and place the cursor on the last line of the fold when the cursor
is moving bottom-up.
autocmd CursorMoved,CursorMovedI * call OnCursorMove()
function! OnCursorMove()
let l = line('.')
silent! foldopen
if exists('b:last_line') && l < b:last_line
norm! ]z
endif
let b:last_line = l
endfunction
However, a fold will not be opened if the movement jumps over the fold. For
example, 2j on the line just above a fold will put the cursor on the line
just after that fold, not the second line in it.
set foldopen=all
seems to do what you want. You may also make an autocommand for cursor movement:
au CursorMoved * call AutoOpen()
calling a function like:
function! AutoOpen()
if foldclosed(".") == line(".")
call feedkeys("zo")
endif
endfunction
If you want this to also work in insert mode, use:
au CursorMoved,CursorMovedI * call AutoOpen()
:help fdo and possibly :help fcl may help you. I have this line in my .vimrc:
set foldopen=block,hor,insert,jump,mark,percent,quickfix,search,tag,undo