Created
December 13, 2011 15:54
-
-
Save wonderful-panda/1472644 to your computer and use it in GitHub Desktop.
VimのコマンドラインでBazaarコマンドの補完をしてみる
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let g:BZR_EXECUTABLE='bzr' | |
if exists('s:commands') | |
unlet s:commands | |
endif | |
let s:cmd_options = {} | |
" コマンド名のリストを返す | |
function! s:GetCommands() | |
if !exists('s:commands') | |
" `bzr help commands` の出力からコマンドの一覧を生成する | |
let s:commands = [] | |
let l:output = system(g:BZR_EXECUTABLE . ' help commands') | |
for l:line in split(l:output, '\n') | |
let l:matches = matchlist(l:line, '\v^([a-z0-9_-]+)\s') | |
if !empty(l:matches) | |
call add(s:commands, l:matches[1]) | |
endif | |
endfor | |
endif | |
return copy(s:commands) | |
endfunction | |
" 指定されたコマンドのオプションのリストを返す | |
function! s:GetCommandOptions(cmd_name) | |
if has_key(s:cmd_options, a:cmd_name) | |
return copy(s:cmd_options[a:cmd_name]) | |
endif | |
" `bzr cmd_name --help` の出力からオプションの一覧を生成する | |
let l:cmd_options = [] | |
let l:output = system(g:BZR_EXECUTABLE . ' ' . a:cmd_name . ' --help') | |
let l:patterns = ['\v^\s*(-[a-zA-Z])( [a-zA-Z-]+|)(\s|,|$)', | |
\ '\v^\s*(--[a-zA-Z-]+)(\s|,|$)', | |
\ '\v^\s*(--[a-zA-Z-]+\=)[a-zA-Z-_]+(\s|,|$)'] | |
for l:line in split(l:output, '\n') | |
if !(l:line =~ '\v^\s+-') | |
continue | |
endif | |
while 1 | |
for l:pattern in l:patterns | |
let l:matches = matchlist(l:line, l:pattern) | |
if !empty(l:matches) | |
break | |
endif | |
endfor | |
if empty(l:matches) | |
break | |
endif | |
call add(l:cmd_options, l:matches[1]) | |
let l:line = l:line[strlen(l:matches[0]):] | |
endwhile | |
endfor | |
call sort(l:cmd_options) | |
let s:cmd_options[a:cmd_name] = l:cmd_options | |
return copy(l:cmd_options) | |
endfunction | |
" 指定されたパスを含むBazaarブランチの、.bzrディレクトリのパスを返す | |
function! s:GetBzrDir(dirpath) | |
let l:path = substitute(a:dirpath, '\\', '/', 'g') | |
if l:path[-1:-1] == '/' | |
let l:path = l:path[0:-2] | |
endif | |
while 1 | |
if isdirectory(l:path.'/.bzr') | |
return l:path.'/.bzr' | |
endif | |
let l:pos = strridx(l:path, '/') | |
if l:pos > 0 | |
let l:path = l:path[:l:pos - 1] | |
else | |
return "" | |
endif | |
endwhile | |
endfunction | |
" 指定されたパスを含むBazaarブランチのルートのパスを返す | |
function! s:GetRoot(dirpath) | |
let l:bzrdir = s:GetBzrDir(a:dirpath) | |
if l:bzrdir == "" | |
return "" | |
else | |
return l:bzrdir[:-5] | |
endif | |
endfunction | |
" 指定されたColocatedワークスペースの中にあるColocatedブランチのリストを返す | |
function! s:GetColoBranches(rootdir) | |
let l:output = [] | |
let l:dirs = glob(a:rootdir.'/.bzr/branches/**/.bzr') | |
if empty(l:dirs) | |
return l:output | |
endif | |
for l:subdir in split(l:dirs, '\n') | |
let l:name = substitute(l:subdir, '\\', '/', 'g')[strlen(a:rootdir.'/.bzr/branches/'):-6] | |
if !empty(l:name) | |
call add(l:output, l:name) | |
endif | |
endfor | |
return l:output | |
endfunction | |
function! s:GetRecentRevisions(rootdir) | |
" not impremented. | |
endfunction | |
" コマンドラインを補完するためのFunction | |
function! s:Complete(arg_lead, cmdline, cursor_pos) | |
let l:cmd = split(a:cmdline) | |
let l:len_cmd = len(l:cmd) | |
if l:len_cmd <= 1 || (l:len_cmd == 2 && l:cmd[1] == a:arg_lead) | |
" コマンド名を補完する | |
return filter(s:GetCommands(), printf("v:val =~ '^%s'", a:arg_lead)) | |
elseif a:arg_lead[:4] == 'colo:' | |
" coloブランチ名を補完する | |
let l:root = s:GetRoot(getcwd()) | |
if !empty(l:root) | |
return filter(map(s:GetColoBranches(l:root), "'colo:'.v:val"), | |
\ printf("v:val[:%d] == '%s'", strlen(a:arg_lead) - 1, a:arg_lead)) | |
endif | |
elseif a:arg_lead =~ '\v^\-\-[a-zA-Z-]*$' | |
" オプションを補完する | |
return filter(s:GetCommandOptions(l:cmd[1]), printf("v:val =~ '^%s'", a:arg_lead)) | |
else | |
" ディレクトリ、ファイルを補完する | |
if a:arg_lead =~ '^--[A-Za-z-]+\=$' | |
return map(split(glob('*'), '\n'), "a:arg_lead . v:val") | |
elseif !empty(a:arg_lead) | |
return split(glob(a:arg_lead . '*'), '\n') | |
else | |
return s:GetCommandOptions(l:cmd[1]) + split(glob(a:arg_lead . '*'), '\n') | |
endif | |
endif | |
return [] | |
endfunction | |
command! -complete=customlist,s:Complete -nargs=* Bzr call s:RunShellCommand(g:BZR_EXECUTABLE.' '.<q-args>) | |
command! -complete=customlist,s:Complete -nargs=* BzrAsync call vimproc#system_gui(g:BZR_EXECUTABLE.' '.<q-args>) | |
function! s:RunShellCommand(cmdline) | |
botright new | |
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap | |
call setline(1,a:cmdline) | |
call setline(2,substitute(a:cmdline,'.','=','g')) | |
execute 'silent $read !'.escape(a:cmdline,'()%#') | |
setlocal nomodifiable | |
1 | |
if search('\m\C^--- .*\n+++ .*\n@@','n') | |
setlocal filetype=diff | |
endif | |
if a:cmdline =~ '\m\C^git ' | |
2match Statement /\v\C<commit \x{7,}>/ | |
elseif a:cmdline =~ '\m\C^bzr log' | |
2match Statement /\v-{50,}/ | |
endif | |
endfunction |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment