NeoBundle 관리에 정의된 명령을 추출하여 메뉴에 표시

16168 단어 Vim

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
상술한 내용을 적절하게 저장하고 생성한다.
AutoMenu_CreateFromPath('^\~\/dotfiles\/\.vim\/bundle\/\([^\/]\+\)/')
이렇게 하면 매개 변수가 전달되는 디렉터리에서 명령을 수집합니다.
메뉴의 그룹 이름은 정규 표현식에서 괄호로 묶은 첫 번째 그룹에서 선택됩니다.

좋은 웹페이지 즐겨찾기