Vim.ScriptLocal: Add ScriptLocal (get script-local things) #258

Merged
merged 1 commit into from Mar 1, 2015

Projects

None yet

5 participants

@haya14busa
Member

概要

path から <SID> を取得したり, script-local な関数を取得したオブジェクト(sfuncs) を取得できるモジュールです.
外部モジュールとして実装していた vital-snoop (https://github.com/haya14busa/vital-snoop.vim) が vital 本家にもあると便利という想いによりテストやドキュメントを vital に合わせて移植しました.

実装した関数は4つで

  1. sid({path}): {path}から<SID>を返す 
  2. sfuncs({path}): {path}からそのpathのscript-local関数を持つオブジェクトを返す
  3. sid2sfucs(<SID>): <SID>からscript-local関数を持つオブジェクトを返す
  4. scriptnames(): <SID>をキー, pathを値とした辞書を返す. (あとで知りましたが :h scriptnames-dictionaryと同内容です)

{path}については絶対パスと, &runtimepathから見ての相対パスを渡すことができます.

要するに以下のようなことができます.

let s:V = vital#of('vital')
let s:S = s:V.import('Vim.ScriptLocal')

"" Get <SID> with relative path to &runtimepath
" e.g. starts with autoload/, plugin/, etc...
" (autoload/**/*.vim, plugin/**/*.vim)
:echo s:S.sid('autoload/vital/test/Vim/ScriptLocal/test.vim')
" => <SID>
"" Get the dict which contains script local functions with absolute
" path
:let bundle = '~/.vim/bundle/'
:let p = 'vital.vim/autoload/vital/test/Vim/ScriptLocal/test.vim'
:let absolute_path = bundle . p
:let sf = s:S.sfuncs(absolute_path)
:echo sf
" =>
"  {
"   'double': function('<SNR>439_double'),
"   '_power': function('<SNR>439__power')
"  }
:echo sf.double(3) | " => 6
:echo sf._power(3) | " => 9
vital.vim/autoload/vital/test/Vim/ScriptLocal/test.vim
function! s:double(x) abort
    return a:x * 2
endfunction

function! s:_power(x) abort
    return a:x * a:x
endfunction

名前について

外部モジュールはSnoopという名前にしていましたが, 本PRではScriptLocalにしました.
少し長い気もするのでより良さげな名前があれば教えて欲しいです!

その他

a) テストでautoloadファイル以下や.themisrcを汚してる
autoloadファイルの読み込みなどをテストするため, テスト用のファイルがautoload/以下に置かれてます.
まずい気もしますがどうでしょう... test/ 以下におくとテストとして実行されてしまうので別のディレクトリに置いとくとかはありかなと思いました.

b) Windows におけるシンボリックリンクのテスト

ちょっとやり方がわからないのでスキップしてます. いい感じのやり方思いつく方教えてください...
シンボリックリンク以外のテストが通ることは確認しました. https://ci.appveyor.com/project/haya14busa/vital-snoop-vim

c) script-local変数も取得したい?
https://gist.github.com/haya14busa/cb78147229dfde98a5e6
script-local 変数をpathから無理やり取得する闇の関数も実装してみたのですが, 安全じゃないことを
明示した上で, vitalに含めるという選択肢もありますかね?

テストとかで使いたいという需要が多数あればワンチャン🐶あるかも? (基本的にはなしかなと思いますが)

@ujihisa
Member
ujihisa commented Feb 15, 2015

🍣👍

@rhysd rhysd and 1 other commented on an outdated diff Feb 15, 2015
autoload/vital/test/Vim/ScriptLocal/test.vim
@@ -0,0 +1,7 @@
+function! s:double(x) abort
+ return a:x * 2
+endfunction
+
+function! s:_power(x) abort
@rhysd
rhysd Feb 15, 2015 Member

細かいですが,power よりも square 感あります.

@haya14busa
haya14busa Feb 15, 2015 Member

あ...なんか違和感あると思ったらそうでしたっ(ハズカシサ) 💦

