私は自分のコードをモジュール化してvimrc
、いくつかの自己完結型で再利用可能なバンドル/プラグインプラグインに変換する作業を行っています。理解できないオートロードとスコープの問題に遭遇しました。私はを読みました:h autoload
、:h <sid>
、:h script-local
、私はどのようにこの作品にはまだ非常に明確ではありませんよ。
私はいくつかのよく開発されたプラグインを調べて、一般的に使用されるパターンを理解し、プラグインを次のように構成しました。
" ~/.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
vimrcの開始時に、次のコマンドでプラグインを実行します。
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
これはすべて正しく期待どおりに機能しているように見えますが、s:set_default(...)
関数が呼び出されるたびに、関数は各フラグに対して呼び出されるため、非効率的です。そのため、関数からそれらを移動しようとしました。
" ~/.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() " {{{
" ...
しかし、これは私がどのように解決すべきかわからないエラーを引き起こします:
Error detected while processing /Users/nfarrar/.vim/myplugin.vim
line 40:
E117: Unknown function: <SNR>3_set_default
私はまだvimのスコープをしっかりと理解していませんが、私が読んだことから-vimは 'スコープ'を提供するためにスクリプトを使用して名前マングルの形式を実装しているようです。実行時に読み込まれる各ファイルに一意のSIDを割り当てます(このプロセスがどのように機能するかは不明ですs:
)。スクリプトスコープの識別子()が前に付いている関数を呼び出すと、その識別子がマップされたSIDに透過的に置き換えられます。 。
場合によっては、次のような関数を呼び出すスクリプトを見たことがあります(ただし、私の場合は機能しません。理由がわかりません。誰かがこれを説明できるといいのですが)。
call <SID>set_default('g:myplugin_thing_one_flag', 1)
call <SNR>set_default('g:myplugin_thing_one_flag', 1)
以下は機能しますが、それが良いパターンであるかどうかはわかりません:
" ~/.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 " }}}
ローカルスクリプトでは、次のように述べています。
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
これは私が取るべきアプローチかもしれないように見えますが、私はその理由、または正確にそれを使用する方法を完全に確信していません。誰かが洞察を提供できますか?
echom 'this is the function call'
vimrcから呼び出されている関数にステートメントを追加echom 'file was sourced'
し、ファイル内の他の場所(関数ではない)にステートメントを追加すると、最初に後者が表示され、次に前者が表示されます。