3

I want to create a function for a mapping. The key for the mapping is configured through a variable. How can I escape the key in the return statement so it works? This works:

let g:some_key = "<Up>"
function! <SID>TestFun()
  " doing something
  return "\<Up>"
endfunction
noremap <expr> g:some_key <SID>TestFun()

But I want something likes this

let g:some_key = "<Up>"
function! <SID>TestFun()
  " doing something
  return "\".g:some_key
endfunction
noremap <expr> g:some_key <SID>TestFun()

Right now my solution was creating a new variable holding the escaped key like this

exec 'let s:escaped_key = "\'.g:some_key.'"'

but I'm there's a better way to do it.

EDIT: The method I'm looking for should also work for a function called using <C-R>=<SID>SomeFunction()<CR> in a imap

  • I don't know if it will work, but have you tried the fnameescape() function ? If I store "<Up>" inside the g:some_key variable then type : echo fnameescape(g:some_key), the output is "\<Up>". – saginaw Nov 30 '15 at 22:43
  • Didn't think about that! It works in the specific case I asked about, but I forgot to mention that I also need it to work for function called using <C-R>=<SID>SomeFunction()<CR> in imap (and in this case fnameescape() doesn't work. Edited the question accordingly. Thank you for your help – Enrico Ghirardi Nov 30 '15 at 23:13
3

All problems in computer science can be solved by another level of indirection except for the problem of too many layers of indirection.

-Kevlin Henney

Use a <Plug> (or <SID>) mapping to g:some_key. Use this new mapping in your function instead of g:some_key.

let g:some_key = '<Up>'
execute 'nnoremap <Plug>(some-key) ' . g:some_key

function! s:TestFun()
  " doing something
  return "\<Plug>(some-key)"
endfunction
execute 'nmap <expr> ' . g:some_key . ' <SID>TestFun()'

There are a few things worth noting:

  • Using nmap instead of nnoremap so that we can map <Plug>
  • Using double quoted string and escaping the key notation. e.g. "\<Plug>.."
  • You can use <SID> mapping instead and use <script> if you want to emulate nnoremap. See :h <SID> and :h :map-script for more information.

For more help see:

:h :execute
:h <Plug>
:h <SID>
:h :map-script
:h key-notation
:h expr-string
:h literal-string
  • Hey, thanks for the answer, really informative. It helped me correct a good part of the current design of the script. But this approach still doesn't work for value returned by <C-R>= expression I have to call feedkeys("\<Plug>(some-key)") if I want it to work. – Enrico Ghirardi Dec 1 '15 at 22:53
  • @EnricoGhirardi Using <c-r>= is a bit more tricky however you can use eval() to create a properly quoted string. e.g. eval('"'.substitute(g:some_key, '<', '\\&', 'g').'"'). I usually avoid eval() (feedkeys() too), so use at your own risk. If you are able, I would suggest you use an <expr> mapping instead of <c-r>= for your imap's. – Peter Rincker Dec 2 '15 at 1:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.