@rhysd rhysd commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
@@ -0,0 +1,97 @@
+*vital-vim-script_local.txt* Get script-local things
+
+Maintainer: haya14busa <hayabusa1419@gmail.com>
+
+==============================================================================
+CONTENTS *Vital.Vim.ScriptLocal-contents*
+
+ INTRODUCTION |Vital.Vim.ScriptLocal-introduction|
+ INTERFACE |Vital.Vim.ScriptLocal-interface|
+ Functions |Vital.Vim.ScriptLocal-functions|
+
+==============================================================================
+INTRODUCTION *Vital.Vim.ScriptLocal-introduction*
+
+ *Vital.Vim.ScriptLocal* provides a way to Get script local things.
@rhysd
rhysd Feb 15, 2015 Member

Get が大文字なのって何か意図がありますか?

@rhysd rhysd commented on the diff Feb 15, 2015
doc/vital-vim-script_local.txt
+==============================================================================
+CONTENTS *Vital.Vim.ScriptLocal-contents*
+
+ INTRODUCTION |Vital.Vim.ScriptLocal-introduction|
+ INTERFACE |Vital.Vim.ScriptLocal-interface|
+ Functions |Vital.Vim.ScriptLocal-functions|
+
+==============================================================================
+INTRODUCTION *Vital.Vim.ScriptLocal-introduction*
+
+ *Vital.Vim.ScriptLocal* provides a way to Get script local things.
+>
+ let s:V = vital#of('vital')
+ let s:S = s:V.import('Vim.ScriptLocal')
+>
+ "" Get <SID> with relative path to &runtimepath
@rhysd
rhysd Feb 15, 2015 Member

好みかもしれないのですが,サンプルコードはシンタックスハイライトされないので適宜空行入れたほうが見やすいのではないでしょうか.

@haya14busa
haya14busa Feb 15, 2015 Member

ちょっとだけ入れました(加減がわからずホントにちょっとになってしまった)

@rhysd
rhysd Feb 15, 2015 Member

ありがとうございます.僕的には見やすくなりました.

@rhysd rhysd commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
+INTERFACE *Vital.Vim.ScriptLocal-interface*
+------------------------------------------------------------------------------
+FUNCTIONS *Vital.Vim.ScriptLocal-functions*
+
+sid({path}) *Vital.Vim.ScriptLocal.sid()*
+ Returns <SID> with given path. {path} could be relative to
+ 'runtimepath' or absolute path.
+
+ *Vital.Vim.ScriptLocal-path*
+ {path} example
+ 1. /home/haya14busa/.vim/bundle/incsearch.vim/autoload/incsearch.vim
+ 2. ~/.vim/bundle/incsearch.vim/autoload/incsearch.vim
+ 3. autoload/incsearch.vim
+ 4. plugin/incsearch.vim
+
+ You can pass paths which starts with autoload/, plugin/, etc... as a
@rhysd
rhysd Feb 15, 2015 Member

starts -> start

@rhysd rhysd commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
+ " {
+ " 'double': function('<SNR>439_double'),
+ " '_power': function('<SNR>439__power')
+ " }
+ :echo sf.double(3) | " => 6
+ :echo sf._power(3) | " => 9
+
+sid2sfuncs(<SID>) *Vital.Vim.ScriptLocal.sid2sfuncs()*
+ Returns a dict which contains |script-local| functions with <SID>.
+>
+ :echo s:S.sid2sfuncs(1)
+ " => { 'fname1': funcref1, 'fname2': funcref2, ...}
+ " The file whose SID is 1 may be your vimrc
+
+scriptnames() *Vital.Vim.ScriptLocal.scriptnames()*
+ Returns a dict of |:scriptnames|. The keys is <SID> and the values is
@rhysd
rhysd Feb 15, 2015 Member

is -> are

@rhysd rhysd and 1 other commented on an outdated diff Feb 15, 2015
test/Vim/ScriptLocal.vimspec
@@ -0,0 +1,116 @@
+Describe Vim.ScriptLocal
+
+ Before all
+ let V = vital#of('vital')
+ let P = V.import('Prelude')
+ let S = V.import('Vim.ScriptLocal')
+ End
+
+ Context .sid()
+ It returns SID with relative path to &runtimepath
+ let sid = S.sid('autoload/vital/test/Vim/ScriptLocal/test.vim')
+ Assert IsNumber(sid)
+ Assert NotEquals(sid, -1)
@rhysd
rhysd Feb 15, 2015 Member

