Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

Somehow I'm not able to execute the following mapping:

function! s:MySurroundingFunctionIWantToKeep()
  let s:Foobar={'foo': 'bar'}
  map \42 :echo <sid>Foobar.foo<cr>
endfunction
call s:MySurroundingFunctionIWantToKeep()

I thought it works the same way as it does with a script-local function:

function! s:MySurroundingFunctionIWantToKeep()
  function! s:Foobar()
    echo 'bar'
  endfunction
  map \42 :call <sid>Foobar()<cr>
endfunction
call s:MySurroundingFunctionIWantToKeep()

Also freeing s:Foobar from s:MySurroundingFunctionIWantToKeep() doesn't help, like:

let s:Foobar={'foo': 'bar'}
map \42 :echo <sid>Foobar.foo<cr>

Declaring the s:Foobar script-local variable as g:Foobar global variable does the trick.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

There is no way (that I know of) to directly access script-local variables outside the context of that script; <SID> only works for functions (and only in mappings).

You could provide indirect access through a function, though:

function! s:FoobarHash()
  return s:Foobar
endfunction
function! s:MySurroundingFunctionIWantToKeep()
  let s:Foobar={'foo': 'bar'}
  map \42 :echo <sid>FoobarHash()['foo']<cr>
endfunction
call s:MySurroundingFunctionIWantToKeep()

Depending on how isolated you want to keep the variable, you could make the “accessor” function more restrictive (only allow certain keys, only allow read access, only allow writes to certain keys, etc).

let s:Foobar={'foo': 'bar', 'baz': 'quux'}
function! s:FoobarAccess(...)
  " Provide limited access to the script-local hash s:Foobar

  if a:0 == 1
    " allow read access to all keys
    return s:Foobar[a:1]

  elseif a:0 == 2
    " allow write access to only 'foo'
    if a:1 !=# 'foo'
      throw 'FoobarAccess: not allowed to write to key ' . a:1
    endif
    let old = s:Foobar[a:1]
    let s:Foobar[a:1] = a:2
    return old

  else
    throw 'FoobarAccess must take exactly one or two arguments'
  endif
endfunction


map \42 :echo <sid>FoobarAccess('foo')<cr>
map \43 :echo <sid>FoobarAccess('foo','new value')<cr>
map \44 :echo <sid>FoobarAccess('baz')<cr>
map \45 :echo <sid>FoobarAccess('baz',1)<cr>
share|improve this answer
    
It's a pity. I actually try to make a dictionary's functions eligible for mappings, i.e. expose the object's behaviour much like I would do with a script-local function object. Also I can't see a problem why Vim would prevent such an access pattern. –  Tim Friske Dec 16 '12 at 9:21

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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