Como referenciar um dicionário local de script em um mapeamento do Vim?

3

De alguma forma, não consigo executar o mapeamento a seguir:

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

Eu achei que funciona da mesma maneira que com uma função local de script:

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

Também liberar s:Foobar de s:MySurroundingFunctionIWantToKeep() não ajuda, como:

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

Declarar a variável% script-local s:Foobar como variável global g:Foobar faz o truque.

    
por Tim Friske 16.12.2012 / 01:47

1 resposta

3

Não há como (que eu saiba) acessar diretamente as variáveis locais do script fora do contexto daquele script; <SID> só funciona para funções (e somente em mapeamentos).

Você pode fornecer acesso indireto por meio de uma função:

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

Dependendo de quão isolado você deseja manter a variável, você poderia tornar a função de “acessador” mais restritiva (permitir somente certas chaves, permitir somente o acesso de leitura, permitir somente gravações em certas chaves, 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  :echo <sid>FoobarAccess('foo')<cr>
map  :echo <sid>FoobarAccess('foo','new value')<cr>
map  :echo <sid>FoobarAccess('baz')<cr>
map  :echo <sid>FoobarAccess('baz',1)<cr>
    
por 16.12.2012 / 05:41