NeoBundleとかで管理されたコマンドをメニューに表示させたらチートシートみたいで便利なんじゃないかと思いましたがそんなことはなかったです。
let s:DEFAULT_GROUP = '* default *'
let s:TOP_MENU_LABEL = 'AutoMenu'
function! s:isIgnoreVerbosePattern(verbose)
" TODO: depending on user locale
let verboseIgnorePatterns = [
\ '^$',
\ '^\s*名前',
\ ]
for pattern in verboseIgnorePatterns
if a:verbose =~ pattern
return 1
endif
endfor
return 0
endfunction
function! s:verboseOf(command)
let v = ''
redir => v
execute join(['silent', 'verbose', a:command], ' ')
redir END
let filteredTokens = []
for line in split(v, '\n')
if !s:isIgnoreVerbosePattern(line)
call add(filteredTokens, line)
endif
endfor
let verboses = []
let len = len(filteredTokens)
for i in range(0, len - 1 - 1)
let current = filteredTokens[i + 0]
let next = filteredTokens[i + 1]
" TODO: is this depending on our language?
let setAtToken = matchlist(next, '^\s\+Last set from\s\+\(.\+\)$')
if (len(setAtToken)) <= 0 || (setAtToken[1] == '')
continue
end
let setAt = setAtToken[1]
let work = {'st': current, 'setAt': setAt}
call add(verboses, work)
endfor
return verboses
endfunction
function! s:groupFromPath(path, filter)
let matched = matchlist(a:path, a:filter)
if len(matched) >= 1
if matched[1] == ''
return s:DEFAULT_GROUP
else
return substitute(matched[1], '\.', '\\\.', 'g')
endif
else
return ''
endif
endfunction
function! s:parseCmdVerbose(verbose)
let token = matchlist(a:verbose, '^.\{4}\(\S\+\)\s\+\(\S\)')
if len(token) <= 0
return {}
else
if token[2] == 'b'
echo a:verbose
endif
return {'cmd': token[1], 'nargs': token[2]}
endif
endfunction
function! s:parseMapVerbose(verbose)
let token = matchlist(a:verbose, '^\(\S\?\)\s\+\(\S\+\)')
if len(token) <= 0
return {}
else
return {'mode': token[1], 'map': token[2]}
endif
endfunction
function! Feedkeys(keybinding)
let keybinding = a:keybinding
let pattern = '<.\{-}>'
" subtitute <C-x> into \<C-x>
" TODO: not work if nested blanket were appeared
let i = 0
while i < 10
let i += 1
let start = match(keybinding, pattern)
let end = matchend(keybinding, pattern)
if start == -1
break
endif
let keybinding = substitute(keybinding, keybinding[start : end], eval('"' . '\' . keybinding[start : end] . '"'), 'g')
endwhile
endfunction
function! s:filterByPath(verboses, filterPath)
let res = []
for verbose in a:verboses
let group = s:groupFromPath(verbose['setAt'], a:filterPath)
if group == ''
continue
endif
let work = verbose
let work['group'] = group
call add(res, work)
endfor
return res
endfunction
function! AutoMenu_CreateFromPath(filterPath)
let mapVerboses = s:filterByPath(s:verboseOf('map'), a:filterPath)
let cmdVerboses = s:filterByPath(s:verboseOf('command'), a:filterPath)
" clear menu
execute join(['silent!', 'unmenu', s:TOP_MENU_LABEL], ' ')
for cmdVerbose in cmdVerboses
let moreCmdVerbose = s:parseCmdVerbose(cmdVerbose['st'])
if moreCmdVerbose == {}
continue
endif
let cmdVerbose['cmd'] = moreCmdVerbose['cmd']
let cmdVerbose['nargs'] = moreCmdVerbose['nargs']
let menuExp = [s:TOP_MENU_LABEL, cmdVerbose['group'], cmdVerbose['cmd']]
execute join(['menu', join(menuExp, '.'), ":" . cmdVerbose['cmd'] . '<CR>'], ' ')
endfor
endfunc
上記を適当に保存、soureして。
AutoMenu_CreateFromPath('^\~\/dotfiles\/\.vim\/bundle\/\([^\/]\+\)/')
こんな感じで実行すると引数渡ししたディレクトリ配下からコマンドを収集します。
メニューのグループ名は正規表現でカッコで囲ったグループ1番目から拾います。