geckos
geckos

Reputation: 6279

How to avoid remap in 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,

Upvotes: 1

Views: 456

Answers (2)

Ingo Karkat
Ingo Karkat

Reputation: 172510

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.

Upvotes: 1

Peter Rincker
Peter Rincker

Reputation: 45087

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

Upvotes: 2

Related Questions