ここだけでないですが,ちゃんと SID がとれているかどうかのテストを戻り値が -1 でないかどうかだけでチェックしているのが気になります.エラーを返していない他に,ちゃんとした SID が取れているのテストってある程度できないでしょうか?(一応完璧にチェックすることができないのは理解していますが,SID の仕様をちゃんと理解していないので,まったくできなかったらすみません)

@haya14busa
haya14busa Feb 15, 2015 Member

んーすくなくとも 1 以上かみるということはできると思いますが, それではあまり変わらんデスよね...

あえて言うならそのSIDを使って実際に:scriptnamesとの整合性をみるとか, script-local関数取得したり呼んでみることが考えられますが, それがまさに実装されてそれぞれテストされている(sid()scriptnames()使ってたり, sfunc()sid()を内部で使ってる)ので微妙にムズさです.

もうひとつ, 言われてよく考えてみたら読み込み先のファイルに<SID>取得する関数おいて整合性をみたり, 適当な関数呼んでみるとかは出来るかもですね.
読み込み先のファイル依存にはなりますが, 考えられるのはこれくらいでしょうか.

@haya14busa
haya14busa Feb 15, 2015 Member

ちょっとテストカイゼンして詳しくみるようにしましたっ
haya14busa@10f1521

@rhysd
rhysd Feb 15, 2015 Member

要領を得ない指摘ですみません.カイゼン,良さそうです!

@rhysd
Member
rhysd commented Feb 15, 2015

@hayabusa ++

グッジョブです 🐦 👍

実装はちらっとしか見れていないので,時間あればもっとちゃんと見てみます.

名前について

名前指定するのは import() のときだけなので,わかりやすさ優先で ScriptLocal で良いのではないでしょうか.

テストでautoloadファイル以下や.themisrcを汚してる

.themisrc はよく分からないのですが,autoload 以下にテスト用ファイルを置くのはまずいと思います.
vim-themis のほうにテスト用ファイル/ディレクトリを無視する機能があるのが一番良いと思うのですが,無い場合はテスト前に適当な場所にテスト用ファイル/ディレクトリをつくってテストして最後に削除するみたいな実装が必要になるんじゃなかろうかと思います.

script-local変数も取得したい?

個人的には欲しいです.
黒魔術を使っていて危険であることはドキュメントに明示しておけば良いと思います.

@haya14busa
Member

@rhysd ありがとうございますっ!

名前指定するのは import() のときだけなので,わかりやすさ優先で ScriptLocal で良いのではないでしょうか.

確かにそうですね. よりこのままでよさそうな気がしてきました.

vim-themis のほうにテスト用ファイル/ディレクトリを無視する機能があるのが一番良いと思うのですが

アッ, よく見たら :h themis-option-exclude ありました. こちらに変更したほうがよさげですね.
他の選択肢としてすでにbenchmark/とかのディレクトリもあったり, 他のテストでもテスト用の.txtファイルおいてたりするので testdata/ディレクトリみたいなものを作るというのもありかなーと思うのですがどうでしょう.

script-local変数も取得したい?
個人的には欲しいです.
黒魔術を使っていて危険であることはドキュメントに明示しておけば良いと思います.

fmfm...ベンリケースはあるはずなので, 他に誰かいれるなーって人がいなさそうであれば入れてみようかと思いますっ

@thinca
Member
thinca commented Feb 15, 2015

コミットメッセージのプレフィックスは Vim.ScriptLocal: でお願いしますっ!

@haya14busa
Member

コミットメッセージのプレフィックスは Vim.ScriptLocal: でお願いしますっ!

oh...普通にミスッってました. rebase で直しましたっ

