He estado trabajando en modularizar y convertir un código en mi vimrc
en algunos paquetes / complementos reutilizables y autónomos. Me he encontrado con un problema con la carga automática y el alcance que tengo dificultades para comprender. He leído a través de :h autoload
, :h <sid>
, :h script-local
, pero todavía no estoy muy claro sobre cómo funciona este.
He estado buscando algunos complementos bien desarrollados para descubrir algunos patrones comúnmente utilizados, y he estructurado mis complementos de la siguiente manera:
" ~/.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
Al comienzo de mi vimrc, ejecuto el complemento 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
Todo esto parece funcionar correctamente y como se esperaba, pero cada vez que se llama a una función, se llama a la s:set_default(...)
función para cada indicador, lo cual es ineficaz, así que intenté moverlas fuera de las funciones:
" ~/.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() " {{{
" ...
Pero esto causa errores que no estoy seguro de cómo debería resolver:
Error detected while processing /Users/nfarrar/.vim/myplugin.vim
line 40:
E117: Unknown function: <SNR>3_set_default
Todavía no entiendo sólidamente el alcance de vim, pero por lo que he leído, parece que vim implementa una forma de manipulación de nombres con scripts para proporcionar 'alcance'. Asigna (no estoy seguro de cómo funciona exactamente este proceso) un SID único para cada archivo que se carga en tiempo de ejecución, y cuando llama a una función que tiene el prefijo con un identificador de alcance de script ( s:
), reemplaza ese identificador de forma transparente con un SID asignado .
En algunos casos, he visto scripts que llaman a funciones como esta (pero no funciona en mi caso, no entiendo por qué y espero que alguien pueda explicar esto):
call <SID>set_default('g:myplugin_thing_one_flag', 1)
call <SNR>set_default('g:myplugin_thing_one_flag', 1)
Lo siguiente funciona, pero no estoy seguro si es un buen patrón:
" ~/.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 " }}}
En script local, dice:
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
Parece que este podría ser el enfoque que debo adoptar, pero no estoy completamente seguro de por qué, o exactamente cómo usarlo. ¿Alguien puede dar alguna idea?
echom 'this is the function call'
en la función que se llama desde vimrc y otro enechom 'file was sourced'
cualquier otro lugar del archivo (no en una función), veo el último primero, luego el primero.