Different VimResized autocmds for Shrinking and Growing - vim

autocmd VimResized * <foo> will run the command <foo> whenever the vim application's window is resized.
Is there a way to run different commands depending on whether the resize is a shrink or a grow?
And, if so, are there any caveats for console vim?

A window is 2-dimensionnal, so the concept of shrinking or growing is quite imprecise : are you talking about the height, or about the width, or about the area?
Let's assume you're talking about the area.
A simple way to do it is to save the last size of the window, on startup and on each time the win is resized; then you just have to compare the last size and the new one, each time the win is resized:
" Defines a command to save the current dims:
command! SaveVimDims let g:last_lines=&lines | let g:last_columns=&columns
" Saves the dims on startup:
au VimEnter * SaveVimDims
" Calls the func below, each the win is resized:
au VimResized * call VimResized_Func()
function! VimResized_Func()
" Gets the area of the last dims:
let last_area = g:last_lines * g:last_columns
" Saves the new dims:
SaveVimDims
" Gets the area of the new dims:
let cur_area = g:last_lines * g:last_columns
" Compares the areas:
if cur_area < last_area
" do something when shrinking
else
" do something when growing
endif
endf
This was only tested with Gvim; I never use Vim in console. Hope it'll work as well

Related

Vim popup window not showing on successive events

I have the following plugin I wrote to test popup windows
"plugin/morning/morning.vim"
augroup morning_command_line_popup
autocmd!
au CmdlineLeave * call morning#close()
au CmdlineEnter * call morning#open()
au CmdlineChanged * call morning#update()
augroup END
"autoload/morning.vim"
function morning#open()
let opt = {}
let opt.border = []
let opt.minwidth = &columns / 3
let g:morning_window_handle = popup_create(":echo 'hi'", opt)
endfunction
function morning#close()
call popup_close(g:morning_window_handle)
endfunction
function morning#update()
call popup_show(g:morning_window_handle)
endfunction
The first time I enter the command line, the popup window appears. Every successive time that I enter the command line, it doesn't appear. I know the events are being fired and the functions are being called because if I put echom commands in the functions the messages show. Anyone know what could be wrong?
I figured out that if I redraw after showing the popup window, it seems to work consistently. I don't know if there's a reason why it won't redraw normally, or if doing this is extremely inefficient. This also has the side effect of overwriting wildmenu.
function morning#open()
let opt = {}
let opt.border = []
let opt.minwidth = &columns / 3
let g:morning_window_handle = popup_create(":echo 'hi'", opt)
redraw
endfunction
function morning#close()
call popup_close(g:morning_window_handle)
endfunction
function morning#update()
call popup_settext(g:morning_window_handle, string(getcmdline()))
call popup_show(g:morning_window_handle)
redraw
endfunction

Colorcolumn and text wrapping at the same time in Vim

I am setting colorcolumn in Vim, on the 90th column, but at the same time I would like to maintain text wrapping functionality.
Therefore, in order to maintain the coloured column on the wrapped lines, and have no breaks, I have to put in my .vimrc something like:
let col_no=90
if ((longest_line_size / 90) >= 2)
for i in range(2, (longest_line_size / 90))
let col_no=col_no . "," . ((90*i) + (&columns - 91))
endfor
endif
execute 'set colorcolumn=' . col_no
The problem is that when I resize the window (or the buffer), the coloured column on the wrapped lines is not aligned. A solution would be to re-run the function when the buffer is resized.
Is this possible? Any other solutions/suggestions are also welcome.
You can run a function every time the window size changes using the following autocommand
augroup Resize
autocmd!
autocmd VimResized * :call YourFunctionName<cr>
augroup END
Add that to your vimrc file. To use it with your code you will need to wrap the code up in a function.
function YourFunctionName
#your code goes here
endfunction
Note that the function name must begin with a capital letter.

Resizing the vim tabline on NERDTree window resize

I am using vim (terminal/console vim NOT gui vim) with NERDTree and NERDTreeTabs.
As you may have guessed I like to use vim's tab functionality to keep track of multiple open files.
I never really liked how the tabs would start at the very "beginning" of the tabline (there would be tabs on top of the NERDTree window). I wanted to have the tabs start from the END of the NERDTree window (i.e. the right edge), resembling an IDE. So I defined my own tabline like so:
" Globals
" NERDTree width
let g:ntw = 25
set showtabline=2 " Always show tabs
function! Tabline(width)
let s = '%#String#'. repeat(' ', a:width).'|'
for i in range(tabpagenr('$'))
let tab = i + 1
let bufnr = tabpagebuflist(tab)[tabpagewinnr(tab) - 1]
let bufname = bufname(bufnr)
let s .= '%' . tab . 'T'
let s .= (tab == tabpagenr() ? '%#TabLineSel#' : '%#TabLine#')
let s .= ' '.(bufname != '' ? fnamemodify(bufname, ':t') : 'New ').' '
if getbufvar(bufnr, "&mod") " If buf is modified
let s .= '+ '
endif
endfor
let s .= '%#TabLineFill#'
return s
endfunction
set tabline=%!Tabline(g:ntw)
let g:NERDTreeWinSize = g:ntw
Basically all I am doing is inserting blank spaces into the tabline before any tabs start. The width of the blank spaces would match the width of NERDTree. Now the problem is when I resize the NERDTree window. Obviously, the tab line's extra spacing does not resize itself automatically, resulting in an ugly mismatch.
I was thinking I could find out a way to execute 'set tabline=%!Tabline(g:ntw)" where g:btw is the current width of NERDTree whenever the NERDTree window is resized. But I am unable to find out a way to do this.
As a side note, since I am using NERDTreeTabs plugin, you can assume that the NERDTree window will ALWAYS exist. You can also assume that the NERDTree window will always be on the left.
So then my questions are:
1) Is there a more elegant way of getting this done?
2) If no to 1), how could I achieve what I am trying to do? (example code please)
Thanks in advance!
Assuming that the NERD_Tree window is always at the left, occupying the full height, its window number is 1. You can then query the current width via winwidth(1) instead of hard-coding it in your g:ntw variable.