@thinca thinca and 1 other commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
+ INTERFACE |Vital.Vim.ScriptLocal-interface|
+ Functions |Vital.Vim.ScriptLocal-functions|
+
+==============================================================================
+INTRODUCTION *Vital.Vim.ScriptLocal-introduction*
+
+ *Vital.Vim.ScriptLocal* provides a way to get script local things.
+>
+ let s:V = vital#of('vital')
+ let s:S = s:V.import('Vim.ScriptLocal')
+>
+ "" Get <SID> with relative path to &runtimepath
+ " e.g. starts with autoload/, plugin/, etc...
+ " (autoload/**/*.vim, plugin/**/*.vim)
+
+ :echo s:S.sid('autoload/vital/test/Vim/ScriptLocal/test.vim')
@thinca
thinca Feb 15, 2015 Member

行頭 : の有無は統一して欲しいです。(個人的にはなしでいいかなっ)

@haya14busa
haya14busa Feb 15, 2015 Member

確かに他のファイルにはなかったので消しましたー

@haya14busa
Member

ファイル移行するときにミスッてsymlink.vimがシンボリックリンクじゃなかった...直します...

@haya14busa haya14busa changed the title from Vim:ScriptLocal: Add ScriptLocal (get script-local things) to Vim.ScriptLocal: Add ScriptLocal (get script-local things) Feb 15, 2015
@crazymaster crazymaster commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
@@ -0,0 +1,99 @@
+*vital-vim-script_local.txt* Get script-local things
+
+Maintainer: haya14busa <hayabusa1419@gmail.com>
+
+==============================================================================
+CONTENTS *Vital.Vim.ScriptLocal-contents*
+
+ INTRODUCTION |Vital.Vim.ScriptLocal-introduction|
@crazymaster
crazymaster Feb 15, 2015 Member

ここのindentは要らないのでは?

@crazymaster crazymaster commented on an outdated diff Feb 15, 2015
test/Vim/ScriptLocal.vimspec
+ endif
+ let sid = S.sid('autoload/vital/test/Vim/ScriptLocal/symlink.vim')
+ Assert IsNumber(sid)
+ Assert NotEquals(sid, -1)
+ Assert Exists(printf("*\<SNR>%s_double", sid))
+ End
+ It returns SID with symbolic link (absolute)
+ if P.is_windows()
+ Skip "windows doesn't handle symlink"
+ endif
+ let sid = S.sid(g:root . '/autoload/vital/test/Vim/ScriptLocal/symlink.vim')
+ Assert IsNumber(sid)
+ Assert NotEquals(sid, -1)
+ Assert Exists(printf("*\<SNR>%s_double", sid))
+ End
+ It handle the case &regexpengine == 1
@crazymaster
crazymaster Feb 15, 2015 Member

s/handle/handles/

@thinca thinca commented on an outdated diff Feb 15, 2015
doc/vital-vim-script_local.txt
@@ -0,0 +1,99 @@
+*vital-vim-script_local.txt* Get script-local things
+
+Maintainer: haya14busa <hayabusa1419@gmail.com>
+
+==============================================================================
+CONTENTS *Vital.Vim.ScriptLocal-contents*
+
+ INTRODUCTION |Vital.Vim.ScriptLocal-introduction|
+ INTERFACE |Vital.Vim.ScriptLocal-interface|
+ Functions |Vital.Vim.ScriptLocal-functions|
+
+==============================================================================
+INTRODUCTION *Vital.Vim.ScriptLocal-introduction*
+
+ *Vital.Vim.ScriptLocal* provides a way to get script local things.
@thinca
thinca Feb 15, 2015 Member

ここの indent も要らないですね。

@thinca thinca and 1 other commented on an outdated diff Feb 15, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+ for line in s:_capture_lines(':scriptnames')
+ let [sid, path] = split(line, '\m^\s*\d\+\zs:\s\ze')
+ let sdict[str2nr(sid)] = path " str2nr(): ' 1' -> 1
+ endfor
+ return sdict
+endfunction
+
+"" Return SID from the given path
+" return -1 if the given path is not found in scriptnames()
+" NOTE: it execute `:source` a given path once if the file haven't sourced yet
+function! s:sid(path) abort
+ " Expand
+ let tp = fnamemodify(expand(a:path), ':p') " target path
+ " Relative to &runtimepath
+ if !filereadable(tp)
+ let tp = globpath(&runtimepath, a:path)
@thinca
thinca Feb 15, 2015 Member

