How to avoid remap in vim - vim

I have the following on my .vimrc
au FileType ruby nnoremap <expr> <leader>t ':!rspec ' . expand('%') . ':' . line('.')
This executes rspec on the line specified, and gives me option to edit the line before pressing enter. But I have to be on the test file so it get the file name and line number correctly.
While developing I run nnoremap <leader>t :!rspec some/spec/file.rb:123 manually to run the test I want from anywhere in the code. So I can code and fire the test without need to visit the test file.
The problem is that if I visit another ruby file the mapping in .vimrc runs again and I loose the nnoremap command I used before. Is there a command to only map (in normal mode) if there isn't already a map for that sequence?
Regards,

This should be a buffer-local mapping. Use <buffer>:
au FileType ruby nnoremap <buffer> <expr> <leader>t ':!rspec ' . expand('%') . ':' . line('.')
We can do better!
Use an augroup and make is self clearing to make it safe to re-:source.
augroup ruby_testing
autocmd!
autocmd FileType ruby nnoremap <buffer> <expr> <leader>t ':!rspec ' . expand('%') . ':' . line('.')
augroup END
Even better forgo the autocmd and put this mapping in the after directory. Add the following line to ~/.vim/after/ftplugin/ruby.vim:
nnoremap <buffer> <expr> <leader>t ':!rspec ' . expand('%') . ':' . line('.')
For more help see:
:h :map-local
:h :augroup
:h after-directory

