I am trying to create a keybinding to delete all the commented lines in the file.
The following gives me the desirable result :g/^\(#\|$\)/d
I am declaring the binding as following in ~/.vimrc
nnoremap <leader>dcl :g/\v^(#|$)/d<cr>
It is throwing the following error:
E492: Not an editor command: $)/d<cr>
What is the proper way to declare a keybinding with regex?
Replace your binding by:
nnoremap <leader>dcl :g/\v^(#<bar>$)/d<cr>
Indeed, in scripts or in the command line, vim considers | characters as a command delimiter; so you have to replace it by <bar>.
Related
The following substitute command works fine on the command line:
:s/\vlabel\{(\w|:)+}/nonumber
It searches for label{eq:xyz123} and replaces its occurence on the current line line with nonumber.
I would like to map this to a command via vimrc. I tried:
nnoremap <leader>nn :s/\vlabel\{(\w|:)+}/nonumber<CR>
but this gives the error:
E492: Not an editor command: :)+}/nonumber<CR>
What is the right way to effect this mapping?
You can use:
nnoremap <leader>nn :s/\vlabel\{(\w<bar>:)+}/nonumber<CR>
Note the use of <bar> instead of |. The error occurs because | is interpreted as a delimiter of commands; i.e., Vim is interpreting your command as if there were two separate lines:
nnoremap <leader>nn :s/\vlabel\{(\w
:)+}/nonumber<CR>
For more, you can read :help map-bar.
I am trying to have to custom commands in vim as follows:
The first command just runs a bash script. this works fine on its own.
:command Build :!./build-linux.sh
Now I want to use this command in another such as this:
:command BuildAndDebug :Build | :call vimspector#Launch()
This command is supposed to run the bash script and then launch a debugger.
When I try to do this, I get this error back:
E488: Trailing characters: :Build | :call vimspector#Launch()
I can't seem to find the trailing characters here. I suspect the :Build is the cause of this because it does not know where the command ends. However I can't seem to get it to work at all.
You need to add the -bar attribute to your command definition if you want to be able to "chain" other commands after it with |:
:command -bar Build :!./build-linux.sh
This is described in chapter 40 of the user manual: :help usr_40, and documented under :help :command-bar.
I am familiar with the = filter. == key sequence indents the current line, while gg=G indents the entire file. I am trying to create a command:FixIndentation to get a similar effect, to fix indentation in the entire file.
# vim documentation provides example to map to key
map <F7> gg=G<C-o><C-o>
# my attempt to map to a command fails
command ReIndent execute "gg=G"
:ReIndent
E492: Not an editor command: gg=G
add normal! to tell it to execute it in normal mode:
command ReIndent execute "normal! gg=G"
How do I map a substitution to a key in my .vimrc without getting an error when I source it?
I'm trying to add
nnoremap <leader>re :'<,'>s/<%=*\s//g | '<,'>s/\s-*%>//g
to my .vimrc but when I do so and reload the file I get the following error:
The problem is that you're combining two :s commands, but the command separator | concludes the :map command, so that the second substitution is executed immediately, causing the error. You need to escape the |, or better use the special <Bar> notation inside mappings:
nnoremap <leader>re :'<,'>s/<%=*\s//g <Bar> '<,'>s/\s-*%>//g
PS: Wouldn't it be more natural to define the mapping in visual mode (as it works on the last selection, anyway)? With a :vmap, the first '<,'> range will be inserted automatically:
xnoremap <leader>re :s/<%=*\s//g <Bar> '<,'>s/\s-*%>//g
I've written a few macros in my .vimrc for the version control system I'm using (Perforce) (please don't suggest the perforce plugin for vim, I tried it and I don't like it). They all work fine except the revert macro, which breaks due to a confirmation prompt (which I need so I don't accidentally fat-finger my changes away). It currently looks like this:
map <F8> :if confirm('Revert to original?', "&Yes\n&No", 1)==1 | !p4 revert <C-R>=expand("%:p")<CR><CR><CR>:edit<CR> | endif
This causes bash to complain when vim tries to load the file:
bin/bash: -c: line 0: syntax error near unexpected token `('
Looking at the buffer bash sees, it looks like the error is that vim sends it everything after the first pipe, not just the part meant for bash. I tried a few alternatives but I can't seem to make it work. I've got it to show confirm dialog correctly when I removed the pipes and endif (using shorthand if), but then vim complains after the user gives a response.
I think you want something along these lines:
:map <F8> :if confirm('Revert to original?', "&Yes\n&No", 1)==1 <Bar> exe "!p4 revert" . expand("%:p") <Bar> edit <Bar> endif<CR><CR>
Remember that :map is a dumb sequence of keystrokes: what you're mapping F8 to has to be a sequence of keystrokes that would work if typed. A <CR> in the middle of the :if statement doesn't mean ‘and press Enter when executing the command at this point if the condition is true’; it means ‘press Enter here when in the middle of typing in the :if command’, which obviously isn't what you want.
Building it up a piece at time, from the inside out:
There's a shell command you sometimes want to run.
That shell command needs to be inside an :if to do the ‘sometimes’ bit, and so have an :endif following it.
After a literal ! everything following is passed to the shell, including | characters which normally signify the start of another Vim command. That's reasonable, because | is a perfectly good character to use in shell commands. So we need some way of containing the shell command. :exe can do this; it executes the supplied string as a command — and its argument, being a string, has a defined end. So the general form is :if condition | exe "!shell command" | endif.
Your shell command has an expression in it. Using :exe makes this easy, since you can simply concatenate the string constant parts of the command with the result of the expression. So the command becomes :exe "!p4 revert" . expand("%:p") — try that out on its own on a file, and check it does what you want before going any further.
Putting that inside the condition gives you :if confirm('Revert to original?', "&Yes\n&No", 1)==1 | exe "!p4 revert" . expand("%:p") | edit | endif — again try that out before defining the mapping.
Once you have that working, define the mapping. A literal | does end a mapping and signify the start of the next Vim command. In your original the mapping definition only went to the end of the condition (check it with :map <F8> after loading a file) and the !p4 part was being run immediately, on the Vim file that defines the mapping! You need to change each | in your command into <Bar>, similarly to how each press of Enter in your command needs writing as <CR>. That gives you the mapping above. Try it by typing it at the command line first, then do :map <F8> again to check it's what you think it is. And only then try pressing F8.
If that works, put the mapping in your .vimrc.
Use of the pipe to string multiple vim commands together is not particularly well-defined, and there are numerous eccentricities. Critically, (see :help :bar) it can't be used after a command like the shell command :! which sees a | character as its argument.
You might find it easier to use the system() function.
E.G.
:echo system("p4 revert " . shellescape(expand("%:p")))
The shellescape() wrapper is useful in case you have characters like spaces or quotes in the filename (or have cleverly named it ; rm -rf ~ (Don't try this at home!)).
In the interest of creating more readable/maintainable code, you may want to move your code into a function:
function Revert()
if confirm('Revert to original?', "&Yes\n&No", 1)==1
return system("p4 revert " . shellescape(expand("%:p")))
endif
endfunction
which you would access by using the :call or :echo command in your macro.