複数のパスが見つかった場合、globpath() は全てのパスを改行区切りで返すので、その対応をした方が良いです。
また、第3引数 {nosuf} も渡した方が良いです。

@haya14busa
haya14busa Feb 15, 2015 Member

oh...完全に対応漏れでした...

複数のパスが見つかった場合, 最初(or 最後?)のものを使う or エラー返しちゃう のどちらかが考えられると思いますがどちらがいいでしょうか?

思考停止で最初のものを使うようにしようかと思ったんですが, それが意図してないものだった場合に気づきにくくなってしまう...?

@thinca
thinca Feb 15, 2015 Member

最初のものでいいんじゃないですかねー。(適当)

@thinca thinca and 1 other commented on an outdated diff Feb 15, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+" @return {sid1: path1, sid2: path2, ...}
+function! s:scriptnames() abort
+ let sdict = {} " { sid: path }
+ for line in s:_capture_lines(':scriptnames')
+ let [sid, path] = split(line, '\m^\s*\d\+\zs:\s\ze')
+ let sdict[str2nr(sid)] = path " str2nr(): ' 1' -> 1
+ endfor
+ return sdict
+endfunction
+
+"" Return SID from the given path
+" return -1 if the given path is not found in scriptnames()
+" NOTE: it execute `:source` a given path once if the file haven't sourced yet
+function! s:sid(path) abort
+ " Expand
+ let tp = fnamemodify(expand(a:path), ':p') " target path
@thinca
thinca Feb 15, 2015 Member

この expand() は何を展開するのを想定しているでしょうか?
expand() はかなり色々なものを展開するので、慎重に使った方が良いです。意図的であれば問題はないです。

@haya14busa
haya14busa Feb 15, 2015 Member

意図的でない(fnamemodify()で十分)だと思うので消しました

@thinca thinca commented on an outdated diff Feb 15, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+" " => { 'fname1': funcref1, 'fname2': funcref2, ...}
+function! s:sfuncs(path) abort
+ return s:sid2sfuncs(s:sid(a:path))
+endfunction
+
+"" Return a dict which contains script-local functions from SID
+" USAGE:
+" :echo s:sid2sfuncs(1)
+" " => { 'fname1': funcref1, 'fname2': funcref2, ...}
+" " The file whose SID is 1 may be your vimrc
+" NOTE: old regexpengine has a bug which returns 0 with
+" :echo "\<SNR>" =~# "\\%#=1\x80\xfdR" | " => 0
+" But it matches correctly with :h /collection
+" :echo "\<SNR>" =~# "\\%#=1[\x80][\xfd]R" | " => 1
+" http://lingr.com/room/vim/archives/2015/02/13#message-21261450
+let s:SNR = "[\x80][\xfd]R"
@thinca
thinca Feb 15, 2015 Member

<SNR> がこの値であるという確証がないので、実際の値から導出した方が良いかもしれません。

例えば、

function! s:_SNR() abort
  let snr = "\<SNR>"
  let result = ''
  for i in range(len(snr))
    let result .= '[' . snr[i] . ']'
  endfor
  return result
endfunction

let s:SNR = s:_SNR()

もしくはワンライナーで、

let s:SNR = join(map(range(len("\<SNR>")), '"[" . "\<SNR>"[v:val] . "]"'), '')

まあ、<SNR> の値が将来変わる可能性はかなり低いので、問題が起きてから対応でも全然問題ない気もします。

@thinca thinca commented on an outdated diff Feb 15, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+" NOTE: old regexpengine has a bug which returns 0 with
+" :echo "\<SNR>" =~# "\\%#=1\x80\xfdR" | " => 0
+" But it matches correctly with :h /collection
+" :echo "\<SNR>" =~# "\\%#=1[\x80][\xfd]R" | " => 1
+" http://lingr.com/room/vim/archives/2015/02/13#message-21261450
+let s:SNR = "[\x80][\xfd]R"
+function! s:sid2sfuncs(sid) abort
+ let sprefix = s:_sprefix(a:sid)
+ ":h :function /{pattern}
+ " -> ^________
+ " function <SNR>14_functionname(args, ...)
+ let fs = s:_capture_lines(':function ' . printf("/^%s%s_", s:SNR, a:sid))
+ let r = {}
+ " -> ^--------____________-
+ " function <SNR>14_functionname(args, ...)
+ for fname in map(fs, "matchstr(v:val, printf('\\m^function\\s<SNR>%d_\\zs\\w\\{-}\\ze(', a:sid))")
@thinca
thinca Feb 15, 2015 Member

