14

I have two question about understand those vim script. please give some help,

Question 1: I download a.vim plugin, and i try to read this plugin, how to understand the below variable definition? the first line I can understand, but the second line, I don't know exactly "g:alternateExtensions_{'aspx.cs'}" means.

" E.g. let g:alternateExtensions_CPP = "inc,h,H,HPP,hpp" " let g:alternateExtensions_{'aspx.cs'} = "aspx" 

Question 2: how to understand "SID" before the function name, using like below function definition and function call.

function! <SID>AddAlternateExtensionMapping(extension, alternates) //omit define body call <SID>AddAlternateExtensionMapping('h',"c,cpp,cxx,cc,CC") call <SID>AddAlternateExtensionMapping('H',"C,CPP,CXX,CC") 

thanks for you kindly help.

1
  • 1
    I know it's already been answered, but I think it should be better if we have two questions for this? Commented Mar 13, 2020 at 10:31

2 Answers 2

31
let g:alternateExtensions_{'aspx.cs'} = "aspx" 

That is an inline expansion of a Vimscript expression into a variable name, a rather obscure feature that is rarely used since Vim version 7. See :help curly-braces-names for details. It is usually used to interpolate a variable, not a string literal like here ('aspx.cs'). Furthermore, this here yields an error, because periods are forbidden in variable names. Newer plugins would use a List or Dictionary variable, but those data types weren't available when a.vim was written.


To avoid polluting the function namespace, plugin-internal functions should be script-local, i.e. have the prefix s:. To invoke these from a mapping, the special <SID> prefix has to be used instead of s:, because <SID> internally gets translated into something that keeps the script's ID, whereas the pure s:, when executed as part of the mapping, has lost its association to the script that defined it.

Some plugin authors don't fully understand this unfortunate and accidental complexity of Vim's scoping implementation either, and they put the <SID> prefix also in front of the function name (which works, too). Though it's slightly more correct and recommended to write it like this:

" Define and invoke script-local function. function! s:AddAlternateExtensionMapping(extension, alternates) ... call s:AddAlternateExtensionMapping('h',"c,cpp,cxx,cc,CC") " Only in a mapping, the special <SID> prefix is actually necessary. nmap <Leader>a :call <SID>AddAlternateExtensionMapping('h',"c,cpp,cxx,cc,CC") 
Sign up to request clarification or add additional context in comments.

3 Comments

Hi Ingo, thanks for your answer, very informative as always. Do you have any suggestions or alternative to the A.vim plugin?
Thanks for the informative answer to both questions. I'm guessing <SID> is literally typed in, there's no keystroke sequence to write that in vim?
@icedwater: Yes, you type <SID> as five separate characters. Inside Vim, this then becomes translated to another (unique to the script) character sequence (which contains something that is written and echoed as <SNR>, but in fact is a special sequence).
11

<SID> is explained in :help <SID>:

When defining a function in a script, "s:" can be prepended to the name to make it local to the script. But when a mapping is executed from outside of the script, it doesn't know in which script the function was defined. To avoid this problem, use "<SID>" instead of "s:". The same translation is done as for mappings. This makes it possible to define a call to the function in a mapping. When a local function is executed, it runs in the context of the script it was defined in. This means that new functions and mappings it defines can also use "s:" or "<SID>" and it will use the same unique number as when the function itself was defined. Also, the "s:var" local script variables can be used. 

That number is the one you see on the left when you do :scriptnames, IIRC.

7 Comments

I didn't upvote this, as it only answers half the question.
And the question was really two questions.
I know, you make a fair point, but the other answer attempted both.
@icedwater the question is not properly designed. It must be separated on two different questions. So answers that relates only to one of the questions are absolutely normal.
Yup, I'll upvote this if I find it after it has been split. Either way, I don't think the OP is going to come back and split this... I wonder if there is a standard way to edit and split such questions into two?
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.