Can an autocmd be turned on/off? - vim

I have follwing in my .vimrc to hightlight all words that matches the one on current cursor
autocmd CursorMoved * silent! exe printf('match Search /\<%s\>/', expand('<cword>'))
But sometimes it is a little annoying, so I'd like to map a key to turn on or off it, e.g. <F10>
How can I do this?

Clear the autocommand and remove highlight:
nmap <f8> :autocmd! CursorMoved<cr> :call clearmatches()<cr>
and to turn it back on using a different key:
nmap <f9> :autocmd CursorMoved * silent! exe printf('match Search /\<%s\>/', expand('<cword>'))<cr>

Put the following in your .vimrc:
let g:toggleHighlight = 0
function! ToggleHighlight(...)
if a:0 == 1 "toggle behaviour
let g:toggleHighlight = 1 - g:toggleHighlight
endif
if g:toggleHighlight == 0 "normal action, do the hi
silent! exe printf('match Search /\<%s\>/', expand('<cword>'))
else
"do whatever you need to clear the matches
"or nothing at all, since you are not printing the matches
endif
endfunction
autocmd CursorMoved * call ToggleHighlight()
map <F8> :call ToggleHighlight(1)<CR>
The idea is, if you call the function with an argument it changes the behavior to print/no print.
The autocommand just uses the last setting because the function there is called without an argument.

Related

How to enable/disable "function" (if ... els)

I have the following keymaps:
nnoremap <silent> <leader>vn :call Number()<CR>
function! Number()
set number relativenumber
augroup numbertoggle
autocmd!
autocmd BufEnter,FocusGained,InsertLeave * set relativenumber
autocmd BufLeave,FocusLost,InsertEnter * set norelativenumber
augroup END
endfunction
nnoremap <silent> <leader>vN :call NoNumber()<CR>
function! NoNumber()
set number! norelativenumber
augroup numbertoggle
autocmd!
autocmd BufEnter,FocusGained,InsertLeave * set norelativenumber
autocmd BufLeave,FocusLost,InsertEnter * set norelativenumber
augroup END
endfunction
But I would like to use only one <leader>vn shortcut for this; i.e. to call NoNumber if Number has already been called. What is the correct way to do this?
It seems like I can use if ... else in Number function, but I'm not sure how to implement it correctly. Or is there some other way?
Just check if the option number is set:
if &number
set nonumber
else
set number
endif
See the docs on using &option.
You can combine if with the mapping:
:nnoremap <silent> <leader>vn :if &number | call NoNumber() | else | call Number() | endif<CR>

Stop cursor from moving when toggle line numbering

I've set up some options in my .vimrc so that it toggles to relative line numbering when in visual modes and switches back to absolute when hitting escape. The problem is every time I switch modes, it brings the cursor back to the first column. I am trying to stop this.
My original code is as follows and is inspired by this post.
So my code is
autocmd InsertEnter * :set norelativenumber
autocmd InsertLeave * :set relativenumber
function! SetLineNumbersVisual()
set relativenumber
return
endfunction
function! ResetLineNumbering()
set norelativenumber
return
endfunction
map <Esc> :call ResetLineNumbering()<CR>
vnoremap <silent> <expr> <SID>SetLineNumbersVisual SetLineNumbersVisual()
nnoremap <silent> <script> v v<SID>SetLineNumbersVisual
nnoremap <silent> <script> V V<SID>SetLineNumbersVisual
nnoremap <silent> <script> <C-v> <C-v><SID>SetLineNumbersVisual
augroup LineNumberSwap
autocmd!
autocmd InsertEnter * call ResetLineNumbering()
autocmd InsertLeave * call ResetLineNumbering()
autocmd CursorHold * call ResetLineNumbering()
augroup END
So that code swaps to relative when in any visual mode and then upon exiting brings it back to absolute. What is also does it constantly move the cursor back to the first column.
To fix this I tried determining the cursor position before setting the mode and then forcing the cursor to move back, but does this doesn't seem to work.
function! SetLineNumbersVisual()
let l:cur_pos = getpos(".")
set relativenumber
call cursor(l:cur_pos[1],l:cur_pos[2])
return
endfunction
function! ResetLineNumbering()
let l:cur_pos = getpos(".")
set norelativenumber
call cursor(l:cur_pos[1],l:cur_pos[2])
return
endfunction
Isn't fixing the problem though.
If you don't specify a return expression, 0 is returned, which evaluates to "go to the first character" motion.
You want to return an empty string:
function! SetLineNumbersVisual()
set relativenumber
return ''
endfunction

How to retain cursor position when using :%!filtercmd in vim?

