1

After reading help I've started experimenting with a kind of a weird type of mappings — ones that are strings to be emitted and captured and not entered by user. So inside a script I've created:

nnoremap <SID>MyMapping :echom "Hi!"<CR>

I'm however puzzled to what purpose utilize such mapping and how to run it. I've tried with norm <SID>MyMapping from the same script or from the script's function, with no effects. feedkeys(), expand("<SID>") in place of <SID> didn't help.

How to run such mapping? What can they be used for?

Update: As one of the answers revealed it turns out that the key is \<SNR>. Example:

function! RunIt()
  echom "1: normal ".expand("<SID>")."MyMapping"
  echom "2: normal \<SNR>".s:SID()."_MyMapping"
endfunction

The output:

1: normal <SNR>253_MyMapping
2: normal <80><fd>R253_MyMapping

The second one works when echom is replaced with exe, the first one doesn't.

0

1 Answer 1

2

It's fairly difficult to trigger such a mapping.

The problem with norm <SID>MyMapping is that the :normal command doesn't really recognize <...> sequences, so it ends up executing the <, S, I, D, >, etc. keystrokes literally. The sequence <S fails because S is not a valid motion or text object, so the whole sequence ends up doing nothing.

In order to recognize <...> sequences, you need :execute and a double quoted string, such as exe "norm \<SID>My mapping", but here again it will not work because Vim will not replace <SID> in this situation...

Normally, when Vim finds <SID> used anywhere in a script file, it will replace it with something like <SNR>42_, where the 42 number is unique to this source file. That's the magic that makes <SID> work to implement "local" functions, because two script files defining functions with the same name will end up with separate unique numbers and the functions won't clash.

But this replacement will not happen automatically in this situation... So you'll have to do it manually, by detecting which number was used for this specific source file.

:help <SID> suggests a way to find out the specific number for the current source file, by matching the expansion of <sfile> looking for the <SNR> sequence.

Putting it all together, you can call this mapping from a function defined in the same source file with:

nnoremap <SID>MyMapping :echom "Hi!"<CR>

function! s:SID()
  return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfunction

function! RunIt()
  execute "normal \<SNR>".s:SID()."_MyMapping"
endfunction

What can they be used for?

I can't come up with any useful way to employ these mappings. The <SID> mechanism is meant for functions, avoiding name clash with other scripts.

Mappings are useful when they're public and global, so it's no surprise that <SID> doesn't really serve a meaningful purpose here...

4
  • 1
    You don't need s:SID() anymore. Starting from 8.2.1347, you can just write expand('<SID>'). For the purpose of <SID>, see :h :map-script.
    – user938271
    Commented Sep 10, 2020 at 0:48
  • @user938271 Wow glad to know! I happened to test this on a build running 8.2.0209... I guess it's past time to upgrade! 😁
    – filbranden
    Commented Sep 10, 2020 at 0:58
  • 1
    Thanks, it works. I've updated the question to pin point what I've done differently.
    – Mooncer
    Commented Sep 10, 2020 at 1:33
  • @user938271 Only thing is expand('<SID>') returns '<SNR>42_' (with a literal "<SNR>") instead of "\<SNR>42_", so it would also need some post-processing here, for this particular use case. That's understandable, since expand('<SID>') is meant to be used on mappings and other contexts that would expand <...> sequences by themselves...
    – filbranden
    Commented Sep 10, 2020 at 11:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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