こんな感じで複雑になる場合は、一旦変数に入れると便利です。

let pattern = printf('\m^function\s<SNR>%d_\zs\w\{-}\ze(', a:sid)
for fname in map(fs, 'matchstr(v:val, pattern)')
@thinca thinca commented on an outdated diff Feb 15, 2015
test/Vim/ScriptLocal.vimspec
@@ -0,0 +1,123 @@
+Describe Vim.ScriptLocal
+
+ Before all
+ let V = vital#of('vital')
+ let P = V.import('Prelude')
+ let S = V.import('Vim.ScriptLocal')
+ End
+
+ Context .sid()
@thinca
thinca Feb 15, 2015 Member

個々の関数の部分は Describe の方がいいですね。既存のテストを参考にして頂けると…!

@rhysd
Member
rhysd commented Feb 15, 2015

アッ, よく見たら :h themis-option-exclude ありました. こちらに変更したほうがよさげですね.
他の選択肢としてすでにbenchmark/とかのディレクトリもあったり, 他のテストでもテスト用の.txtファイルおいてたりするので testdata/ディレクトリみたいなものを作るというのもありかなーと思うのですがどうでしょう.

runtimepath 上にディレクトリ増やしたくないと思うので,test/ 以下に assets なり testdata なりのディレクトリ掘るのが一番良いと思います!

@thinca
Member
thinca commented Feb 15, 2015

@rhysd ++
/test/_testdata 辺りに +1
_ を付けたのは、確実にモジュール名と被らないようにするためです。他の文字でも良い。

@haya14busa
Member

修正+追加しましたっ

  1. テスト用Vim scriptファイルを /test/_testdata ディレクトリに移しました
  2. sid2path() 関数足しました. (<SID>からpathを取得する. やっぱり個人的に欲しいと思ったので)
  3. svars(), sid2svars() 関数を足しました. (script-local変数を取得できる)

svars() の黒魔術感, ベンリ💀

@thinca thinca and 1 other commented on an outdated diff Feb 17, 2015
@@ -26,4 +26,4 @@ script:
- vim --cmd version --cmd quit
- vim --cmd "try | helptags doc/ | catch | cquit | endtry" --cmd quit
- ./spec.sh -q -p /tmp/vimproc
- - /tmp/vim-themis/bin/themis --runtimepath /tmp/vimproc --reporter dot
+ - /tmp/vim-themis/bin/themis --runtimepath /tmp/vimproc --exclude test/_testdata/ --reporter dot
@thinca
thinca Feb 17, 2015 Member

ここより、.themisrc に書いた方が普段から使いやすいと思います。
詳しくは :help .themisrc の Command line Options の項目をチェック!

@haya14busa
haya14busa Feb 17, 2015 Member

themisベンリ...!

@thinca thinca commented on an outdated diff Feb 17, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+\ ' return s:',
+\ 'endfunction'
+\ ]
+
+"" Return script-local variable (s:var) dict form path
+function! s:svars(path) abort
+ return s:sid2svars(s:sid(a:path))
+endfunction
+
+"" Return script-local variable (s:var) dictionary form SID
+function! s:sid2svars(sid) abort
+ let fullpath = fnamemodify(s:sid2path(a:sid), ':p')
+ let lines = readfile(fullpath)
+ try
+ call writefile(s:_get_svars_func, fullpath)
+ execute 'source' fullpath
@thinca
thinca Feb 17, 2015 Member

fnameescape() した方が良さそう。

