J'ai travaillé sur la modularisation et la conversion d'un code dans mon vimrc
en quelques bundles / plugins autonomes et réutilisables. J'ai rencontré un problème avec le chargement automatique et la portée que j'ai du mal à comprendre. Je l' ai lu :h autoload
, :h <sid>
, :h script-local
, mais je ne suis pas encore tout à fait clair sur la façon dont cela fonctionne.
J'ai regardé des plugins bien développés pour comprendre certains modèles couramment utilisés et j'ai structuré mes plugins comme suit:
" ~/.vim/autoload/myplugin.vim
if exists('g:loaded_myplugin')
finish
endif
let g:loaded_myplugin = 1
let g:myplugin_version = 0.0.1
" Save cpoptions.
let s:cpo_save = &cpo
set cpo&vim
function! myplugin#init() " {{{
" Default 'init' function. This will run the others with default values,
" but the intent is that they can be called individually if not all are
" desired.
call myplugin#init_thing_one()
call myplugin#init_thing_two()
endfunction" }}}
function! myplugin#init_thing_one() " {{{
" init thing one
call s:set_default('g:myplugin_thing_one_flag', 1)
" do some things ...
endfunction " }}}
function! myplugin#init_thing_two() " {{{
" init thing two
call s:set_default('g:myplugin_thing_two_flag', 1)
" do some things ...
endfunction " }}}
function! s:set_default(name, default) " {{{
" Helper function for setting default values.
if !exists(a:name)
let {a:name} = a:default
endif
endfunction " }}}
" Restore cpotions.
let &cpo = s:cpo_save
unlet s:cpo_save
Au début de mon vimrc, j'exécute le plugin avec:
if has('vim_starting')
if &compatible | set nocompatible | endif
let g:myplugin_thing_one_flag = 0
let g:myplugin_thing_two_flag = 2
call myplugin#init()
endif
Tout cela semble fonctionner correctement et comme prévu - mais chaque fois qu'une fonction est appelée, la s:set_default(...)
fonction est appelée pour chaque indicateur, ce qui est inefficace - j'ai donc tenté de les déplacer hors des fonctions:
" ~/.vim/autoload/myplugin.vim
" ...
set cpo&vim
" Set all defaults once, the first time this plugin is referenced:
call s:set_default('g:myplugin_thing_one_flag', 1)
call s:set_default('g:myplugin_thing_two_flag', 1)
function! myplugin#init() " {{{
" ...
Mais cela provoque des erreurs que je ne sais pas comment résoudre:
Error detected while processing /Users/nfarrar/.vim/myplugin.vim
line 40:
E117: Unknown function: <SNR>3_set_default
Je ne comprends toujours pas bien la portée de vim, mais d'après ce que j'ai lu - il semble que vim implémente une forme de manipulation de nom avec des scripts pour fournir une «portée». Il attribue (pas sûr de savoir comment fonctionne exactement ce processus) un SID unique pour chaque fichier qui est chargé au moment de l'exécution - et lorsque vous appelez une fonction qui est préfixée avec un identificateur de portée de script ( s:
), il remplace de manière transparente cet identifiant par un SID mappé .
Dans certains cas, j'ai vu des scripts qui appellent des fonctions comme celle-ci (mais cela ne fonctionne pas dans mon cas, je ne comprends pas pourquoi, et j'espère que quelqu'un peut expliquer cela):
call <SID>set_default('g:myplugin_thing_one_flag', 1)
call <SNR>set_default('g:myplugin_thing_one_flag', 1)
Ce qui suit fonctionne, mais je ne sais pas si c'est un bon modèle:
" ~/.vim/autoload/myplugin.vim
" ...
set cpo&vim
" Set all defaults once, the first time this plugin is referenced:
call myplugin#set_default('g:myplugin_thing_one_flag', 1)
call myplugin#set_default('g:myplugin_thing_two_flag', 1)
function! myplugin#init() " {{{
" ...
function! myplugin#set_default(name, default) " {{{
" ...
endfunction " }}}
Dans le script local, il indique:
When executing an autocommand or a user command, it will run in the context of
the script it was defined in. This makes it possible that the command calls a
local function or uses a local mapping.
Otherwise, using "<SID>" outside of a script context is an error.
If you need to get the script number to use in a complicated script, you can
use this function:
function s:SID()
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_SID$')
endfun
Il voit que cela pourrait être l'approche que je dois adopter, mais je ne sais pas vraiment pourquoi, ni exactement comment l'utiliser. Quelqu'un peut-il donner un aperçu?
echom 'this is the function call'
dans la fonction appelée depuis vimrc et une autreechom 'file was sourced'
n'importe où ailleurs dans le fichier (pas dans une fonction), je vois la dernière en premier, puis la première.