When I issue a vim command that starts with :%!, such as :%!sort to sort all lines in the buffer, the cursor moves to the first line. How do I preserve the cursor position?
Ultimately, I want to use this command in an autocmd, such as:
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :%!sort
augroup END
Will the same method work in both places?
You can use a mark to remember the current line number (but note that the line contents could change):
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :kk
autocmd BufWrite *.xxx :%!sort
autocmd BufWrite *.xxx :'k
augroup END
I would rather use the Preserve function. Beyond solving your problem in this particular task you can use it for much more.
" preserve function
if !exists('*Preserve')
function! Preserve(command)
try
let l:win_view = winsaveview()
"silent! keepjumps keeppatterns execute a:command
silent! execute 'keeppatterns keepjumps ' . a:command
finally
call winrestview(l:win_view)
endtry
endfunction
endif
augroup filetype_xxx
autocmd!
autocmd BufWrite *.xxx :call Preserve("%!sort")
augroup END
You can also use the "Preserve Function" to perform other useful tasks like:
command! -nargs=0 Reindent :call Preserve('exec "normal! gg=G"')
DelBlankLines')
fun! DelBlankLines() range
if !&binary && &filetype != 'diff'
call Preserve(':%s/\s\+$//e')
call Preserve(':%s/^\n\{2,}/\r/ge')
endif
endfun
endif
command! -nargs=0 DelBlank :call DelBlankLines()
nnoremap <Leader>d :call DelBlankLines()<cr>
" remove trailing spaces
if !exists('*StripTrailingWhitespace')
function! StripTrailingWhitespace()
if !&binary && &filetype != 'diff'
call Preserve(":%s,\\s\\+$,,e")
endif
endfunction
endif
command! Cls call StripTrailingWhitespace()
cnoreabbrev cls Cls
cnoreabbrev StripTrailingSpace Cls

What autocmd FileType is in .vimrc?

I started using twitvim and found this code code for .vimrc.
But I am not sure what the last part of code is trying to do.
autocmd FileType twitvim call s:twitvim_my_settings()
function! s:twitvim_my_settings()
set nowrap
endfunction
And this is the original code. I deleted all of <C-u>, <C-w> and j.
""" twitvim
let twitvim_count = 40
nnoremap ,tp :<C-u>PosttoTwitter<CR>
nnoremap ,tf :<C-u>FriendsTwitter<CR><C-w>j
nnoremap ,tu :<C-u>UserTwitter<CR><C-w>j
nnoremap ,tr :<C-u>RepliesTwitter<CR><C-w>j
nnoremap ,tn :<C-u>NextTwitter<CR>
autocmd FileType twitvim call s:twitvim_my_settings()
function! s:twitvim_my_settings()
set nowrap
endfunction
While Kent's answer is correct and very detailed, I thought I'd submit a visual version.
autocmd FileType twitvim call s:twitvim_my_settings()
|______________________| |__| | |___________________|
| | | |
1 2 3 4
1. Automatically do something when the FileType (the file extension) matches .twitvim
2. call (Vim's way to run a function)
3. Refers to a function local to the current script file
4. The function to be ran
I don't use the plugin, but I could try to explain what the meaning of those lines:
"this just assigning a variable, may be used by the plugin
let twitvim_count = 40
" create a normal mode mapping, to execute Posttotwitter command.
" The leading ctrl-u just for removing the range information of the
"command line. if you removed it, range info will be kept
" all following commands have the same meaning for <c-u>
nnoremap ,tp :<C-u>PosttoTwitter<CR>
" the next 4 commands are same as above, but executing different cmd. the ctrl-w j will move cursor
" to a "belower" window, the cmd may open a new window/split.
nnoremap ,tf :<C-u>FriendsTwitter<CR><C-w>j
nnoremap ,tu :<C-u>UserTwitter<CR><C-w>j
nnoremap ,tr :<C-u>RepliesTwitter<CR><C-w>j
nnoremap ,tn :<C-u>NextTwitter<CR>
"create autocmd, if the filetype is twitvim, call a function
autocmd FileType twitvim call s:twitvim_my_settings()
"here a function was defined
function! s:twitvim_my_settings()
"this function just do one thing, set nowrap option. (text is gonna be displayed without wrap.)
set nowrap
endfunction

Stop substitutions in vim function from leaking out into history of all substitutions

I have a pre-buffer write hook set up in vim that makes a few small adjustments before the contents of the buffer is saved out to a file.
if !exists("autocommands_loaded")
let autocommands_loaded = 1
autocmd BufWritePre *.php call TidyUpFormatting()
endif
func! TidyUpFormatting()
let save_cursor = getpos('.')
%s/\s\+$//ge
%s/\($\n\s*\)\+\%$//ge
%s/var_dump /var_dump/ge
%s/){/) {/ge
%s/( /(/ge
%s/if(/if (/ge
%s/while(/while (/ge
call setpos('.', save_cursor)
endfunction
This is in my ftplugin/php.vim file.
I've noticed though that these substitutions in TidyUpFormatting show up in the history of all substitutions - for example if I scroll up through the list of substitutions that I've done manually, there they are.
Is there a flag I can use, or indeed some better way, to do this so that these substitutions don't "leak out"?
Search patterns from :substitution inside a function indeed do pollute the search history (once for an entire function, not for every :s). You can remedy this by adding this at the end of the function:
:call histdel('search', -1)
I needed to prefix the substitution commands with the "silent" command, changing the TidyUpFormatting function to:
func! TidyUpFormatting()
let save_cursor = getpos('.')
silent! %s/\s\+$//ge
silent! %s/\($\n\s*\)\+\%$//ge
silent! %s/var_dump /var_dump/ge
silent! %s/){/) {/ge
silent! %s/( /(/ge
silent! %s/if(/if (/ge
silent! %s/while(/while (/ge
call setpos('.', save_cursor)
endfunction

Resources