@thinca thinca commented on an outdated diff Feb 17, 2015
doc/vital-vim-script_local.txt
+
+sid2sfuncs(<SID>) *Vital.Vim.ScriptLocal.sid2sfuncs()*
+ Returns a dict which contains |script-local| functions with <SID>.
+>
+ echo s:S.sid2sfuncs(1)
+ " => { 'fname1': funcref1, 'fname2': funcref2, ...}
+ " The file whose SID is 1 may be your vimrc
+
+svars({path}) *Vital.Vim.ScriptLocal.svars()*
+ Returns a dict which contains |script-variable| with {path}.
+ (See |Vital.Vim.ScriptLocal-path|). >
+
+ let s = s:S.svars('test/_testdata/Vim/ScriptLocal/test.vim')
+ echo s | " => { 'i': 1 }
+<
+ NOTE: svars() will temporally overwrite the target file and
@thinca
thinca Feb 17, 2015 Member

かなり危険なので、WARNING とか CAUTION くらい強い言葉を使ってもいいかも。

@thinca thinca commented on the diff Feb 17, 2015
autoload/vital/__latest__/Vim/ScriptLocal.vim
+
+let s:GETSVARSFUNCNAME = '___VITAL_VIM_SCRIPTLOCAL_GET_SVARS___'
+
+let s:_get_svars_func = [
+\ printf('function! s:%s() abort', s:GETSVARSFUNCNAME),
+\ ' return s:',
+\ 'endfunction'
+\ ]
+
+"" Return script-local variable (s:var) dict form path
+function! s:svars(path) abort
+ return s:sid2svars(s:sid(a:path))
+endfunction
+
+"" Return script-local variable (s:var) dictionary form SID
+function! s:sid2svars(sid) abort
@thinca
thinca Feb 17, 2015 Member

これ、s: の辞書自体は変わらないはずなので、{sid} をキーにしてキャッシュ取っておくと2回目以降に無用なファイル書き換えをせずに済みそうな予感ありますね。(そんなに使われるのかと言う疑問もないでもない)

@haya14busa
haya14busa Feb 17, 2015 Member

それでいうと .sid(), .sid2path(), .sid2svars(), .svars() は全部キャッシュできる感ありますね. (svars()は関数組み合わせてるだけなので要らないけど)

s:var とる系の .svars(), .sid2svars() は危険だからキャッシュしたいというのはあるかも...? (というか全部面倒臭がらずキャッシュできるやつはやるほうがいい感もありますかね. redir必要以上に発動しないようにできるし)

@haya14busa
haya14busa Feb 17, 2015 Member

キャッシュ可能な関数は全部キャッシュしてみました!
ちょっとボイラープレートが増えて読みづらくなったかもですが, ユースケースとして, quickrunとかでゴリゴリ試すケースとかもきっとあるはずで, その際にredirが毎回呼ばれなくなるとなかなかベンリだということに気づきました.

@haya14busa
haya14busa Feb 17, 2015 Member

無用なファイル書き換えをせずに済みそうな予感

よく読んだら危険なのを無用にするためと書いてあったのに読み落として全部やっちゃいましたスイマセン

@thinca
Member
thinca commented Feb 21, 2015

👍

@thinca
Member
thinca commented Feb 28, 2015

👍 するだけして放置しちゃってたけど、もうマージしちゃっても良いかな?

@rhysd
Member
rhysd commented Feb 28, 2015

fb5b1dd 以降のコミットをざっと読みました.

LGTM です 👍

@haya14busa
Member

個人的には欲しい機能は全部実装済みですっ.
squash はしたほうがよさげですかね?

@rhysd
Member
rhysd commented Mar 1, 2015

@haya14busa

squash するかどうかは過去のプルリクマージみた感じ,個人の好みで決めて良さそうです.

@haya14busa haya14busa Vim.ScriptLocal: Add ScriptLocal (get script-local things)
- add test/_testdata/ directory for test data
- add the g:root variable to get vital root path for testing
1c2c3bb
@haya14busa
Member

squash してまとめましたっ

@rhysd rhysd merged commit 34b74d1 into vim-jp:master Mar 1, 2015

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details
@rhysd
Member
rhysd commented Mar 1, 2015

🎉

@haya14busa
Member

ワーイ, みなさんありがとうございましたっ....!

@haya14busa haya14busa deleted the haya14busa:add-vim-scriptlocal branch Mar 1, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment