Ho lavorato sulla modularizzazione e la conversione di un codice nel mio vimrc
in alcuni plugin / plugin plug-in autonomi e riutilizzabili. Ho riscontrato un problema con il caricamento automatico e l'ambito che ho difficoltà a comprendere. Ho letto attraverso :h autoload
, :h <sid>
, :h script-local
, ma io non sono ancora del tutto chiaro su come funziona.
Ho cercato alcuni plugin ben sviluppati per capire alcuni schemi comunemente usati e ho strutturato i miei plugin come segue:
" ~/.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
All'inizio del mio vimrc, eseguo il plugin con:
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
Tutto questo sembra funzionare correttamente e come previsto - ma ogni volta che viene chiamata una funzione, la s:set_default(...)
funzione viene chiamata per ogni flag, il che è inefficace - quindi ho tentato di spostarli fuori dalle funzioni:
" ~/.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() " {{{
" ...
Ma questo causa errori che non sono sicuro di come dovrei risolvere:
Error detected while processing /Users/nfarrar/.vim/myplugin.vim
line 40:
E117: Unknown function: <SNR>3_set_default
Ancora non capisco perfettamente l'ambito di Vim, ma da quello che ho letto - sembra che Vim implementa una forma di modifica del nome con script per fornire 'ambito'. Assegna (non sono sicuro di come funzioni esattamente questo processo) un SID univoco per ciascun file che viene caricato in fase di esecuzione - e quando chiamate una funzione che ha il prefisso con un identificatore dell'ambito dello script ( s:
), sostituisce in modo trasparente quell'identificatore con un SID mappato .
In alcuni casi, ho visto degli script che chiamano funzioni come questa (ma non funziona nel mio caso, non capisco perché, e spero che qualcuno possa spiegarlo):
call <SID>set_default('g:myplugin_thing_one_flag', 1)
call <SNR>set_default('g:myplugin_thing_one_flag', 1)
Quanto segue funziona, ma non sono sicuro che sia un buon modello:
" ~/.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 " }}}
Nello script locale, afferma:
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
Vede in questo modo potrebbe essere l'approccio che devo adottare, ma non sono completamente sicuro del perché, o esattamente come usarlo. Qualcuno può fornire alcune informazioni?
echom 'this is the function call'
nella funzione chiamata da vimrc e un'altra inechom 'file was sourced'
qualsiasi altra parte del file (non in una funzione), vedo prima la seconda, poi la prima.