Skip to content

Instantly share code, notes, and snippets.

@tyru
Last active July 2, 2019 17:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tyru/6d2999418ac5f5b7d5cdb960032d6009 to your computer and use it in GitHub Desktop.
Save tyru/6d2999418ac5f5b7d5cdb960032d6009 to your computer and use it in GitHub Desktop.
require() function for deeply nested very loooooooooong named autoload function
let s:L = vital#of('vital').import('Data.List')
function! s:require(ns, ...) abort
let ns = strtrans(a:ns)
let fnlist = map(
\ split(execute('function /' . ns), '\n'),
\ {_,l -> matchstr(l, '^function ' . ns . '#\zs\w\+\ze(')}
\)
call filter(fnlist, '!empty(v:val)')
if a:0
let nofuncs = filter(copy(a:1), {_,fn -> index(fnlist, fn) is -1})
if !empty(nofuncs)
" TODO: show multiple func name at once?
throw printf('Exxx: Unknown function in %s: %s', ns, nofuncs[0])
endif
return map(fnlist, {_,fn -> function(ns . '#' . fn)})
endif
let d = {}
for fn in fnlist
let d[fn] = function(ns . '#' . fn)
endfor
return d
endfunction
let v:errors = []
" vital#of('vital').import('Data.List').pop([1,2,3])
call assert_equal(function('vital#of'), s:require('vital').of)
call assert_equal(3, s:require('vital').of('vital').import('Data.List').pop([1,2,3]))
call assert_equal([function('vital#of')], s:require('vital', ['of']))
call assert_equal(3, s:require('vital', ['of'])[0]('vital').import('Data.List').pop([1,2,3]))
try
call s:require('vital', ['xxx'])
call assert_true(0, 'Exxx was not thrown')
catch
call assert_exception('Exxx:')
endtry
echohl ErrorMsg
for s:_ in v:errors
echo s:_
endfor
echohl None
@lambdalisue
Copy link

こんなんどうでしょう? Vital 依存無くして簡易化したやつ

let s:name = fnamemodify(expand('<sfile>:p'), ':t:r')

function! z#_#require(path) abort
  let l:prefix = printf('z#%s#%s', s:name, a:path)
  let l:script = printf(
        \ 'autoload/%s.vim',
        \ substitute(l:prefix, '#', '/', 'g')
        \)
  execute printf(
        \ 'runtime! %s',
        \ fnameescape(s:from_slash(l:script)),
        \)
  let l:fnames = map(
        \ split(execute('function /' . l:prefix), '\n'),
        \ { -> matchstr(v:val, '^function \zs[a-zA-Z0-9_#]\+\ze(') }
        \)
  let l:module = {}
  for l:fname in filter(l:fnames, '!empty(v:val)')
    let l:name = matchstr(l:fname, '.*#\zs[a-zA-Z0-9_]\+')
    let l:module[l:name] = funcref(l:fname)
  endfor
  return l:module
endfunction

function! s:from_slash(path) abort
  return fnamemodify(a:path, 'gs?/?\\?')
endfunction

@tyru
Copy link
Author

tyru commented Jul 2, 2019

あ、すみません。
冒頭で vital import してますがその後使ってないです (issue にあげるために依存切った)。

簡易化いいですね。
というか今気づきましたが自分のバージョンだとスクリプトがロードされてない場合に対処できてないですね。
あざます。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment