I want to construct a command line within a mapping, using the :execute normal "commandstring" techinique. But I can't do it from within a mapping as vim immediately interprets the "" as a keypress. So this doesn't work:
nnoremap <leader>jj :execute "normal :tabnew foo.txt\<cr>"<cr>
I tried doubly escaping the backslash, to no effect:
nnoremap <leader>jj :execute "normal :tabnew foo.txt\\<cr>"<cr>
Now vim types in the backslash and then interprets the as a keypress.
Any way out of this?
That's indeed tricky. You have to escape the < character as <lt>, so that the <cr> is not parsed as special key notation:
nnoremap <leader>jj :execute "normal :tabnew foo.txt\<lt>cr>"<cr>
Note that your example doesn't need any of this; :normal :...<CR> is the same as ...
nnoremap <leader>jj :tabnew foo.txt<cr>
Related
I manually replace ^M with
:%s/<ctrl-v><ctrl-m>//g after I open a log file. I have to do this several times a day so I tried to assign F11 key to perform this action.
I tried the following in .vimrc but it did not work.
:nnoremap <silent> <F11> :let _s=#/ <Bar> :%s/^M//e <Bar> :let #/=_s <Bar> :nohl <Bar> :unlet _s <CR>
Note: I pressed ctrl+vctrl+m to get ^M in the above statement.
I have a similar assignment for F10 to remove EOL whitespace and that works.
:nnoremap <silent> <F10> :let _s=#/ <Bar> :%s/\s\+$//e <Bar> :let #/=_s <Bar> :nohl <Bar> :unlet _s <CR>
What am I doing wrong here?
Check that your terminal actually forwards F11 to the commands it’s running instead of listening to the key itself. For instance, the default configuration of Windows Terminal intercepts F11 and does not forward it, so you can’t rebind the key inside Vim.
Furthermore, your command looks quite convoluted; my Vimscript knowledge is limited but if the purpose of your command is to change Windows file endings into UNIX file endings, the following, simpler command works:
:nnoremap <silent> <F11> :set fileformat=unix<CR>
There’s also a widely installed utility program, dos2unix, that does the same, and which might be even simpler for your use-case.
In my vimrc I had a mapping to find all line with TODO in them and put them in the quickfix window:
nnoremap <leader>f :vimgrep /TODO/j % \| :cw<CR>
I now want to add the alternative pattern FIXME in the same way. So I tried
nnoremap <leader>f :vimgrep /TODO\|FIXME/j % \| :cw<CR>
and
nnoremap <leader>f :vimgrep /TODO<bar>FIXME/j % \| :cw<CR>
but neither return any results.
vimgrep /TODO|FIXME/j %
works at the : prompt when typed manually. So far my work-around is this:
function! FindFixme()
vimgrep /TODO\|FIXME/j %
cw
endfunction
nnoremap <leader>f :call FindFixme()<CR>
But I don't really understand why I can't get it to work as a single map command.
Thanks.
The regular expression item for alternation is \|, and you indeed need to escape a | so that it doesn't end the mapping command. Taken together, you need two backslashes: one for escaping and one to remain for the item:
nnoremap <leader>f :vimgrep /TODO\\|FIXME/j % \| :cw<CR>
But I would prefer the <Bar> notation, maybe even combined with <Bslash>:
nnoremap <leader>f :vimgrep /TODO<Bslash><Bar>FIXME/j % <Bar> :cw<CR>
You can further shorten this to:
nnoremap <leader>f :vimgrep /TODO<Bslash><Bar>FIXME/j %<Bar>cw<CR>
The naive approach
nnoremap <leader>s :!echo "foo" <bar> vim -c="nnoremap x :q<cr>" -<cr>
displays errors. Is there a way to achieve this?
Figured it out. There are two problems with my original code. The first being an equals sign after -c. For the other, the solution is to use <lt>cr> instead of <cr>. So the entire command would look like this:
nnoremap <leader>s :!echo "foo" <bar> vim -c "nnoremap x :q<lt>cr>" -<cr>
:help <lt>
I have a file type specific mapping for executing code in the current buffer.
For .pl files:
:nnoremap <buffer> <leader>r :!echo "OUTPUT:"; perl %<cr>
For .py files:
:nnoremap <buffer> <leader>r :!echo "OUTPUT:"; python %<cr>
As you can see, the {rhs} differs only in the interpreter name ('perl', 'python' etc). So, I wrote a function to generate it.
" Creates command-string to run code in buffer.
function! GenerateCmd(prg)
return ':!echo "OUTPUT:"; ' . a:prg . ' %<cr>'
endfunction
And this is where I got stuck. How do I set the {rhs} to be the string value returned by GenerateCmd()?
For example: :nnoremap <buffer> <leader>r =GenerateCmd('perl') doesn't create the same mapping as the one I hand-wrote for Perl above.
When the command is static (i.e. it doesn't need to be re-evaluated on every mapping invocation), you can use :execute, which allows to evaluate strings as Vimscript commands:
:execute 'nnoremap <buffer> <leader>r' GenerateCmd('perl')
The missing piece of the puzzle is :help map-expr, where the {rhs} is determined by a Vimscript expression:
:nnoremap <buffer> <expr> <leader>r GenerateCmd('perl')
Note that the expression must return actual keys, so instead of '...<cr>' use "...\<cr>" inside your function; within double quotes, you can use escaped special-key notation (which is easier than embedding an actual ^M).
I learned that using this:
let mapleader=','
if exists(":Tabularize")
nmap <Leader>a= :Tabularize /=<CR>
vmap <Leader>a= :Tabularize /=<CR>
endif
would give me a shortcut to tabularize with the '=' char. But I'd like to generalize it, so that I could use some shortcut like:
<Leader>a$
<Leader>a*
And it would read the '$' or '*' char and use it as the "char to tabularize". I.e., pass this char to the :Tabularize /CHAR function
Any ideas?
If you put that if block in your vimrc it will never work, because vimrc is sourced before any plugins, so the :Tabularize command doesn't exist yet when the expresion exists(':Tabularize') is evaluated and it will always be false.
You could use these mappings:
nnoremap <Leader>a :Tabularize /
vnoremap <Leader>a :Tabularize /
So when you press ,a* you'll be left in in command line mode with :Tabularize /*, ready to press Enter.