vim autocmd on change line?

I'm trying to run a function whenever a line is altered, but there doesn't seem to be a specific autocommand for this. I could run the function on CursorMoved, but it would slow down editing. I could also map the function for all the major editing movements, but it could get very messy as I'm trying to keep each line independent of the others. If there's no solution, I could possibly do a diff every few seconds to see what's changed and run the function on the changed lines, but again it's a messy solution.
Any ideas?
If you can get Vim 7.4, have a look at the TextChanged (and TextChangedI, for insert mode) events. (Note that this will monitor changes throughout the entire buffer.)
You could do something like this with a BufWritePre event. Have a master file that defines your lines and tokens, then in the slave files, a reference to their master, like:
master-Foo.vim:
let b:Dom_slaves = ['/foo/bar/slave.cpp', '...', ...]
let b:Dom_map = {
\ 10 : "do your laundry",
\ 20 : "prepare your lunch"
\ }
slave.cpp
/* Dom_master = master-Foo.vim */
...
cout << "I will gladly /* Dom-id:10 */ and /* Dom-id:20 */.\n";
Dominate.vim
let MSMap = {}
autocmd BufWritePre * call s:Dominate()
function! s:Dominate()
" if current buffer's Dom_slaves and Dom_map defined
" read & update all slaves with Dom_map mappings
" else see if 'Dom_master = somefile' appears in the buffer
" update mapped values from cache or read master file, cache and update
" endif
endfunction
By the way, this is a horrible thing to do to your vim. :P

Is there a way to diff two registers in vim? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
(Vim)diff two subroutines in same file
Sometimes I see a block of code I suspect to be identical to another block in the same file, but it's a bit too long for visual inspection and I may just be missing something. I've tried to visually select the block and yank to the the default register, put that register into / (find), but it didn't match even the original block.
Is there a way to select a section, yank it in a register, select another section then diff the two, without creating a bunch of new files? I imagine the diff results opening in a new buffer in a tab or split.
EDIT: My question is basically a duplicate of This one. I found this answer to be the most helpful & closest to what I was looking for. The only thing I'd change is to make it output in Unified format so it looks like the diff output I'm used to (it has more info as well). I suppose this means using a different diff utility.
Inspired from my lh#path#strip_common() function:
echo matchstr(#a.'##'.#b, '^\zs\(.*\)\ze.\{-}##\1.*$')
will show what is common between registers #a and #b.
You can show more information with:
function ShowDiff(a,b)
" I expect neither string to contain '##'
let start = matchstr(a:a.'##'.a:b, '^\zs\(.*\)\ze.\{-}##\1.*$')
let end= matchstr(a:a.'##'.a:b, '^.\{-}\zs\(.*\)\ze##.\{-}\1$')
let a = a:a[len(start): -len(end)-1]
let b = a:b[len(start): -len(end)-1]
echo "identical beginning: ".strlen(start )." chars -> ".start
echo "identical ending : ".strlen(end)." chars -> ".end
echo "typical to a : ".strlen(a)." chars -> ".a
echo "typical to b : ".strlen(b)." chars -> ".b
endfunction
Used with:
:call ShowDiff(#a, #b)
You could use the following sequence assuming that the two segments are already in registers, 'a and 'b. Could probably be put into a macro or function.
new
only
put a
diffthis
vnew
put b
diffthis
This creates a new buffer, makes it the only visible buffer, puts 'a into it, sets it up to be diff'd, then opens a new buffer in a vertical split, puts 'b into this split empty buffer and also sets it up to diff. Immediately vim (or gvim) will show the differences.
When done, type :ls to get the list of buffers, use :buffer *N* to return back to the original file and use :bdel! *N* to delete the created buffers (named "[No Name]").
Here's a function to open two new windows side by side, each containing the specified register contents (called as DiffRegs(#a, #1), for instance) and diff them. The new buffers will not be written or modifiable:
" A list for bookkeeping..
let g:diffreg_buffers = []
function! DiffRegs(reg1, reg2)
" Preserve the unnamed register
let s:nonamereg = ##
let ## = a:reg1
" new window
:new
normal P
setlocal nomodifiable
setlocal buftype=nofile
diffthis
call add(g:diffreg_buffers, bufnr('%'))
let ## = a:reg2
:vsp +enew
normal P
setlocal nomodifiable
setlocal buftype=nofile
diffthis
call add(g:diffreg_buffers, bufnr('%'))
let ## = s:nonamereg
endfunction " DiffRegs(reg1, reg2)
" Function to wipe all buffers we're diffing with the function above
function! EndDiffs()
for buffer in g:diffreg_buffers
exe ':buffer ' . buffer
diffoff
quit
endfor
let g:diffreg_buffers = []
endfunction " EndDiffs()
You can bind those to key combinations of your choice, but if you don't call EndDiffs() after each call to DiffRegs(), you'll run into issues.
To compare quickly two different parts of a file, you can split the view in two by using:
:sp horizontal split
or
:vsp vertical split
Once you have splitted the screen, you must use :diffthis in each window to hightlight the differences. (Then :diffoff to leave diff mode)
Then to go back to a single window you can quit one of them with :q or use CTRLwo

Resources