Home > Software design >  escaping backslash in .vimrc to have a :map working with grep and \s
escaping backslash in .vimrc to have a :map working with grep and \s

Time:03-21

On my .vimrc I use this:

:map ,p :!clear; grep -E "def \|class " %

to map ,p to the grep that provide Python def and class hierarchy, it work very well.

I try with no success to do the same to get some vuejs structure.

I get what I need on Bash with this is grep:

$ grep -E '^\s \S : {|\() {$|<script>|import' /tmp/somevuejs.vue

But when I try to put it on .vimrc:

:map ,j :!clear; grep -E '^\s \S : {|\() {$|<script>|import' %

I get this error:

$ vim file.txt
Error detected while processing /home/me/.vimrc:
line   20:
E10: \ should be followed by /, ? or &

I've try multiples escapes combinatoric with no success, neither of this worked:

:map ,j :!clear; grep -E '^//\s //\S : {|\() {$|<script>|import' %
:map ,j :!clear; grep -E "^//\s //\S : {|\() {$|<script>|import" %

CodePudding user response:

:help map-bar says that you can't use a | in a mapping unless you escape it somehow.

Your existing mapping "works" because its | is properly escaped:

:map ,p :!clear; grep -E "def \|class " %
                              ^^

Your new mapping doesn't work because its many |s are not escaped:

:map ,j :!clear; grep -E '^\s \S : {|\() {$|<script>|import' %
                                    ^      ^        ^

The exact error reported by Vim is caused by this construct:

{|\(

The | is considered by Vim as a separator between two Vim commands, so you get one Vim command:

:!clear; grep -E '^\s \S : {

(that executes a borked external command anyway), followed by a second one:

:\() {$|<script>|import' %

which doesn't really make sense. It's the \ that causes the error. If you escape that first | you will get a different error caused by the second |, and then another one caused by the third |.

Escape those |s to make your mapping "work":

:map ,j :!clear; grep -E '^\s \S : {\|\() {$\|<script>\|import' %
                                    ^^      ^^        ^^

I put "work" in quotes because those mappings are super clunky.

  1. They need a <CR> at the end so that you don't have to press Enter to execute the command:

    :map ,p :!clear; grep -E "def \|class " %<CR>
    :map ,j :!clear; grep -E '^\s \S : {\|\() {$\|<script>\|import' %<CR>
    
  2. They should be restricted to normal mode, unless you really want them to be defined for visual, select, and operator-pending modes, too:

    :nmap ,p :!clear; grep -E "def \|class " %<CR>
    :nmap ,j :!clear; grep -E '^\s \S : {\|\() {$\|<script>\|import' %<CR>
    
  3. Since you don't seem to be purposely using another mapping in your mappings, it is best to make them non-recursive:

    :nnoremap ,p :!clear; grep -E "def \|class " %<CR>
    :nnoremap ,j :!clear; grep -E '^\s \S : {\|\() {$\|<script>\|import' %<CR>
    
  4. And, since you are in a script, you can safely remove the colon:

    nnoremap ,p :!clear; grep -E "def \|class " %<CR>
    nnoremap ,j :!clear; grep -E '^\s \S : {\|\() {$\|<script>\|import' %<CR>
    

That's a lot cleaner!

Now, I guess we will keep the next mystery, namely why you use an external tool for that instead of :help :global, for the comments… or for another question.

  • Related