Extend a vim command - vim

How can I extend a command in vim?
I want to do it in two situations,
After a :diffget or :diffput I always want to run a :diffupdate
After a :NERDTreeToggle I want to run a <C-w>=

I am unaware of any autocmd events that would be triggered for your scenarios. However a few custom mappings might be helpful.
You can change the default dp and do mappings to also do a :diffupdate
nnoremap dp dp:diffupdate<cr>
nnoremap do do:diffupdate<cr>
Note there are times where you cannot use dp and/or do and must use :diffput/:diffget. In these cases I would suggest you create a commands like so:
command! -nargs=? -range=1 -bar Diffput <line1>,<line2>diffput <args>|diffupdate
command! -nargs=? -range=1 -bar Diffget <line1>,<line2>diffget <args>|diffupdate
Or you can just map :diffupdate
nnoremap <f8> :diffupdate<cr>
NERDTree
nnoremap <leader>N :NERDTreeToggle<cr><c-w>=

Maybe you can have a look to the vim macro. It is probably suitable for what you want to do :).

Create your own custom function in VimScript in your .vimrc that wraps several commands.
Here's one I use to launch a Clojure Repl in a buffer using several plugins:
fun! LeinCMD()
execute 'ConqueTerm lein repl'
execute 'set syntax=clojure'
execute 'normal! i'
endf
command! Repl call LeinCMD()
I then call this command with :Repl (note that your custom commands must always start with an uppercase letter).
Source: Automate running several vim commands and keystrokes

Related

Vimrc autocmd runs command instead of mapping

