It's just a matter of escaping the pipe character correctly. For those unfamiliar, |
is a tricky cat due to its special role as the separator between different commands on the same line. We require careful application of the escape character, \
.
Jumping ahead, here's the correct mapping command when using "very-magic mode" (\v
):
nnoremap <C-I><C-S> :s/\v([^\|]+)\\|([^\|]+)/\2\|\1/<CR>
The least obvious part is the double escaping of the literal '|' between the two words.
To understand why we need that (and why the others need single-escaping) you need to know that right hand side of the mapping gets processed/parsed twice: once when we submit the nnoremap
command and once when we enter the mapped keys. The latter is familiar as it's the same as when we enter and run the substitution directly. It also has rules that differ from the general parsing applied to the map command which unfortunately makes this whole thing a bit non-intuitive as you'll see.
The other critical piece of information needed is that a round of parsing strips off one layer of escapes. (FYI this is not Vim specific it's a general thing you'll encounter almost anywhere you have to deal with escaped strings.)
Okay, we know what we'd enter if we ran the command directly...
s/\v([^|]+)\|([^|]+)/\2|\1/
Specifically, we escape the pipe in the pattern to indicate that it is the literal character and not the alternation operator/atom. But now we need another round of escaping and, as I alluded to before, the processing that will occur when nnoremap
is submitted is a general parse not the particular parsing that is done when we run a substitution. Thus, we need to escape every pipe character to prevent their interpretation as a command separator. In addition, we need to re-escape the literal pipe. Otherwise, the stripping of escapes that I mentioned will leave the literal pipe unescaped when the substitution occurs and it will be treated as an alternation atom. <Phew!>
So that give us this:
s/\v([^\|]+)\\|([^\|]+)/\2\|\1/
I don't blame you if you're saying "how the heck am I going to remember this". Fortunately, there's an easy way to see what happens after the first parse: leave off the <CR>
in your mapping. When you run it the result of the first parse will be on the command line waiting for you to hit Enter. You can examine it and correct things from there.