Vim has the :help :map-<unique> modifier which makes the mapping fail if such mapping already exists.
au FileType ruby nnoremap <unique> <expr> <leader>t ...
You can suppress the error message with :silent!:
au FileType ruby silent! nnoremap <unique> <expr> <leader>t ...
Alternatively (and this is slightly better because it doesn't suppress any other errors in the mapping definition, like syntax errors), you could explicitly check for the mapping's existence via maparg():
au FileType ruby if empty(maparg('<leader>t', 'n')) | nnoremap <expr> <leader>t ... | endif
Note that this literally implements that (I understand) you're asking for; i.e. the first Ruby file will define the mapping, and any subsequent Ruby files are ignored; the mapping will always use the first file's name and line number. If you instead want to have different right-hand sides for the same mapping, depending on the currently edited file, the solution is a buffer-local mapping as per #PeterRincker's answer. But with that, you have to be inside the original Ruby buffer to trigger the correct mapping.
A remedy for that might be to recall the executed command-line from the command-line history (should happen automatically for your incomplete mapping, else via histadd()), so that you can easily recall the command from another file.

Related

How to use different .vimrc than what is the default .vimrc

I share lab server with my colleagues, but want my separate .vimrc file. How to get that?
$ cat .vimrc
color desert
$ pwd
/fvs101/home
We have our separate working directory, so my directory is inside
/fvs101/home/sp
At /fvs101/home there is common .vimrc file.
I want to play with vim but do not want to touch this /fvs101/home/.vimrc file.
I want to create my own .vimrc file.
++++++++++my vimrc file
[sp]$ cat .vimrc
noremap - ddp
noremap _ dd2kp
inoremap <c-u> <esc>lviwU<esc>i
nnoremap <c-u> <esc>viwU<esc>
let mapleader = "-"
let maplocalleader = "\\"
nnoremap <leader>ev :vsplit $MYVIMRC<cr>
nnoremap <leader>sv :source $MYVIMRC<cr>
iabbrev ssig -- <cr>Sachin Pawar<cr>sachin.sp.pawar#oracle.com
vnoremap <leader>' vi<esc>`<<esc>i'<esc>`><esc>i'<esc>
nnoremap H 0
nnoremap L $
inoremap jk <esc>
inoremap <esc> <nop>
augroup filetype_js
autocmd!
autocmd FileType javascript nnoremap <buffer> <localleader>c I//<esc>
augroup END
augroup filetype_python
autocmd!
autocmd FileType python nnoremap <buffer> <localleader>c I#<esc>
augroup END
augroup filetype_sql
autocmd!
autocmd FileType sql nnoremap <buffer> <localleader>c I--esc>
augroup END
augroup filetype_shell
autocmd!
autocmd FileType shell nnoremap <buffer> <localleader>c I#esc>
augroup END
augroup filetype_html
autocmd!
autocmd FileType html nnoremap <buffer> <localleader>f Vatzf
augroup END
++++++++++
If i use my separate .vimrc file i am not able to see the mapping for some mappings like
inoremap jk
Why is this happening and how to avoid it.
In order to use my own .vimrc file i have create a separate alias.
alias vi='vim -u /fvs101/home/sp/.vimrc'
Make a different .vimrc (as you have stated in the comments, /refresh/oracle/spawar/.vimrc) and make an alias for your own user
myvi='vim -Nu /refresh/oracle/spawar/.vimrc'
Note that without the -N flag, using the -u flag will start vim in compatibility mode causing all sorts of nasty, unexpected side-effects such as mappings not working entirely.
I found this out by going to see what the -u flag really does and following from there.
Helpful links below.
u flag
N flag
Seeing as you specifically want everyone to log into the same user, the easiest way I can think of how to do this is if you make your own .vimrc (give it a short name, such as ~/.vrc) and every time you open vim, you type
:so ~/.vrc
which will load that vimrc for you. Every time you open vim it will use the defaults, until you load your own vimrc, so you will have to do this each and every time. Also remember that this way, ~/.vimrc loads automatically before you manually load ~/.vrc
You can call Vim with a different runtime configuration file than the default one with
vim -N -u path/to/your/vimrc
If you want to use this always, edit your users shell runtime configuration to define an alias for that.
alias vim="vim -N -u path/to/your/vimrc"
I think the simplest solution would be to append a single line to the end of the default vimrc which reads:
source ~/.vimrc.local " Or whatever you want to call it
Where .vimrc.local contains your custom configuration.

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

How can I show winmanager automatically?

I’ve installed the winmanager, NERDTree and BufExplorer plugins. Now, I have <F8> set to toggle the winmanager display, using the following code in my .vimrc:
" mapping for triggering winmanager plugin
nnoremap <silent> <F8> :if IsWinManagerVisible() <BAR>WMToggle<CR><BAR> else<BAR> WMToggle<CR>:q<CR> endif <CR><CR>
This works fine.
What I want to do is to have winmanager show up automatically if the filetype is .c or .cpp. I added this to my .vimrc:
autocmd FileType c,cpp nested "\<F8>"
but it does not work.
Any help? Thanks in advance!
<F8> is a normal-mode mapping, but :autocmd expects an Ex command on its right-hand side. You need to use :normal (without a ! here, to allow mappings to take effect), and :execute to interpret the special key code:
:autocmd FileType c,cpp nested execute "normal \<F8>"
But I think it is cleaner to avoid the additional redirection and duplicate the mapping's commands instead:
:autocmd FileType c,cpp nested if IsWinManagerVisible() |exe 'WMToggle'| else| exe 'WMToggle' | quit | endif

Change the mapping of F5 on the basis of specific file type

The current mapping of my F5 key is:
imap <F5> <esc>:w\|!python %<CR>
Now I want that if I'm editing any python file (it will be better if it also recognizes file other than standard .py format like .pyd etc) then this mapping works as it is. But, if I edit a Java file it is mapped to something like:
imap <F5> <esc>:w\|!javac %<CR>
And when I'm editing any .c or .cpp file then F5 is mapped to this:
imap <F5> <esc>:w\|!make %<CR>
I have no idea how to proceed.
There are problems with both given answer and original mapping. First of all, for buffer-local mappings there is *map <buffer>. Second, with <buffer> you don’t need to use BufEnter events and can instead use Filetype which are launched only once. Third, you have one error (2.), one potential problem (1.) and one place that can be optimized in original mappings:
you should not be using imap, it makes it very easy to accidentally break old mappings when adding new ones
!python % will break once file contain a special symbol (space, semicolon, quot, dollar, …)
using :update instead of :write avoids useless writes in some cases
My variant:
autocmd Filetype c,cpp inoremap <buffer> <F5> <C-o>:update<Bar>execute '!make '.shellescape(expand('%:r'), 1)<CR>
autocmd Filetype python inoremap <buffer> <F5> <C-o>:update<Bar>execute '!python '.shellescape(#%, 1)<CR>
autocmd Filetype java inoremap <buffer> <F5> <C-o>:update<Bar>execute '!javac '.shellescape(#%, 1)<CR>
Try this:
au BufEnter *.py map <F5> <esc>:w\|!python %<CR>
au BufEnter *.java imap <F5> <esc>:w\|!javac %<CR>
au BufEnter *.c, *.cpp imap <F5> <esc>:w\|!make %<CR>
I'm not 100% sure about the comma separated file types, trying to verify...
The vim docs are usually pretty nasty to try to figure out how to use commands, but these should help get you started:
:h BufEnter
:h :autocmd
Note: You may have to restart vim for these changes to overwrite the current autocommand groups.

Vim: <leader> key sequences are interfused with normal mode mappings

I'm trying to define mappings for "cpp" filetype:
autocmd! FileType cpp map <leader>c echo "test c"
autocmd! FileType cpp map <leader>r echo "test r"
autocmd! FileType cpp map <leader>t echo "test t"
My leader key is redefined:
let mapleader = ","
When I open *.cpp file only one of the mappings works as expected: the ",t" sequence makes the "echo" happen, but the other two behaves as if there were no any mappings defined: ",r" makes Vim to switch to replace mode and ",c" brings Vim to insert mode.
What am I doing wrong?
I don't know how your example (including ,c one) could work: you forgot to prepend echo with a colon. But there is another mistake: according to the help:
:au[tocmd]! [group] {event} {pat} [nested] {cmd}
Remove all autocommands associated with {event} and {pat}, and add the command {cmd}.
So, the last one (,t) should replace all previous ones.
There are also another things you should to consider:
Don't use map, use noremap instead: it may once save you from doing a debug job after you add some mapping.
If you define filetype mapping you should normally add <buffer> as an argument to :noremap in a position before {lhs}: it will make this mapping local to the current buffer.
In case you want to re-source vimrc you should put all command into augroup:
augroup VimrcCpp
autocmd!
autocmd FileType cpp nnoremap <buffer> <leader>c :echo "c"<CR>
autocmd FileType cpp nnoremap <buffer> <leader>r :echo "r"<CR>
autocmd FileType cpp nnoremap <buffer> <leader>t :echo "t"<CR>
augroup END
I would have removed it from vimrc and added to ~/.vim/ftplugin/cpp.vim (after directory is to be used only to override options that you don't like if they are unconditionally defined by a plugin. If there are no mapping conflicts, don't use after).
I suggest you put those mapping in a file called cpp.vim placed in your ~/.vim/after/ftplugin/ (or any equivalent based on OS) directory.
Vim automatically loads it as long as you have
filetype plugin on
in your .vimrc.
This saves you writing autocommands and keeps your configuration well organized.

Resources