I want to add a hotkey to my vim to run my python files, so I have added the following line to my vimrc:
autocmd FileType python map <F5> :w|!python3 %
But on opening the file instead of running autocmd, it runs python with my file.
For me this seems no different from what many tutorials suggest on using autocmd and map, so I'd like to know what exactly is happening here instead of the behavior I expect.
Your :map command ends at the command separator |; the remainder is already executed when the :autocmd runs. You need to escape it (\|), or better use the special <Bar> character:
autocmd FileType python nnoremap <buffer> <F5> :w<Bar>!python3 %<CR>
Cp. :help map_bar. Also, you should use :noremap; it makes the mapping immune to remapping and recursion. And (as #PeterRincker suggested), make the mapping buffer-local, so that it only applies to Python buffers).
Your :autocmd FileType approach is fine for a few mappings, but it doesn't scale well. If you have :filetype plugin on in your ~/.vimrc, you can factor our your mappings into a separate script ~/.vim/ftplugin/python_mappings.vim.

:edit in function does not opens path given in argument

I have in .vimrc:
function! s:Edit(path)
vsplit a:path
endfunction
command! -nargs=1 -complete=file E call s:Edit(<q-args>)
Problem is that in new window i have file named "a:path" not file passed as argument to :E command.
Although my function starts to work when i do:
exec "vsplit".a:path
Why?
Can it be done better?
Build up your command and execute it with :execute. e.g.
function! s:Edit(path)
execute 'vsplit ' . a:path
endfunction
command! -nargs=1 -complete=file E call s:Edit(<q-args>)
For more help see :h :exe
Is there a better way?
Really depends on your goals. I would need more information about what this is supposed to do. However it seem like you want to create an alias for :vsplit. I would suggest you using cmdalias.vim or a the very least the following:
command! -nargs=? -complete=file -bang E vsplit<bang> <args>
If all you are doing is trying to optimize key strokes then the following mapping would also be sufficient:
nnoremap <leader>v :vsp<space>
Personally I would just get used to using :vsplit and stop worrying.

VIM: why do these bindings work only sometimes?

I've got these bindings in my .vimrc. They work most of the time, but sometimes they don't: they will just save the file but not run it.
Then I go into insert mode and exit it back to normal mode, and they work again. What could be the problem?
Thanks!
autocmd FileType python map <C-k> :write <CR> :! python % <CR>
autocmd FileType lisp map <C-k> :write <CR> :! clisp % <CR>
autocmd FileType scala map <C-k> :write <CR> :! scala % <CR>
There are many topics to discuss here so with out further ado:
Mappings
Your current mappings map <c-k> ... will only work in normal, visual, and operator-pending modes. However executing your mappings in visual mode or operator-pending modes would save the buffer with only a range of lines (read not good). I suggest you make your mappings for normal mode only.
Two general rules of thumb:
Always supply a mode like n for normal.
Always use noremp instead of map unless you are mapping to a <Plug> mapping.
So one of your mappings might look something similar to this:
nnoremap <c-k> :w<cr>:!python %<cr>
For more information:
:h :map-modes
:h map-overview
:h :nore
:h map-listing
:h map-verbose
Filetype based mappings
You need to do 2 things:
Create a mapping local to a specific buffer by using the <buffer> option for noremap.
Load the mappings for just a specific filetype.
This can be done via an autocmd and FileType event in your .vimrc like so:
autocmd FileType python nnoremap <buffer> <c-k> :w<cr>:!python %:p<cr>
The other way option is by creating a filetype plugin. (see :h ftplugin for more details)
A simple example is do create a file named, ~/.vim/ftplugin/python.vim and place your mappings inside like so:
nnoremap <buffer> <c-k> :w<cr>:!python %:p<cr>
I personally lean more towards the ftplugin approach but having a everything in your .vimrc file can be nice.
For more help see:
:h :au
:h FileType
:h map-local
:h ftplugin
:make
A more vim like way of doing this would be to use :make. (Assuming you want to lint vs execute your current buffer)
:make will execute the 'makeprg'. It defaults to make which is great of C projects
After running :make the quickfix list will be contain any errors.
Set your compiler via the :compiler command.
Extra parameter can be passed like so :make foo-command
Current filename can be represented by %. e.g. :make %
Often people set do :complier/'makeprg' in side of ftplugins e.g. ~/.vim/ftplugin/perl.vim or autocmd's e.g. autocmd FileType perl compiler perl.
Fop more help see:
:h :make
:h 'makeprg'
:h :compiler
:h c_%
quickfix list
Use :cnext and :cprev to move between your errors.
:copen to open up the quickfix list in a window (:cclose to close)
:cwindow to open quickfix list window only if there are errors
May want to use better mappings for :cnext and friends. I suggest Tim Pope's unimpaired plugin
For more help see the following:
:h quickfix
:h :cnext
:h :cope
Alternatives to using :make
Just use <c-z> to suspend vim and run your build system. (Cons: loose out on the quickfix list)
Use :! to compile. (Same cons as suspending) e.g. :!make
Syntastic is a syntax checking system that checks files on save
Ale (Asynchronous Lint Engine) is a plugin for providing linting in NeoVim and Vim 8 while you edit your text files
Dispatch can be used to run things in the background. Great for test suites
May want to consider terminal multiplexers like tmux or screen.
SingleComplile tries and takes some of the work out of using :make
Conclusion
Personally I would install ALE as this removes the need for your mappings. It is also a great idea to learn how to use the location (or quickfix) list. When you are ready to get your hands dirty then you can learn and use :make.
tl;dr
Install ALE.
The space inserted between <CR> and : could lead to errors, because this space is really entered during the execution of the mapping.
With :noremap or :nnoremap (which should be used most of the times, as Peter Rincker wrote in his answer), it wouldn't be a big problem, since it only would move the cursor one char to the right (see :h <space>).
But with :map, it could trigger a custom mapping (or a partial one).
Then, instead of:
autocmd FileType python map <C-k> :write <CR> :! python % <CR>
the following would be better:
autocmd FileType python map <C-k> :write <CR>:! python % <CR>
and this one, really better:
autocmd FileType python nnoremap <C-k> :write <CR>:! python % <CR>

Run selected text through filter and reinsert

I like using code cleanup scripts; perldidy; uglifierjs, etc. I previously ran them all like this in my vimrc...
map <leader>pt :!perltidy<CR>
map <leader>jt :!uglifyjs -b<CR>
map <leader>pjt :!python -mjson.tool<CR>
map <leader>ct :!column -t<CR>
How this functionally works; it runs currently selected text throguh the CLI program, and replaces the selection with the output. Works wonderfully; but as you can see I now have to stop and think what beautifier I want to run and remember the nemonic I have for it. This led me to think there has to be a better way. So I tried did this...
map <leader>jt :call RunTidy()<cr>
function! RunTidy()
if (&ft == "javascript")
echo 'is js..'
:'<,'>!ulifyjs -b
endif
if (&ft == "json")
echo 'is json'
:'<,'>!python -mjson.tool
endif
endfunction
The problem being this just doesn't work; executing once for each line and not replacing contents.. Anyone aware of a better way to do this? I feel like this should be a solved problem...
augroup filters
autocmd!
autocmd FileType perl map <buffer> <leader>t :!perltidy<CR>
autocmd FileType javascript map <buffer> <leader>t :!uglifyjs -b<CR>
autocmd FileType json map <buffer> <leader>t :!python -mjson.tool<CR>
augroup END
or put those mappings, all with the same lhs, in different ~/.vim/after/ftplugin/{filetype}.vim.
Use ftplugins. You need to have filetype plugin indent on in your vimrc.
Create files in ~/.vim/ftplugin/<filetype>.vim. These files will be sourced when the file type is set.
For example using javascript put the following in ~/.vim/ftplugin/javascript.vim
noremap <buffer> <leader>jt :!uglifyjs -b<CR>
to map <leader>jt to :!uglifyjs -b<CR> in all javascript buffers. This will not show up in other filetypes.
You would do the same for all other filetypes.
You can do the same for file type specific settings by using setlocal.
Take a look at :h ftplugin

Can I use cppcheck when I execute :wq in Vim editor for c/c++

I want to override wq/q/w!/w/q! to user defined command along with its functionality.
Example :
If I use :wq to exit, the command should do static code check of that particular c/c++ file and exit.
Please help me in this case.
Thanks in advance.
The built in solution to your problem is called an "autocommand" in Vim.
It is a way to invoke a command at a specific time like opening, saving or closing a buffer.
See :help autocmd for the full list
In your case, you should add to your .vimrc the following command
autocmd BufWritePre *.cpp,*.hpp !cppcheck %
BufWritePre means 'before writing the buffer' (You can also use BufWrite or BufWritePost)
*.cpp,*.hpp means the auto command will only be applied when saving cpp or hpp files. You can add c and h files if you want.
% means 'path of the current buffer'
cppcheck must be in your path
You are not overriding the defaut behaviour of 'w' but you are using 'hooks' to add custom commands.
I wouldn't do that. It obliges us (well, you actually) to save only when the file is really compilable -- which make no sense when we have to abort the current editing because an urging meeting that we've forget about is about to begin; saving the file in that situation is the normal way to proceed.
Moreover, what is the purpose of running cppcheck on a :wq? How can we exploit the result?
Instead, I'd have a mapping that run cppcheck, though :make in order to exploit the vim quickfix feature (:h quickfix)
function s:Check()
try
let save_makeprg=&makeprg
set makeprg=cppcheck
" you may have to specify other files/extensions
:make *.cpp *.hpp
finally
let &makeprg=save_makeprg
endtry
endfunction
nnoremap <buffer> <c-f7> :call <sid>Check()<cr>
<block>
function FunForQuickfix(makeprgIn, makeefmIn)
try
let save_makeprg=&makeprg
let save_makeefm=&efm
let &makeprg=a:makeprgIn
let &efm=a:makeefmIn
:wa
:make
:cw
finally
let &makeprg=save_makeprg
let &efm=save_makeefm
endtry
endfunction
function CompileAndRunTestCodeByScons()
call FunForQuickfix('scons . -j8 -u', '%f:%l:%c:\ %m,%f:%l:\ %m,build/release64/%f:%l:%c:\ %m,build/release64/%f:%l:\ %m,%f\|%l\|,build/release64/%f:%s,%m:%l:Assertion,%sExpression:\ false,scons:\ building\ terminated\ because\ of\ errors,%sError%m')
endfunction
function CppCheck()
call FunForQuickfix("cppcheck *.cpp -j 8 --enable=all", "\[%f:%l\]:\ %m")
endfunction
nmap ma :wa<CR>:call CompileAndRunTestCodeByScons()<CR>
nmap mc :wa<CR>:call CppCheck()<CR>
nmap <F3> :cp<cr>
nmap <F4> :cn<cr>
</block>
add this in ~/.vimrc, then use ma to compile code and mc to run cppcheck
this code is copy from Luc Hermitte, and i chang it
You might want some things even better, use cppcheck and other checkes while you are developing in vim.
Install and use that vim plugin: https://github.com/scrooloose/syntastic

Resources