rm ctrlp fuf l9 rails tabular for vundle
This commit is contained in:
parent
9349b069e9
commit
0bea27d080
59 changed files with 0 additions and 28501 deletions
|
|
@ -1,48 +0,0 @@
|
||||||
if !exists(':Tabularize')
|
|
||||||
finish " Tabular.vim wasn't loaded
|
|
||||||
endif
|
|
||||||
|
|
||||||
let s:save_cpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
AddTabularPattern! assignment /[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*=/l1r1
|
|
||||||
AddTabularPattern! two_spaces / /l0
|
|
||||||
|
|
||||||
AddTabularPipeline! multiple_spaces / / map(a:lines, "substitute(v:val, ' *', ' ', 'g')") | tabular#TabularizeStrings(a:lines, ' ', 'l0')
|
|
||||||
|
|
||||||
AddTabularPipeline! argument_list /(.*)/ map(a:lines, 'substitute(v:val, ''\s*\([(,)]\)\s*'', ''\1'', ''g'')')
|
|
||||||
\ | tabular#TabularizeStrings(a:lines, '[(,)]', 'l0')
|
|
||||||
\ | map(a:lines, 'substitute(v:val, ''\(\s*\),'', '',\1 '', "g")')
|
|
||||||
\ | map(a:lines, 'substitute(v:val, ''\s*)'', ")", "g")')
|
|
||||||
|
|
||||||
function! SplitCDeclarations(lines)
|
|
||||||
let rv = []
|
|
||||||
for line in a:lines
|
|
||||||
" split the line into declaractions
|
|
||||||
let split = split(line, '\s*[,;]\s*')
|
|
||||||
" separate the type from the first declaration
|
|
||||||
let type = substitute(split[0], '\%(\%([&*]\s*\)*\)\=\k\+$', '', '')
|
|
||||||
" add the ; back on every declaration
|
|
||||||
call map(split, 'v:val . ";"')
|
|
||||||
" add the first element to the return as-is, and remove it from the list
|
|
||||||
let rv += [ remove(split, 0) ]
|
|
||||||
" transform the other elements by adding the type on at the beginning
|
|
||||||
call map(split, 'type . v:val')
|
|
||||||
" and add them all to the return
|
|
||||||
let rv += split
|
|
||||||
endfor
|
|
||||||
return rv
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
AddTabularPipeline! split_declarations /,.*;/ SplitCDeclarations(a:lines)
|
|
||||||
|
|
||||||
AddTabularPattern! ternary_operator /^.\{-}\zs?\|:/l1
|
|
||||||
|
|
||||||
AddTabularPattern! cpp_io /<<\|>>/l1
|
|
||||||
|
|
||||||
AddTabularPattern! pascal_assign /:=/l1
|
|
||||||
|
|
||||||
AddTabularPattern! trailing_c_comments /\/\*\|\*\/\|\/\//l1
|
|
||||||
|
|
||||||
let &cpo = s:save_cpo
|
|
||||||
unlet s:save_cpo
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,95 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/dir.vim
|
|
||||||
" Description: Directory extension
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Init {{{1
|
|
||||||
if exists('g:loaded_ctrlp_dir') && g:loaded_ctrlp_dir
|
|
||||||
fini
|
|
||||||
en
|
|
||||||
let [g:loaded_ctrlp_dir, g:ctrlp_newdir] = [1, 0]
|
|
||||||
|
|
||||||
let s:ars = [
|
|
||||||
\ 's:folsym',
|
|
||||||
\ 's:dotfiles',
|
|
||||||
\ 's:maxdepth',
|
|
||||||
\ 's:maxfiles',
|
|
||||||
\ 's:compare_lim',
|
|
||||||
\ 's:glob',
|
|
||||||
\ ]
|
|
||||||
|
|
||||||
let s:dir_var = ['ctrlp#dir#init('.join(s:ars, ', ').')', 'ctrlp#dir#accept',
|
|
||||||
\ 'dirs', 'dir']
|
|
||||||
|
|
||||||
let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars)
|
|
||||||
\ ? add(g:ctrlp_ext_vars, s:dir_var) : [s:dir_var]
|
|
||||||
|
|
||||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
|
||||||
" Utilities {{{1
|
|
||||||
fu! s:globdirs(dirs, depth)
|
|
||||||
let entries = split(globpath(a:dirs, s:glob), "\n")
|
|
||||||
if !s:folsym
|
|
||||||
let entries = filter(entries, 'getftype(v:val) != "link"')
|
|
||||||
en
|
|
||||||
let ftrfunc = s:dotfiles ? 'ctrlp#dirfilter(v:val)' : 'isdirectory(v:val)'
|
|
||||||
let alldirs = filter(entries, ftrfunc)
|
|
||||||
cal extend(g:ctrlp_alldirs, alldirs)
|
|
||||||
let depth = a:depth + 1
|
|
||||||
if !empty(g:ctrlp_alldirs) && !s:max(len(g:ctrlp_alldirs), s:maxfiles)
|
|
||||||
\ && depth <= s:maxdepth
|
|
||||||
sil! cal ctrlp#progress(len(g:ctrlp_alldirs))
|
|
||||||
cal s:globdirs(join(alldirs, ','), depth)
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:max(len, max)
|
|
||||||
retu a:max && a:len > a:max ? 1 : 0
|
|
||||||
endf
|
|
||||||
" Public {{{1
|
|
||||||
fu! ctrlp#dir#init(...)
|
|
||||||
let s:cwd = getcwd()
|
|
||||||
for each in range(len(s:ars))
|
|
||||||
exe 'let' s:ars[each] '=' string(eval('a:'.(each + 1)))
|
|
||||||
endfo
|
|
||||||
let cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().s:dir_var[3]
|
|
||||||
let cafile = cadir.ctrlp#utils#lash().ctrlp#utils#cachefile(s:dir_var[3])
|
|
||||||
if g:ctrlp_newdir || !filereadable(cafile)
|
|
||||||
let g:ctrlp_alldirs = []
|
|
||||||
cal s:globdirs(s:cwd, 0)
|
|
||||||
cal ctrlp#rmbasedir(g:ctrlp_alldirs)
|
|
||||||
let read_cache = 0
|
|
||||||
el
|
|
||||||
let g:ctrlp_alldirs = ctrlp#utils#readfile(cafile)
|
|
||||||
let read_cache = 1
|
|
||||||
en
|
|
||||||
if len(g:ctrlp_alldirs) <= s:compare_lim
|
|
||||||
cal sort(g:ctrlp_alldirs, 'ctrlp#complen')
|
|
||||||
en
|
|
||||||
if !read_cache
|
|
||||||
cal ctrlp#utils#writecache(g:ctrlp_alldirs, cadir, cafile)
|
|
||||||
let g:ctrlp_newdir = 0
|
|
||||||
en
|
|
||||||
retu g:ctrlp_alldirs
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#dir#accept(mode, str)
|
|
||||||
let path = a:mode == 'h' ? getcwd() : s:cwd.ctrlp#utils#lash().a:str
|
|
||||||
if a:mode =~ 't\|v\|h'
|
|
||||||
cal ctrlp#exit()
|
|
||||||
en
|
|
||||||
cal ctrlp#setdir(path, a:mode =~ 't\|h' ? 'chd!' : 'lc!')
|
|
||||||
if a:mode == 'e'
|
|
||||||
sil! cal ctrlp#statusline()
|
|
||||||
cal ctrlp#setlines(s:id)
|
|
||||||
cal ctrlp#recordhist()
|
|
||||||
cal ctrlp#prtclear()
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#dir#id()
|
|
||||||
retu s:id
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
|
|
@ -1,61 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/line.vim
|
|
||||||
" Description: Line extension - find a line in any buffer.
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Init {{{1
|
|
||||||
if exists('g:loaded_ctrlp_line') && g:loaded_ctrlp_line
|
|
||||||
fini
|
|
||||||
en
|
|
||||||
let g:loaded_ctrlp_line = 1
|
|
||||||
|
|
||||||
let s:line_var = ['ctrlp#line#init()', 'ctrlp#line#accept', 'lines', 'line']
|
|
||||||
|
|
||||||
let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars)
|
|
||||||
\ ? add(g:ctrlp_ext_vars, s:line_var) : [s:line_var]
|
|
||||||
|
|
||||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
|
||||||
" Public {{{1
|
|
||||||
fu! ctrlp#line#init()
|
|
||||||
let [bufs, lines] = [[], []]
|
|
||||||
for each in range(1, bufnr('$'))
|
|
||||||
if getbufvar(each, '&bl')
|
|
||||||
let bufname = bufname(each)
|
|
||||||
if strlen(bufname) && bufname != 'ControlP'
|
|
||||||
cal add(bufs, fnamemodify(bufname, ':p'))
|
|
||||||
en
|
|
||||||
en
|
|
||||||
endfo
|
|
||||||
cal filter(bufs, 'filereadable(v:val)')
|
|
||||||
for each in bufs
|
|
||||||
let from_file = readfile(each)
|
|
||||||
cal map(from_file, 'tr(v:val, '' '', '' '')')
|
|
||||||
let [id, len_ff, bufnr] = [1, len(from_file), bufnr(each)]
|
|
||||||
wh id <= len_ff
|
|
||||||
let from_file[id-1] .= ' #:'.bufnr.':'.id
|
|
||||||
let id += 1
|
|
||||||
endw
|
|
||||||
cal filter(from_file, 'v:val !~ ''^\s*\t#:\d\+:\d\+$''')
|
|
||||||
cal extend(lines, from_file)
|
|
||||||
endfo
|
|
||||||
sy match CtrlPTabExtra '\zs\t.*\ze$'
|
|
||||||
hi link CtrlPTabExtra Comment
|
|
||||||
retu lines
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#line#accept(mode, str)
|
|
||||||
let info = get(split(a:str, '\t#:\ze\d\+:\d\+$'), 1, 0)
|
|
||||||
let bufnr = str2nr(get(split(info, ':'), 0, 0))
|
|
||||||
let linenr = get(split(info, ':'), 1, 0)
|
|
||||||
if bufnr
|
|
||||||
cal ctrlp#acceptfile(a:mode, fnamemodify(bufname(bufnr), ':p'), linenr)
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#line#id()
|
|
||||||
retu s:id
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/mrufiles.vim
|
|
||||||
" Description: Most Recently Used Files extension
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Static variables {{{1
|
|
||||||
fu! ctrlp#mrufiles#opts()
|
|
||||||
let opts = {
|
|
||||||
\ 'g:ctrlp_mruf_max': ['s:max', 250],
|
|
||||||
\ 'g:ctrlp_mruf_include': ['s:include', ''],
|
|
||||||
\ 'g:ctrlp_mruf_exclude': ['s:exclude', ''],
|
|
||||||
\ 'g:ctrlp_mruf_case_sensitive': ['s:csen', 1],
|
|
||||||
\ }
|
|
||||||
for [ke, va] in items(opts)
|
|
||||||
exe 'let' va[0] '=' string(exists(ke) ? eval(ke) : va[1])
|
|
||||||
endfo
|
|
||||||
endf
|
|
||||||
cal ctrlp#mrufiles#opts()
|
|
||||||
fu! ctrlp#mrufiles#list(bufnr, ...) "{{{1
|
|
||||||
if s:locked | retu | en
|
|
||||||
" Get the list
|
|
||||||
let cadir = ctrlp#utils#cachedir().ctrlp#utils#lash().'mru'
|
|
||||||
let cafile = cadir.ctrlp#utils#lash().'cache.txt'
|
|
||||||
let mrufs = ctrlp#utils#readfile(cafile)
|
|
||||||
" Remove non-existent files
|
|
||||||
if exists('a:1') && a:1 == 1
|
|
||||||
let mrufs = s:rmdeleted(mrufs, cadir, cafile)
|
|
||||||
elsei exists('a:1') && a:1 == 2
|
|
||||||
cal ctrlp#utils#writecache([], cadir, cafile)
|
|
||||||
retu []
|
|
||||||
en
|
|
||||||
" Return the list
|
|
||||||
if a:bufnr == -1 | retu mrufs | en
|
|
||||||
" Filter it
|
|
||||||
let filename = fnamemodify(bufname(a:bufnr + 0), ':p')
|
|
||||||
if empty(filename) || !empty(&bt)
|
|
||||||
\ || ( !empty(s:include) && filename !~# s:include )
|
|
||||||
\ || ( !empty(s:exclude) && filename =~# s:exclude )
|
|
||||||
\ || ( index(mrufs, filename) == -1 && !filereadable(filename) )
|
|
||||||
retu
|
|
||||||
en
|
|
||||||
" Remove old matched entry
|
|
||||||
cal filter(mrufs, 'v:val !='.( s:csen ? "#" : "?" ).' filename')
|
|
||||||
" Insert new one
|
|
||||||
cal insert(mrufs, filename)
|
|
||||||
" Remove oldest entry
|
|
||||||
if len(mrufs) > s:max | cal remove(mrufs, s:max, -1) | en
|
|
||||||
cal ctrlp#utils#writecache(mrufs, cadir, cafile)
|
|
||||||
endf "}}}
|
|
||||||
fu! s:rmdeleted(mrufs, cadir, cafile) "{{{
|
|
||||||
cal filter(a:mrufs, '!empty(ctrlp#utils#glob(v:val, 1))')
|
|
||||||
cal ctrlp#utils#writecache(a:mrufs, a:cadir, a:cafile)
|
|
||||||
retu a:mrufs
|
|
||||||
endf
|
|
||||||
fu! ctrlp#mrufiles#init() "{{{1
|
|
||||||
let s:locked = 0
|
|
||||||
aug CtrlPMRUF
|
|
||||||
au!
|
|
||||||
au BufReadPost,BufNewFile,BufWritePost *
|
|
||||||
\ cal ctrlp#mrufiles#list(expand('<abuf>', 1))
|
|
||||||
au QuickFixCmdPre *vimgrep* let s:locked = 1
|
|
||||||
au QuickFixCmdPost *vimgrep* let s:locked = 0
|
|
||||||
aug END
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/quickfix.vim
|
|
||||||
" Description: Quickfix extension
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Init {{{1
|
|
||||||
if exists('g:loaded_ctrlp_quickfix') && g:loaded_ctrlp_quickfix
|
|
||||||
fini
|
|
||||||
en
|
|
||||||
let g:loaded_ctrlp_quickfix = 1
|
|
||||||
|
|
||||||
let s:var_qf = ['ctrlp#quickfix#init()', 'ctrlp#quickfix#accept', 'quickfix',
|
|
||||||
\ 'qfx', [1]]
|
|
||||||
|
|
||||||
let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars)
|
|
||||||
\ ? add(g:ctrlp_ext_vars, s:var_qf) : [s:var_qf]
|
|
||||||
|
|
||||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
|
||||||
|
|
||||||
fu! s:lineout(dict)
|
|
||||||
retu printf('%s|%d:%d| %s', bufname(a:dict['bufnr']), a:dict['lnum'],
|
|
||||||
\ a:dict['col'], matchstr(a:dict['text'], '\s*\zs.*\S'))
|
|
||||||
endf
|
|
||||||
" Public {{{1
|
|
||||||
fu! ctrlp#quickfix#init()
|
|
||||||
let g:ctrlp_nolimit = 1
|
|
||||||
sy match CtrlPqfLineCol '|\zs\d\+:\d\+\ze|'
|
|
||||||
hi def link CtrlPqfLineCol Search
|
|
||||||
retu map(getqflist(), 's:lineout(v:val)')
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#quickfix#accept(mode, str)
|
|
||||||
let items = matchlist(a:str, '^\([^|]\+\ze\)|\(\d\+\):\(\d\+\)|')
|
|
||||||
let [md, filpath] = [a:mode, fnamemodify(items[1], ':p')]
|
|
||||||
if empty(filpath) | retu | en
|
|
||||||
cal ctrlp#exit()
|
|
||||||
let cmd = md == 't' ? 'tabe' : md == 'h' ? 'new' : md == 'v' ? 'vne'
|
|
||||||
\ : ctrlp#normcmd('e')
|
|
||||||
let cmd = cmd == 'e' && &modified ? 'hid e' : cmd
|
|
||||||
try
|
|
||||||
exe cmd.' '.ctrlp#fnesc(filpath)
|
|
||||||
cat
|
|
||||||
cal ctrlp#msg("Invalid command or argument.")
|
|
||||||
fina
|
|
||||||
cal cursor(items[2], items[3]) | sil! norm! zOzz
|
|
||||||
endt
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#quickfix#id()
|
|
||||||
retu s:id
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
|
|
@ -1,109 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/tag.vim
|
|
||||||
" Description: Tag file extension
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Init {{{1
|
|
||||||
if exists('g:loaded_ctrlp_tag') && g:loaded_ctrlp_tag
|
|
||||||
fini
|
|
||||||
en
|
|
||||||
let g:loaded_ctrlp_tag = 1
|
|
||||||
|
|
||||||
let s:tag_var = ['ctrlp#tag#init(s:tagfiles)', 'ctrlp#tag#accept',
|
|
||||||
\ 'tags', 'tag']
|
|
||||||
|
|
||||||
let g:ctrlp_ext_vars = exists('g:ctrlp_ext_vars') && !empty(g:ctrlp_ext_vars)
|
|
||||||
\ ? add(g:ctrlp_ext_vars, s:tag_var) : [s:tag_var]
|
|
||||||
|
|
||||||
let s:id = g:ctrlp_builtins + len(g:ctrlp_ext_vars)
|
|
||||||
" Utilities {{{1
|
|
||||||
fu! s:nodup(items)
|
|
||||||
let dict = {}
|
|
||||||
for each in a:items
|
|
||||||
cal extend(dict, { each : 0 })
|
|
||||||
endfo
|
|
||||||
retu keys(dict)
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:findcount(str)
|
|
||||||
let [tg, fname] = split(a:str, '\t\+\ze[^\t]\+$')
|
|
||||||
let [&l:tags, fname] = [s:ltags, expand(fname, 1)]
|
|
||||||
let tgs = taglist('^'.tg.'$')
|
|
||||||
if empty(tgs) | retu [1, 1] | en
|
|
||||||
let [fnd, ct, pos] = [0, 0, 0]
|
|
||||||
for each in tgs
|
|
||||||
let ct += 1
|
|
||||||
let fulname = fnamemodify(each["filename"], ':p')
|
|
||||||
if stridx(fulname, fname) >= 0
|
|
||||||
\ && strlen(fname) + stridx(fulname, fname) == strlen(fulname)
|
|
||||||
let fnd += 1
|
|
||||||
let pos = ct
|
|
||||||
en
|
|
||||||
if fnd > 1 | brea | en
|
|
||||||
endfo
|
|
||||||
retu [fnd, pos]
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! s:filter(tags)
|
|
||||||
let [nr, alltags] = [0, a:tags]
|
|
||||||
wh 0 < 1
|
|
||||||
if alltags[nr] =~ '^!' && alltags[nr] !~ '^!_TAG_'
|
|
||||||
let nr += 1
|
|
||||||
con
|
|
||||||
en
|
|
||||||
if alltags[nr] =~ '^!_TAG_' && len(alltags) > nr
|
|
||||||
cal remove(alltags, nr)
|
|
||||||
el
|
|
||||||
brea
|
|
||||||
en
|
|
||||||
endw
|
|
||||||
retu alltags
|
|
||||||
endf
|
|
||||||
" Public {{{1
|
|
||||||
fu! ctrlp#tag#init(tagfiles)
|
|
||||||
if empty(a:tagfiles) | retu [] | en
|
|
||||||
let tagfiles = sort(s:nodup(a:tagfiles))
|
|
||||||
let s:ltags = join(tagfiles, ',')
|
|
||||||
let g:ctrlp_alltags = []
|
|
||||||
for each in tagfiles
|
|
||||||
let alltags = s:filter(ctrlp#utils#readfile(each))
|
|
||||||
cal extend(g:ctrlp_alltags, alltags)
|
|
||||||
endfo
|
|
||||||
sy match CtrlPTabExtra '\zs\t.*\ze$'
|
|
||||||
hi link CtrlPTabExtra Comment
|
|
||||||
retu g:ctrlp_alltags
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#tag#accept(mode, str)
|
|
||||||
cal ctrlp#exit()
|
|
||||||
let str = matchstr(a:str, '^[^\t]\+\t\+[^\t]\+\ze\t')
|
|
||||||
let [md, tg] = [a:mode, split(str, '^[^\t]\+\zs\t')[0]]
|
|
||||||
let fnd = s:findcount(str)
|
|
||||||
let cmds = {
|
|
||||||
\ 't': ['tabe', 'tab stj'],
|
|
||||||
\ 'h': ['new', 'stj'],
|
|
||||||
\ 'v': ['vne', 'vert stj'],
|
|
||||||
\ 'e': ['ene', 'tj'],
|
|
||||||
\ }
|
|
||||||
let cmd = fnd[0] == 1 ? cmds[md][0] : cmds[md][1]
|
|
||||||
let cmd = cmd =~ 'tj\|ene' && &modified ? 'hid '.cmd : cmd
|
|
||||||
try
|
|
||||||
if fnd[0] == 1
|
|
||||||
exe cmd
|
|
||||||
let &l:tags = s:ltags
|
|
||||||
exe fnd[1].'ta' tg
|
|
||||||
el
|
|
||||||
exe cmd.' '.tg
|
|
||||||
en
|
|
||||||
cat
|
|
||||||
cal ctrlp#msg("Tag not found.")
|
|
||||||
endt
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#tag#id()
|
|
||||||
retu s:id
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
|
|
@ -1,68 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: autoload/ctrlp/utils.vim
|
|
||||||
" Description: Utilities
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
|
|
||||||
" Static variables {{{1
|
|
||||||
fu! ctrlp#utils#lash()
|
|
||||||
retu &ssl || !exists('+ssl') ? '/' : '\'
|
|
||||||
endf
|
|
||||||
let s:lash = ctrlp#utils#lash()
|
|
||||||
|
|
||||||
fu! ctrlp#utils#opts()
|
|
||||||
let s:cache_dir = $HOME.s:lash.'.ctrlp_cache'
|
|
||||||
if exists('g:ctrlp_cache_dir')
|
|
||||||
let s:cache_dir = expand(g:ctrlp_cache_dir, 1)
|
|
||||||
if isdirectory(s:cache_dir.s:lash.'.ctrlp_cache')
|
|
||||||
let s:cache_dir = s:cache_dir.s:lash.'.ctrlp_cache'
|
|
||||||
en
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
cal ctrlp#utils#opts()
|
|
||||||
" Files and Directories {{{1
|
|
||||||
fu! ctrlp#utils#cachedir()
|
|
||||||
retu s:cache_dir
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#utils#cachefile(...)
|
|
||||||
let tail = exists('a:1') ? '.'.a:1 : ''
|
|
||||||
let cache_file = substitute(getcwd(), '\([\/]\|^\a\zs:\)', '%', 'g').tail.'.txt'
|
|
||||||
retu exists('a:1') ? cache_file : s:cache_dir.s:lash.cache_file
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#utils#readfile(file)
|
|
||||||
if filereadable(a:file)
|
|
||||||
let data = readfile(a:file)
|
|
||||||
if empty(data) || type(data) != 3
|
|
||||||
unl data
|
|
||||||
let data = []
|
|
||||||
en
|
|
||||||
retu data
|
|
||||||
en
|
|
||||||
retu []
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#utils#mkdir(dir)
|
|
||||||
if exists('*mkdir') && !isdirectory(a:dir)
|
|
||||||
sil! cal mkdir(a:dir)
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#utils#writecache(lines, ...)
|
|
||||||
let cache_dir = exists('a:1') ? a:1 : s:cache_dir
|
|
||||||
cal ctrlp#utils#mkdir(cache_dir)
|
|
||||||
if isdirectory(cache_dir)
|
|
||||||
sil! cal writefile(a:lines, exists('a:2') ? a:2 : ctrlp#utils#cachefile())
|
|
||||||
if !exists('a:1')
|
|
||||||
let g:ctrlp_newcache = 0
|
|
||||||
en
|
|
||||||
en
|
|
||||||
endf
|
|
||||||
|
|
||||||
fu! ctrlp#utils#glob(...)
|
|
||||||
retu call('glob', v:version > 701 ? a:000 : a:1)
|
|
||||||
endf
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
" vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,163 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#getSwitchOrder()
|
|
||||||
return g:fuf_bookmarkdir_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkdir#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBookmarkDir', s:MODE_NAME, '""', [])
|
|
||||||
command! -bang -narg=? FufBookmarkDirAdd call s:bookmark(<q-args>)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:bookmark(word)
|
|
||||||
let item = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ }
|
|
||||||
|
|
||||||
let item.path = l9#inputHl('Question', '[fuf] Directory to bookmark:',
|
|
||||||
\ fnamemodify(getcwd(), ':p:~'), 'dir')
|
|
||||||
if item.path !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let item.word = l9#inputHl('Question', '[fuf] Bookmark as:',
|
|
||||||
\ fnamemodify(getcwd(), ':p:~'))
|
|
||||||
if item.word !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call insert(items, item)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_bookmarkdir_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call filter(items, 'v:val.word !=# a:word')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
if !empty(item)
|
|
||||||
execute ':cd ' . fnameescape(item.path)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_bookmarkdir_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#getSwitchOrder()
|
|
||||||
return g:fuf_bookmarkfile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#bookmarkfile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBookmarkFile', s:MODE_NAME, '""', [])
|
|
||||||
command! -bang -narg=? FufBookmarkFileAdd call s:bookmarkHere(<q-args>)
|
|
||||||
command! -bang -narg=0 -range FufBookmarkFileAddAsSelectedText call s:bookmarkHere(l9#getSelectedText())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
" opens a:path and jumps to the line matching to a:pattern from a:lnum within
|
|
||||||
" a:range. if not found, jumps to a:lnum.
|
|
||||||
function s:jumpToBookmark(path, mode, pattern, lnum)
|
|
||||||
call fuf#openFile(a:path, a:mode, g:fuf_reuseWindow)
|
|
||||||
call cursor(s:getMatchingLineNumber(getline(1, '$'), a:pattern, a:lnum), 0)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getMatchingLineNumber(lines, pattern, lnumBegin)
|
|
||||||
let l = min([a:lnumBegin, len(a:lines)])
|
|
||||||
for [l0, l1] in map(range(0, g:fuf_bookmarkfile_searchRange),
|
|
||||||
\ '[l + v:val, l - v:val]')
|
|
||||||
if l0 <= len(a:lines) && a:lines[l0 - 1] =~# a:pattern
|
|
||||||
return l0
|
|
||||||
elseif l1 >= 0 && a:lines[l1 - 1] =~# a:pattern
|
|
||||||
return l1
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return l
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getLinePattern(lnum)
|
|
||||||
return '\C\V\^' . escape(getline(a:lnum), '\') . '\$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:bookmarkHere(word)
|
|
||||||
if !empty(&buftype) || expand('%') !~ '\S'
|
|
||||||
call fuf#echoWarning('Can''t bookmark this buffer.')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let item = {
|
|
||||||
\ 'word' : (a:word =~# '\S' ? substitute(a:word, '\n', ' ', 'g')
|
|
||||||
\ : pathshorten(expand('%:p:~')) . '|' . line('.') . '| ' . getline('.')),
|
|
||||||
\ 'path' : expand('%:p'),
|
|
||||||
\ 'lnum' : line('.'),
|
|
||||||
\ 'pattern' : s:getLinePattern(line('.')),
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ }
|
|
||||||
let item.word = l9#inputHl('Question', '[fuf] Bookmark as:', item.word)
|
|
||||||
if item.word !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call insert(items, item)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_bookmarkfile_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
let lines = fuf#getFileLines(item.path)
|
|
||||||
if empty(lines)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let index = s:getMatchingLineNumber(lines, item.pattern, item.lnum) - 1
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [index], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call filter(items, 'v:val.word !=# a:word')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
|
|
||||||
if !empty(item)
|
|
||||||
call s:jumpToBookmark(item.path, a:mode, item.pattern, item.lnum)
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_bookmarkfile_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,189 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#getSwitchOrder()
|
|
||||||
return g:fuf_buffer_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffer#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBuffer', s:MODE_NAME, '""', [])
|
|
||||||
augroup fuf#buffer
|
|
||||||
autocmd!
|
|
||||||
autocmd BufEnter * call s:updateBufTimes()
|
|
||||||
autocmd BufWritePost * call s:updateBufTimes()
|
|
||||||
augroup END
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
let s:bufTimes = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateBufTimes()
|
|
||||||
let s:bufTimes[bufnr('%')] = localtime()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(nr)
|
|
||||||
let fname = (empty(bufname(a:nr))
|
|
||||||
\ ? '[No Name]'
|
|
||||||
\ : fnamemodify(bufname(a:nr), ':p:~:.'))
|
|
||||||
let time = (exists('s:bufTimes[a:nr]') ? s:bufTimes[a:nr] : 0)
|
|
||||||
let item = fuf#makePathItem(fname, strftime(g:fuf_timeFormat, time), 0)
|
|
||||||
let item.index = a:nr
|
|
||||||
let item.bufNr = a:nr
|
|
||||||
let item.time = time
|
|
||||||
let item.abbrPrefix = s:getBufIndicator(a:nr) . ' '
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getBufIndicator(bufNr)
|
|
||||||
if !getbufvar(a:bufNr, '&modifiable')
|
|
||||||
return '[-]'
|
|
||||||
elseif getbufvar(a:bufNr, '&modified')
|
|
||||||
return '[+]'
|
|
||||||
elseif getbufvar(a:bufNr, '&readonly')
|
|
||||||
return '[R]'
|
|
||||||
else
|
|
||||||
return ' '
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:compareTimeDescending(i1, i2)
|
|
||||||
return a:i1.time == a:i2.time ? 0 : a:i1.time > a:i2.time ? -1 : +1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:findItem(items, word)
|
|
||||||
for item in a:items
|
|
||||||
if item.word ==# a:word
|
|
||||||
return item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_buffer_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let item = s:findItem(self.items, a:word)
|
|
||||||
if empty(item)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
return fuf#makePreviewLinesForFile(item.bufNr, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
" not use bufnr(a:word) in order to handle unnamed buffer
|
|
||||||
let item = s:findItem(self.items, a:word)
|
|
||||||
if empty(item)
|
|
||||||
" do nothing
|
|
||||||
elseif a:mode ==# s:OPEN_TYPE_DELETE
|
|
||||||
execute item.bufNr . 'bdelete'
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
else
|
|
||||||
call fuf#openBuffer(item.bufNr, a:mode, g:fuf_reuseWindow)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_buffer_keyDelete,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_DELETE . ')')
|
|
||||||
let self.items = range(1, bufnr('$'))
|
|
||||||
call filter(self.items, 'buflisted(v:val) && v:val != self.bufNrPrev && v:val != bufnr("%")')
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
if g:fuf_buffer_mruOrder
|
|
||||||
call sort(self.items, 's:compareTimeDescending')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
endif
|
|
||||||
let self.items = fuf#mapToSetAbbrWithSnippedWordAsPath(self.items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,300 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#getSwitchOrder()
|
|
||||||
return g:fuf_buffertag_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#renewCache()
|
|
||||||
let s:tagItemsCache = {}
|
|
||||||
let s:tagDataCache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#buffertag#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTag', s:MODE_NAME, '""',
|
|
||||||
\ [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAll', s:MODE_NAME, '""',
|
|
||||||
\ [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagWithCursorWord', s:MODE_NAME,
|
|
||||||
\ 'expand(''<cword>'')', [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAllWithCursorWord', s:MODE_NAME,
|
|
||||||
\ 'expand(''<cword>'')', [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagWithSelectedText', s:MODE_NAME,
|
|
||||||
\ 'l9#getSelectedText()', [['g:fuf_buffertag_forAll', 0]])
|
|
||||||
call fuf#defineLaunchCommand('FufBufferTagAllWithSelectedText', s:MODE_NAME,
|
|
||||||
\ 'l9#getSelectedText()', [['g:fuf_buffertag_forAll', 1]])
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag_forAll', 0) " private option
|
|
||||||
" the following settings originate from taglist.vim
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__asm' , '--language-force=asm --asm-types=dlmt')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__aspperl' , '--language-force=asp --asp-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__aspvbs' , '--language-force=asp --asp-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__awk' , '--language-force=awk --awk-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__beta' , '--language-force=beta --beta-types=fsv')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__c' , '--language-force=c --c-types=dgsutvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cpp' , '--language-force=c++ --c++-types=nvdtcgsuf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cs' , '--language-force=c# --c#-types=dtncEgsipm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__cobol' , '--language-force=cobol --cobol-types=dfgpPs')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__eiffel' , '--language-force=eiffel --eiffel-types=cf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__erlang' , '--language-force=erlang --erlang-types=drmf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__expect' , '--language-force=tcl --tcl-types=cfp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__fortran' , '--language-force=fortran --fortran-types=pbceiklmntvfs')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__html' , '--language-force=html --html-types=af')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__java' , '--language-force=java --java-types=pcifm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__javascript', '--language-force=javascript --javascript-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__lisp' , '--language-force=lisp --lisp-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__lua' , '--language-force=lua --lua-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__make' , '--language-force=make --make-types=m')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__pascal' , '--language-force=pascal --pascal-types=fp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__perl' , '--language-force=perl --perl-types=clps')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__php' , '--language-force=php --php-types=cdvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__python' , '--language-force=python --python-types=cmf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__rexx' , '--language-force=rexx --rexx-types=s')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__ruby' , '--language-force=ruby --ruby-types=cfFm')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__scheme' , '--language-force=scheme --scheme-types=sf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__csh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__zsh' , '--language-force=sh --sh-types=f')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__slang' , '--language-force=slang --slang-types=nf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sml' , '--language-force=sml --sml-types=ecsrtvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__sql' , '--language-force=sql --sql-types=cFPrstTvfp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__tcl' , '--language-force=tcl --tcl-types=cfmp')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__vera' , '--language-force=vera --vera-types=cdefgmpPtTvx')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__verilog' , '--language-force=verilog --verilog-types=mcPertwpvf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__vim' , '--language-force=vim --vim-types=avf')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag__yacc' , '--language-force=yacc --yacc-types=l')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseTagLine(line)
|
|
||||||
" tag W:\Win32\SRC7\NCSIM\NCVW32\CUBEFACE.H /^#define CUBEFACE_H$/;" macro line:4
|
|
||||||
let fields = matchlist(a:line, '\v^([^\t]+)\t(.+)\t\/\^(.+)\$\/\;\"\t(.+)\tline\:(\d+)')
|
|
||||||
if empty(fields)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'tag' : fields[1],
|
|
||||||
\ 'fname' : fields[2],
|
|
||||||
\ 'pattern': fields[3],
|
|
||||||
\ 'kind' : fields[4],
|
|
||||||
\ 'lnum' : str2nr(fields[5]),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
let s:TEMP_VARIABLES_GROUP = expand('<sfile>:p')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getFileType(bufNr)
|
|
||||||
let ft = getbufvar(a:bufNr, '&filetype')
|
|
||||||
if !empty(ft) || bufloaded(a:bufNr)
|
|
||||||
return ft
|
|
||||||
endif
|
|
||||||
let ft = getbufvar(a:bufNr, 'fuf_buffertag_filetype')
|
|
||||||
if !empty(ft)
|
|
||||||
return ft
|
|
||||||
endif
|
|
||||||
call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP, '&eventignore', 'FileType')
|
|
||||||
call l9#tempvariables#set(s:TEMP_VARIABLES_GROUP, '&filetype', &filetype)
|
|
||||||
" from taglist.vim
|
|
||||||
execute 'doautocmd filetypedetect BufRead ' . bufname(a:bufNr)
|
|
||||||
let ft = &filetype
|
|
||||||
call l9#tempvariables#end(s:TEMP_VARIABLES_GROUP)
|
|
||||||
call setbufvar(a:bufNr, 'fuf_buffertag_filetype', ft)
|
|
||||||
return ft
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeCtagsCmd(bufNr)
|
|
||||||
let ft = s:getFileType(a:bufNr)
|
|
||||||
if !exists('g:fuf_buffertag__{ft}')
|
|
||||||
return ''
|
|
||||||
endif
|
|
||||||
"
|
|
||||||
let cmd = join([g:fuf_buffertag_ctagsPath,
|
|
||||||
\ '-f - --sort=no --excmd=pattern --fields=nKs',
|
|
||||||
\ g:fuf_buffertag__{ft},
|
|
||||||
\ shellescape(fnamemodify(bufname(a:bufNr), ':p'))])
|
|
||||||
return cmd
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTagItems(bufNr)
|
|
||||||
let cmd = s:makeCtagsCmd(a:bufNr)
|
|
||||||
if empty(cmd)
|
|
||||||
return []
|
|
||||||
elseif !exists('s:tagItemsCache[cmd]') ||
|
|
||||||
\ s:tagItemsCache[cmd].time < getftime(expand(bufname(a:bufNr)))
|
|
||||||
let items = split(system(cmd), "\n")
|
|
||||||
if v:shell_error
|
|
||||||
call fuf#echoError([cmd] + items)
|
|
||||||
throw "Command error"
|
|
||||||
endif
|
|
||||||
call map(items, 's:parseTagLine(v:val)')
|
|
||||||
call filter(items, '!empty(v:val)')
|
|
||||||
let s:tagItemsCache[cmd] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : items,
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:tagItemsCache[cmd].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(tag, itemMap)
|
|
||||||
let menu = fnamemodify(a:itemMap[a:tag][0].fname, ':t')
|
|
||||||
\ . ' [' . a:itemMap[a:tag][0].kind . ']'
|
|
||||||
if len(a:itemMap[a:tag]) > 1
|
|
||||||
let menu .= ' (' . len(a:itemMap[a:tag]) . ')'
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(a:tag, menu)
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTagData(bufNrs)
|
|
||||||
let key = join([0] + sort(copy(a:bufNrs)), "\n")
|
|
||||||
let bufNames = map(copy(a:bufNrs), 'bufname(v:val)')
|
|
||||||
if !exists('s:tagDataCache[key]') ||
|
|
||||||
\ fuf#countModifiedFiles(bufNames, s:tagDataCache[key].time) > 0
|
|
||||||
let itemMap = {}
|
|
||||||
for item in l9#concat(map(copy(a:bufNrs), 's:getTagItems(v:val)'))
|
|
||||||
if !exists('itemMap[item.tag]')
|
|
||||||
let itemMap[item.tag] = []
|
|
||||||
endif
|
|
||||||
call add(itemMap[item.tag], item)
|
|
||||||
endfor
|
|
||||||
let items = sort(keys(itemMap))
|
|
||||||
call map(items, 's:makeItem(v:val, itemMap)')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
call map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
let s:tagDataCache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'itemMap': itemMap,
|
|
||||||
\ 'items' : items,
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return [s:tagDataCache[key].items, s:tagDataCache[key].itemMap]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:jumpToTag(item, mode)
|
|
||||||
call fuf#openFile(a:item.fname, a:mode, g:fuf_reuseWindow)
|
|
||||||
call cursor(a:item.lnum, 1)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_buffertag_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if !exists('self.itemMap[a:word][0]')
|
|
||||||
call fuf#echoError('Definition not found:' . a:word)
|
|
||||||
return
|
|
||||||
elseif len(self.itemMap[a:word]) == 1
|
|
||||||
let i = 0
|
|
||||||
else
|
|
||||||
let list = map(fuf#mapToSetSerialIndex(copy(self.itemMap[a:word]), 1),
|
|
||||||
\ 'printf(" %2d: %s|%d| [%s] %s",v:val.index, fnamemodify(v:val.fname, ":~:."), v:val.lnum, v:val.kind, v:val.pattern)')
|
|
||||||
let i = inputlist(['Select a definition of "' . a:word . '":'] + list) - 1
|
|
||||||
endif
|
|
||||||
if 0 <= i && i < len(self.itemMap[a:word])
|
|
||||||
call s:jumpToTag(self.itemMap[a:word][i], a:mode)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
if g:fuf_buffertag_forAll
|
|
||||||
let bufNrs = filter(range(1, bufnr('$')), 'buflisted(v:val)')
|
|
||||||
else
|
|
||||||
let bufNrs = [self.bufNrPrev]
|
|
||||||
endif
|
|
||||||
let [self.items, self.itemMap] = s:getTagData(bufNrs)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,137 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackfile#launch(initialPattern, partialMatching, prompt, exclude, listener)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:exclude = a:exclude
|
|
||||||
let s:listener = a:listener
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = getcwd() . g:fuf_ignoreCase . s:exclude . "\n" . a:dir
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, s:exclude)
|
|
||||||
if isdirectory(a:dir)
|
|
||||||
call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0))
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
let items = copy(s:enumItems(fuf#splitPath(a:patternPrimary).head))
|
|
||||||
return filter(items, 'bufnr("^" . v:val.word . "$") != self.bufNrPrev')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:listener.onComplete(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
if !a:opened && exists('s:listener.onAbort()')
|
|
||||||
call s:listener.onAbort()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#callbackitem#launch(initialPattern, partialMatching, prompt, listener, items, forPath)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:listener = a:listener
|
|
||||||
let s:forPath = a:forPath
|
|
||||||
let s:items = copy(a:items)
|
|
||||||
if s:forPath
|
|
||||||
call map(s:items, 'fuf#makePathItem(v:val, "", 1)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items)
|
|
||||||
else
|
|
||||||
call map(s:items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endif
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
if s:forPath
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endif
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
let parser = (s:forPath
|
|
||||||
\ ? 's:interpretPrimaryPatternForPath'
|
|
||||||
\ : 's:interpretPrimaryPatternForNonPath')
|
|
||||||
return fuf#makePatternSet(a:patternBase, parser, self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
if s:forPath
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endif
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:listener.onComplete(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
if !a:opened && exists('s:listener.onAbort()')
|
|
||||||
call s:listener.onAbort()
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,172 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#getSwitchOrder()
|
|
||||||
return g:fuf_changelist_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#changelist#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufChangeList', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getChangesLines()
|
|
||||||
redir => result
|
|
||||||
:silent changes
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseChangesLine(line)
|
|
||||||
" return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$')
|
|
||||||
if empty(elements)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'prefix': elements[1],
|
|
||||||
\ 'count' : elements[2],
|
|
||||||
\ 'lnum' : elements[3],
|
|
||||||
\ 'text' : printf('|%d:%d|%s', elements[3], elements[4], elements[5]),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(line)
|
|
||||||
let parsed = s:parseChangesLine(a:line)
|
|
||||||
if empty(parsed)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(parsed.text, '')
|
|
||||||
let item.abbrPrefix = parsed.prefix
|
|
||||||
let item.lnum = parsed.lnum
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_changelist_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(self.bufNrPrev)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
let older = 0
|
|
||||||
for line in reverse(s:getChangesLines())
|
|
||||||
if stridx(line, '>') == 0
|
|
||||||
let older = 1
|
|
||||||
endif
|
|
||||||
let parsed = s:parseChangesLine(line)
|
|
||||||
if !empty(parsed) && parsed.text ==# a:word
|
|
||||||
if parsed.count != 0
|
|
||||||
execute 'normal! ' . parsed.count . (older ? 'g;' : 'g,') . 'zvzz'
|
|
||||||
endif
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.items = s:getChangesLines()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
call filter(self.items, '!empty(v:val)')
|
|
||||||
call reverse(self.items)
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#getSwitchOrder()
|
|
||||||
return g:fuf_coveragefile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#getEditableDataNames()
|
|
||||||
return ['coverages']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#coveragefile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufCoverageFile', s:MODE_NAME, '""', [])
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_name', '') " private option
|
|
||||||
command! -bang -narg=0 FufCoverageFileRegister call s:registerCoverage()
|
|
||||||
command! -bang -narg=? FufCoverageFileChange call s:changeCoverage(<q-args>)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems()
|
|
||||||
let key = join([getcwd(), g:fuf_ignoreCase, g:fuf_coveragefile_exclude,
|
|
||||||
\ g:fuf_coveragefile_globPatterns], "\n")
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = l9#concat(map(copy(g:fuf_coveragefile_globPatterns),
|
|
||||||
\ 'fuf#glob(v:val)'))
|
|
||||||
call filter(s:cache[key], 'filereadable(v:val)') " filter out directories
|
|
||||||
call map(s:cache[key], 'fuf#makePathItem(fnamemodify(v:val, ":~:."), "", 0)')
|
|
||||||
if len(g:fuf_coveragefile_exclude)
|
|
||||||
call filter(s:cache[key], 'v:val.word !~ g:fuf_coveragefile_exclude')
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:registerCoverage()
|
|
||||||
let patterns = []
|
|
||||||
while 1
|
|
||||||
let pattern = l9#inputHl('Question', '[fuf] Glob pattern for coverage (<Esc> and end):',
|
|
||||||
\ '', 'file')
|
|
||||||
if pattern !~ '\S'
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
call add(patterns, pattern)
|
|
||||||
endwhile
|
|
||||||
if empty(patterns)
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
echo '[fuf] patterns: ' . string(patterns)
|
|
||||||
let name = l9#inputHl('Question', '[fuf] Coverage name:')
|
|
||||||
if name !~ '\S'
|
|
||||||
call fuf#echoWarning('Canceled')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let coverages = fuf#loadDataFile(s:MODE_NAME, 'coverages')
|
|
||||||
call insert(coverages, {'name': name, 'patterns': patterns})
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'coverages', coverages)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:createChangeCoverageListener()
|
|
||||||
let listener = {}
|
|
||||||
|
|
||||||
function listener.onComplete(name, method)
|
|
||||||
call s:changeCoverage(a:name)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
return listener
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:changeCoverage(name)
|
|
||||||
let coverages = fuf#loadDataFile(s:MODE_NAME, 'coverages')
|
|
||||||
if a:name !~ '\S'
|
|
||||||
let names = map(copy(coverages), 'v:val.name')
|
|
||||||
call fuf#callbackitem#launch('', 0, '>Coverage>', s:createChangeCoverageListener(), names, 0)
|
|
||||||
return
|
|
||||||
else
|
|
||||||
let name = a:name
|
|
||||||
endif
|
|
||||||
call filter(coverages, 'v:val.name ==# name')
|
|
||||||
if empty(coverages)
|
|
||||||
call fuf#echoError('Coverage not found: ' . name)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
call fuf#setOneTimeVariables(
|
|
||||||
\ ['g:fuf_coveragefile_globPatterns', coverages[0].patterns],
|
|
||||||
\ ['g:fuf_coveragefile_name' , a:name]
|
|
||||||
\ )
|
|
||||||
FufCoverageFile
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
let nameString = (empty(g:fuf_coveragefile_name) ? ''
|
|
||||||
\ : '[' . g:fuf_coveragefile_name . ']')
|
|
||||||
return fuf#formatPrompt(g:fuf_coveragefile_prompt, self.partialMatching,
|
|
||||||
\ nameString)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':~:.')
|
|
||||||
let self.items = copy(s:enumItems())
|
|
||||||
call filter(self.items, 'v:val.word !=# bufNamePrev')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#getSwitchOrder()
|
|
||||||
return g:fuf_dir_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#dir#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufDir' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufDirWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')', [])
|
|
||||||
call fuf#defineLaunchCommand('FufDirWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = getcwd() . g:fuf_ignoreCase . g:fuf_dir_exclude . "\n" . a:dir
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_dir_exclude)
|
|
||||||
call filter(s:cache[key], 'v:val.word =~# ''[/\\]$''')
|
|
||||||
if isdirectory(a:dir)
|
|
||||||
call insert(s:cache[key], fuf#makePathItem(a:dir . '.', '', 0))
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_dir_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ fuf#glob(fnamemodify(a:word, ':p') . '*'),
|
|
||||||
\ [], a:count, self.getPreviewHeight())
|
|
||||||
return
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumItems(fuf#splitPath(a:patternPrimary).head)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
execute ':cd ' . fnameescape(a:word)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,139 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#getSwitchOrder()
|
|
||||||
return g:fuf_file_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#file#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufFile' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufFileWithFullCwd' , s:MODE_NAME, 'fnamemodify(getcwd(), '':p'')', [])
|
|
||||||
call fuf#defineLaunchCommand('FufFileWithCurrentBufferDir', s:MODE_NAME, 'expand(''%:~:.'')[:-1-len(expand(''%:~:.:t''))]', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumItems(dir)
|
|
||||||
let key = join([getcwd(), g:fuf_ignoreCase, g:fuf_file_exclude, a:dir], "\n")
|
|
||||||
if !exists('s:cache[key]')
|
|
||||||
let s:cache[key] = fuf#enumExpandedDirsEntries(a:dir, g:fuf_file_exclude)
|
|
||||||
call fuf#mapToSetSerialIndex(s:cache[key], 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:cache[key])
|
|
||||||
endif
|
|
||||||
return s:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumNonCurrentItems(dir, bufNrPrev, cache)
|
|
||||||
let key = a:dir . 'AVOIDING EMPTY KEY'
|
|
||||||
if !exists('a:cache[key]')
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = bufname(a:bufNrPrev)
|
|
||||||
let a:cache[key] =
|
|
||||||
\ filter(copy(s:enumItems(a:dir)), 'v:val.word !=# bufNamePrev')
|
|
||||||
endif
|
|
||||||
return a:cache[key]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_file_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return a:enteredPattern =~# '[^/\\]$'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPathTail',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumNonCurrentItems(
|
|
||||||
\ fuf#splitPath(a:patternPrimary).head, self.bufNrPrev, self.cache)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givencmd#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = copy(a:items)
|
|
||||||
call map(s:items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:word[0] =~# '[:/?]'
|
|
||||||
call histadd(a:word[0], a:word[1:])
|
|
||||||
endif
|
|
||||||
call feedkeys(a:word . "\<CR>", 'n')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givendir#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = map(copy(a:items), 'substitute(v:val, ''[/\\]\?$'', "", "")')
|
|
||||||
let s:items = map(s:items, 'fuf#makePathItem(v:val, "", 0)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(s:items)
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ fuf#glob(fnamemodify(a:word, ':p') . '*'),
|
|
||||||
\ [], a:count, self.getPreviewHeight())
|
|
||||||
return
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
execute ':cd ' . fnameescape(a:word)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#getSwitchOrder()
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#onInit()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#givenfile#launch(initialPattern, partialMatching, prompt, items)
|
|
||||||
let s:prompt = (empty(a:prompt) ? '>' : a:prompt)
|
|
||||||
let s:items = map(copy(a:items), 'fuf#makePathItem(v:val, "", 0)')
|
|
||||||
call fuf#mapToSetSerialIndex(s:items, 1)
|
|
||||||
call map(s:items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#launch(s:MODE_NAME, a:initialPattern, a:partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(s:prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,198 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#getSwitchOrder()
|
|
||||||
return g:fuf_help_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#help#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufHelp' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufHelpWithCursorWord', s:MODE_NAME, 'expand(''<cword>'')', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getCurrentHelpTagFiles()
|
|
||||||
let prefix = 'doc' . l9#getPathSeparator()
|
|
||||||
let tagFiles = split(globpath(&runtimepath, prefix . 'tags' ), "\n")
|
|
||||||
\ + split(globpath(&runtimepath, prefix . 'tags-??'), "\n")
|
|
||||||
return sort(map(tagFiles, 'fnamemodify(v:val, ":p")'))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseHelpTagEntry(line, tagFile)
|
|
||||||
let elements = split(a:line, "\t")
|
|
||||||
if len(elements) != 3 || elements[0][0] ==# '!'
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let suffix = matchstr(a:tagFile, '-\zs..$')
|
|
||||||
if empty(suffix)
|
|
||||||
let suffix = '@en'
|
|
||||||
else
|
|
||||||
let suffix = '@' . suffix
|
|
||||||
endif
|
|
||||||
let dir = fnamemodify(a:tagFile, ':h') . l9#getPathSeparator()
|
|
||||||
return {
|
|
||||||
\ 'word' : elements[0] . suffix,
|
|
||||||
\ 'path' : dir . elements[1],
|
|
||||||
\ 'pattern': elements[2][1:],
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getHelpTagEntries(tagFile)
|
|
||||||
let names = map(l9#readFile(a:tagFile), 's:parseHelpTagEntry(v:val, a:tagFile)')
|
|
||||||
return filter(names, '!empty(v:val)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseHelpTagFiles(tagFiles, key)
|
|
||||||
let cacheName = 'cache-' . l9#hash224(a:key)
|
|
||||||
let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
|
|
||||||
if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
|
|
||||||
return fuf#loadDataFile(s:MODE_NAME, cacheName)
|
|
||||||
endif
|
|
||||||
let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getHelpTagEntries(v:val)')))
|
|
||||||
let items = map(items, 'extend(v:val, fuf#makeNonPathItem(v:val.word, ""))')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
|
|
||||||
return items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumHelpTags(tagFiles)
|
|
||||||
if !len(a:tagFiles)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let key = join([g:fuf_ignoreCase] + a:tagFiles, "\n")
|
|
||||||
if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time)
|
|
||||||
let s:cache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : s:parseHelpTagFiles(a:tagFiles, key)
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:cache[key].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getMatchingIndex(lines, pattern)
|
|
||||||
if empty(a:pattern)
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
for i in range(len(a:lines))
|
|
||||||
if stridx(a:lines[i], a:pattern) >= 0
|
|
||||||
return i
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_help_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(s:enumHelpTags(self.tagFiles)), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].path)
|
|
||||||
let index = s:getMatchingIndex(lines, items[0].pattern)
|
|
||||||
return [items[0].path . ':'] + fuf#makePreviewLinesAround(
|
|
||||||
\ lines, (index < 0 ? [] : [index]), a:count, self.getPreviewHeight() - 1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumHelpTags(self.tagFiles)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openHelp(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.tagFiles = s:getCurrentHelpTagFiles()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,182 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#getSwitchOrder()
|
|
||||||
return g:fuf_jumplist_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#jumplist#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufJumpList', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getJumpsLines()
|
|
||||||
redir => result
|
|
||||||
:silent jumps
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseJumpsLine(line, bufnrPrev)
|
|
||||||
"return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
let elements = matchlist(a:line, '\v^(.)\s*(\d+)\s+(\d+)\s+(\d+)\s*(.*)$')
|
|
||||||
if empty(elements)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let linePrevBuffer = join(getbufline(a:bufnrPrev, elements[3]))
|
|
||||||
if stridx(linePrevBuffer, elements[5]) >= 0
|
|
||||||
let fname = bufname(a:bufnrPrev)
|
|
||||||
let text = elements[5]
|
|
||||||
else
|
|
||||||
let fname = elements[5]
|
|
||||||
let text = join(getbufline('^' . elements[5] . '$', elements[3]))
|
|
||||||
endif
|
|
||||||
return {
|
|
||||||
\ 'prefix': elements[1],
|
|
||||||
\ 'count' : elements[2],
|
|
||||||
\ 'lnum' : elements[3],
|
|
||||||
\ 'fname' : fname,
|
|
||||||
\ 'text' : printf('%s|%d:%d|%s', fname, elements[3], elements[4], text),
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(line, bufnrPrev)
|
|
||||||
let parsed = s:parseJumpsLine(a:line, a:bufnrPrev)
|
|
||||||
if empty(parsed)
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(parsed.text, '')
|
|
||||||
let item.abbrPrefix = parsed.prefix
|
|
||||||
let item.lnum = parsed.lnum
|
|
||||||
let item.fname = parsed.fname
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_jumplist_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].fname)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
let older = 0
|
|
||||||
for line in reverse(s:getJumpsLines())
|
|
||||||
if stridx(line, '>') == 0
|
|
||||||
let older = 1
|
|
||||||
endif
|
|
||||||
let parsed = s:parseJumpsLine(line, self.bufNrPrev)
|
|
||||||
if !empty(parsed) && parsed.text ==# a:word
|
|
||||||
if parsed.count != 0
|
|
||||||
execute 'normal! ' . parsed.count . (older ? "\<C-o>" : "\<C-i>") . 'zvzz'
|
|
||||||
endif
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.items = s:getJumpsLines()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
call map(self.items, 's:makeItem(v:val, self.bufNrPrev)')
|
|
||||||
call filter(self.items, '!empty(v:val)')
|
|
||||||
call reverse(self.items)
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
@ -1,135 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#getSwitchOrder()
|
|
||||||
return g:fuf_line_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#line#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufLine', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_DELETE = -1
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_line_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(self.bufNrPrev)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].index - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
call filter(self.items, 'v:val.word ==# a:word')
|
|
||||||
if empty(self.items)
|
|
||||||
return
|
|
||||||
execute 'cc ' . self.items[0].index
|
|
||||||
endif
|
|
||||||
call cursor(self.items[0].index, 0)
|
|
||||||
normal! zvzz
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let tab = repeat(' ', getbufvar(self.bufNrPrev, '&tabstop'))
|
|
||||||
let self.items = getbufline(self.bufNrPrev, 1, '$')
|
|
||||||
let lnumFormat = '%' . len(string(len(self.items) + 1)) . 'd|'
|
|
||||||
for i in range(len(self.items))
|
|
||||||
let self.items[i] = printf(lnumFormat, i + 1)
|
|
||||||
\ . substitute(self.items[i], "\t", tab, 'g')
|
|
||||||
endfor
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 0)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,134 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#getSwitchOrder()
|
|
||||||
return g:fuf_mrucmd_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#getEditableDataNames()
|
|
||||||
return ['items']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#requiresOnCommandPre()
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufMruCmd', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrucmd#onCommandPre(cmd)
|
|
||||||
if getcmdtype() =~# '^[:/?]'
|
|
||||||
call s:updateInfo(a:cmd)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateInfo(cmd)
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
let items = fuf#updateMruList(
|
|
||||||
\ items, { 'word' : a:cmd, 'time' : localtime() },
|
|
||||||
\ g:fuf_mrucmd_maxItem, g:fuf_mrucmd_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_mrucmd_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call s:updateInfo(a:word)
|
|
||||||
call histadd(a:word[0], a:word[1:])
|
|
||||||
call feedkeys(a:word . "\<CR>", 'n')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#getSwitchOrder()
|
|
||||||
return g:fuf_mrufile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#getEditableDataNames()
|
|
||||||
return ['items', 'itemdirs']
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
let s:aroundCache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#mrufile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufMruFile', s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufMruFileInCwd', s:MODE_NAME,
|
|
||||||
\ '""', [['g:fuf_mrufile_underCwd', 1]])
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_underCwd', 0) " private option
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_searchAroundLevel', -1) " private option
|
|
||||||
augroup fuf#mrufile
|
|
||||||
autocmd!
|
|
||||||
autocmd BufEnter * call s:updateData()
|
|
||||||
autocmd BufWritePost * call s:updateData()
|
|
||||||
augroup END
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
let s:OPEN_TYPE_EXPAND = -1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:updateData()
|
|
||||||
if !empty(&buftype) || !filereadable(expand('%'))
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
let items = fuf#updateMruList(
|
|
||||||
\ items, { 'word' : expand('%:p'), 'time' : localtime() },
|
|
||||||
\ g:fuf_mrufile_maxItem, g:fuf_mrufile_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'items', items)
|
|
||||||
call s:removeItemFromCache(expand('%:p'))
|
|
||||||
let itemDirs = fuf#loadDataFile(s:MODE_NAME, 'itemdirs')
|
|
||||||
let itemDirs = fuf#updateMruList(
|
|
||||||
\ itemDirs, { 'word' : expand('%:p:h') },
|
|
||||||
\ g:fuf_mrufile_maxItemDir, g:fuf_mrufile_exclude)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, 'itemdirs', itemDirs)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:removeItemFromCache(word)
|
|
||||||
for items in values(s:cache)
|
|
||||||
if exists('items[a:word]')
|
|
||||||
unlet items[a:word]
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" returns empty value if invalid item
|
|
||||||
function s:formatItemUsingCache(item)
|
|
||||||
if a:item.word !~ '\S'
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
if !exists('s:cache[a:item.word]')
|
|
||||||
if filereadable(a:item.word)
|
|
||||||
let s:cache[a:item.word] = fuf#makePathItem(
|
|
||||||
\ fnamemodify(a:item.word, ':p:~'), strftime(g:fuf_timeFormat, a:item.time), 0)
|
|
||||||
else
|
|
||||||
let s:cache[a:item.word] = {}
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:cache[a:item.word]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:expandSearchDir(dir, level)
|
|
||||||
let dirs = [a:dir]
|
|
||||||
let dirPrev = a:dir
|
|
||||||
for i in range(a:level)
|
|
||||||
let dirPrev = l9#concatPaths([dirPrev, '*'])
|
|
||||||
call add(dirs, dirPrev)
|
|
||||||
endfor
|
|
||||||
let dirPrev = a:dir
|
|
||||||
for i in range(a:level)
|
|
||||||
let dirPrevPrev = dirPrev
|
|
||||||
let dirPrev = fnamemodify(dirPrev, ':h')
|
|
||||||
if dirPrevPrev ==# dirPrev
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
call add(dirs, dirPrev)
|
|
||||||
endfor
|
|
||||||
return dirs
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:listAroundFiles(dir)
|
|
||||||
if !exists('s:aroundCache[a:dir]')
|
|
||||||
let s:aroundCache[a:dir] = [a:dir] +
|
|
||||||
\ fuf#glob(l9#concatPaths([a:dir, '*' ])) +
|
|
||||||
\ fuf#glob(l9#concatPaths([a:dir, '.*']))
|
|
||||||
call filter(s:aroundCache[a:dir], 'filereadable(v:val)')
|
|
||||||
call map(s:aroundCache[a:dir], 'fuf#makePathItem(fnamemodify(v:val, ":~"), "", 0)')
|
|
||||||
if len(g:fuf_mrufile_exclude)
|
|
||||||
call filter(s:aroundCache[a:dir], 'v:val.word !~ g:fuf_mrufile_exclude')
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return s:aroundCache[a:dir]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
let cwdString = (g:fuf_mrufile_underCwd ? '[CWD]' : '')
|
|
||||||
let levelString = (g:fuf_mrufile_searchAroundLevel < 0 ? ''
|
|
||||||
\ : '[Around:' . g:fuf_mrufile_searchAroundLevel . ']')
|
|
||||||
return fuf#formatPrompt(g:fuf_mrufile_prompt, self.partialMatching, cwdString . levelString)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
if a:mode ==# s:OPEN_TYPE_EXPAND
|
|
||||||
let nextLevel = (self.searchAroundLevel < 0 ? 0 : self.searchAroundLevel + 1)
|
|
||||||
call fuf#setOneTimeVariables(['g:fuf_mrufile_searchAroundLevel', nextLevel])
|
|
||||||
let self.reservedMode = self.getModeName()
|
|
||||||
return
|
|
||||||
else
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.searchAroundLevel = g:fuf_mrufile_searchAroundLevel
|
|
||||||
call fuf#defineKeyMappingInHandler(g:fuf_mrufile_keyExpand,
|
|
||||||
\ 'onCr(' . s:OPEN_TYPE_EXPAND . ')')
|
|
||||||
if self.searchAroundLevel < 0
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
|
|
||||||
call map(self.items, 's:formatItemUsingCache(v:val)')
|
|
||||||
else
|
|
||||||
let self.items = fuf#loadDataFile(s:MODE_NAME, 'itemdirs')
|
|
||||||
call map(self.items, 's:expandSearchDir(v:val.word, g:fuf_mrufile_searchAroundLevel)')
|
|
||||||
let self.items = l9#concat(self.items)
|
|
||||||
let self.items = l9#unique(self.items)
|
|
||||||
call map(self.items, 's:listAroundFiles(v:val)')
|
|
||||||
let self.items = l9#concat(self.items)
|
|
||||||
endif
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~')
|
|
||||||
call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')
|
|
||||||
if g:fuf_mrufile_underCwd
|
|
||||||
let cwd = fnamemodify(getcwd(), ':p:~')
|
|
||||||
call filter(self.items, 'stridx(v:val.word, cwd) == 0')
|
|
||||||
endif
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(self.items)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#getSwitchOrder()
|
|
||||||
return g:fuf_quickfix_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#renewCache()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#quickfix#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufQuickfix', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getJumpsLines()
|
|
||||||
redir => result
|
|
||||||
:silent jumps
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseJumpsLine(line)
|
|
||||||
return matchlist(a:line, '^\(.\)\s\+\(\d\+\)\s\(.*\)$')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:makeItem(qfItem)
|
|
||||||
if !a:qfItem.valid
|
|
||||||
return {}
|
|
||||||
endif
|
|
||||||
let item = fuf#makeNonPathItem(
|
|
||||||
\ printf('%s|%d:%d|%s', bufname(a:qfItem.bufnr), a:qfItem.lnum,
|
|
||||||
\ a:qfItem.col, matchstr(a:qfItem.text, '\s*\zs.*\S'))
|
|
||||||
\ , '')
|
|
||||||
let item.bufnr = a:qfItem.bufnr
|
|
||||||
let item.lnum = a:qfItem.lnum
|
|
||||||
return item
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_quickfix_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let items = filter(copy(self.items), 'v:val.word ==# a:word')
|
|
||||||
if empty(items)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let lines = fuf#getFileLines(items[0].bufnr)
|
|
||||||
return fuf#makePreviewLinesAround(
|
|
||||||
\ lines, [items[0].lnum - 1], a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#prejump(a:mode)
|
|
||||||
call filter(self.items, 'v:val.word ==# a:word')
|
|
||||||
if !empty(self.items)
|
|
||||||
execute 'cc ' . self.items[0].index
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let self.items = getqflist()
|
|
||||||
call map(self.items, 's:makeItem(v:val)')
|
|
||||||
call fuf#mapToSetSerialIndex(self.items, 1)
|
|
||||||
call filter(self.items, 'exists("v:val.word")')
|
|
||||||
call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#getSwitchOrder()
|
|
||||||
return g:fuf_tag_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#tag#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufTag' , s:MODE_NAME, '""', [])
|
|
||||||
call fuf#defineLaunchCommand('FufTagWithCursorWord', s:MODE_NAME, 'expand(''<cword>'')', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTagNames(tagFile)
|
|
||||||
let names = map(l9#readFile(a:tagFile), 'matchstr(v:val, ''^[^!\t][^\t]*'')')
|
|
||||||
return filter(names, 'v:val =~# ''\S''')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseTagFiles(tagFiles, key)
|
|
||||||
let cacheName = 'cache-' . l9#hash224(a:key)
|
|
||||||
let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
|
|
||||||
if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
|
|
||||||
return fuf#loadDataFile(s:MODE_NAME, cacheName)
|
|
||||||
endif
|
|
||||||
let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getTagNames(v:val)')))
|
|
||||||
let items = map(items, 'fuf#makeNonPathItem(v:val, "")')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
|
|
||||||
return items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumTags(tagFiles)
|
|
||||||
if !len(a:tagFiles)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let key = join([g:fuf_ignoreCase] + a:tagFiles, "\n")
|
|
||||||
if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time)
|
|
||||||
let s:cache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : s:parseTagFiles(a:tagFiles, key)
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:cache[key].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getMatchingIndex(lines, cmd)
|
|
||||||
if a:cmd !~# '\D'
|
|
||||||
return str2nr(a:cmd)
|
|
||||||
endif
|
|
||||||
let pattern = matchstr(a:cmd, '^\/\^\zs.*\ze\$\/$')
|
|
||||||
if empty(pattern)
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
for i in range(len(a:lines))
|
|
||||||
if a:lines[i] ==# pattern
|
|
||||||
return i
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return -1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_tag_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForNonPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" 'cmd' is '/^hoge hoge$/' or line number
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
let tags = taglist('^' . a:word . '$')
|
|
||||||
if empty(tags)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let i = a:count % len(tags)
|
|
||||||
let title = printf('(%d/%d) %s', i + 1, len(tags), tags[i].filename)
|
|
||||||
let lines = fuf#getFileLines(tags[i].filename)
|
|
||||||
let index = s:getMatchingIndex(lines, tags[i].cmd)
|
|
||||||
return [title] + fuf#makePreviewLinesAround(
|
|
||||||
\ lines, (index < 0 ? [] : [index]), 0, self.getPreviewHeight() - 1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return s:enumTags(self.tagFiles)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openTag(a:word, a:mode)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.tagFiles = fuf#getCurrentTagFiles()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
let &l:tags = join(self.tagFiles, ',')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
let &l:tags = ''
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,159 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GLOBAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#createHandler(base)
|
|
||||||
return a:base.concretize(copy(s:handler))
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#getSwitchOrder()
|
|
||||||
return g:fuf_taggedfile_switchOrder
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#getEditableDataNames()
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#renewCache()
|
|
||||||
let s:cache = {}
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#requiresOnCommandPre()
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function fuf#taggedfile#onInit()
|
|
||||||
call fuf#defineLaunchCommand('FufTaggedFile', s:MODE_NAME, '""', [])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS/VARIABLES {{{1
|
|
||||||
|
|
||||||
let s:MODE_NAME = expand('<sfile>:t:r')
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:getTaggedFileList(tagfile)
|
|
||||||
execute 'cd ' . fnamemodify(a:tagfile, ':h')
|
|
||||||
let result = map(l9#readFile(a:tagfile), 'matchstr(v:val, ''^[^!\t][^\t]*\t\zs[^\t]\+'')')
|
|
||||||
call map(l9#readFile(a:tagfile), 'fnamemodify(v:val, ":p")')
|
|
||||||
cd -
|
|
||||||
call map(l9#readFile(a:tagfile), 'fnamemodify(v:val, ":~:.")')
|
|
||||||
return filter(result, 'v:val =~# ''[^/\\ ]$''')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:parseTagFiles(tagFiles, key)
|
|
||||||
let cacheName = 'cache-' . l9#hash224(a:key)
|
|
||||||
let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
|
|
||||||
if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
|
|
||||||
return fuf#loadDataFile(s:MODE_NAME, cacheName)
|
|
||||||
endif
|
|
||||||
let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getTaggedFileList(v:val)')))
|
|
||||||
call map(items, 'fuf#makePathItem(v:val, "", 0)')
|
|
||||||
call fuf#mapToSetSerialIndex(items, 1)
|
|
||||||
call fuf#mapToSetAbbrWithSnippedWordAsPath(items)
|
|
||||||
call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
|
|
||||||
return items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:enumTaggedFiles(tagFiles)
|
|
||||||
if !len(a:tagFiles)
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
let key = join([getcwd(), g:fuf_ignoreCase] + a:tagFiles, "\n")
|
|
||||||
if !exists('s:cache[key]') || fuf#countModifiedFiles(a:tagFiles, s:cache[key].time)
|
|
||||||
let s:cache[key] = {
|
|
||||||
\ 'time' : localtime(),
|
|
||||||
\ 'items' : s:parseTagFiles(a:tagFiles, key)
|
|
||||||
\ }
|
|
||||||
endif
|
|
||||||
return s:cache[key].items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" s:handler {{{1
|
|
||||||
|
|
||||||
let s:handler = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getModeName()
|
|
||||||
return s:MODE_NAME
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPrompt()
|
|
||||||
return fuf#formatPrompt(g:fuf_taggedfile_prompt, self.partialMatching, '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getPreviewHeight()
|
|
||||||
return g:fuf_previewHeight
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.isOpenable(enteredPattern)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePatternSet(patternBase)
|
|
||||||
return fuf#makePatternSet(a:patternBase, 's:interpretPrimaryPatternForPath',
|
|
||||||
\ self.partialMatching)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.makePreviewLines(word, count)
|
|
||||||
return fuf#makePreviewLinesForFile(a:word, a:count, self.getPreviewHeight())
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.getCompleteItems(patternPrimary)
|
|
||||||
return self.items
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onOpen(word, mode)
|
|
||||||
call fuf#openFile(a:word, a:mode, g:fuf_reuseWindow)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPre()
|
|
||||||
let self.tagFiles = fuf#getCurrentTagFiles()
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeEnterPost()
|
|
||||||
" NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
|
|
||||||
let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~:.')
|
|
||||||
" NOTE: Don't do this in onModeEnterPre()
|
|
||||||
" because that should return in a short time.
|
|
||||||
let self.items = copy(s:enumTaggedFiles(self.tagFiles))
|
|
||||||
call filter(self.items, 'v:val.word !=# bufNamePrev')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:handler.onModeLeavePost(opened)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,570 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2009-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if exists('g:loaded_autoload_l9')
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_autoload_l9 = 1
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" COMPATIBILITY TEST {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
let s:L9_VERSION_CURRENT = 101
|
|
||||||
let s:L9_VERSION_PASSABLE = 101
|
|
||||||
|
|
||||||
" returns true if given version is compatible.
|
|
||||||
function l9#isCompatible(ver)
|
|
||||||
return
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
let s:VERSION_FACTOR = str2float('0.01')
|
|
||||||
|
|
||||||
" returns false if the caller script should finish.
|
|
||||||
" a:vimVersion: if 0, don't check vim version
|
|
||||||
" a:l9Version: same rule as v:version
|
|
||||||
function l9#guardScriptLoading(path, vimVersion, l9Version, exprs)
|
|
||||||
let loadedVarName = 'g:loaded_' . substitute(a:path, '\W', '_', 'g')
|
|
||||||
if exists(loadedVarName)
|
|
||||||
return 0
|
|
||||||
elseif a:vimVersion > 0 && a:vimVersion > v:version
|
|
||||||
echoerr a:path . ' requires Vim version ' . string(a:vimVersion * s:VERSION_FACTOR)
|
|
||||||
return 0
|
|
||||||
elseif a:l9Version > 0 && (a:l9Version > s:L9_VERSION_CURRENT ||
|
|
||||||
\ a:l9Version < s:L9_VERSION_PASSABLE)
|
|
||||||
echoerr a:path . ' requires L9 library version ' . string(a:l9Version * s:VERSION_FACTOR)
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
for expr in a:exprs
|
|
||||||
if !eval(expr)
|
|
||||||
echoerr a:path . ' requires: ' . expr
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
let {loadedVarName} = 1
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#getVersion()
|
|
||||||
return s:L9_VERSION_CURRENT
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LIST {{{1
|
|
||||||
|
|
||||||
" Removes duplicates (unstable)
|
|
||||||
" This function doesn't change the list of argument.
|
|
||||||
function l9#unique(items)
|
|
||||||
let sorted = sort(a:items)
|
|
||||||
if len(sorted) < 2
|
|
||||||
return sorted
|
|
||||||
endif
|
|
||||||
let last = remove(sorted, 0)
|
|
||||||
let result = [last]
|
|
||||||
for item in sorted
|
|
||||||
if item != last
|
|
||||||
call add(result, item)
|
|
||||||
let last = item
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Removes duplicates (stable)
|
|
||||||
" This function doesn't change the list of argument.
|
|
||||||
function l9#uniqueStably(items)
|
|
||||||
let result = []
|
|
||||||
for item in a:items
|
|
||||||
if count(result, item, &ignorecase) == 0
|
|
||||||
call add(result, item)
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ]
|
|
||||||
" This function doesn't change the list of argument.
|
|
||||||
function l9#concat(items)
|
|
||||||
let result = []
|
|
||||||
for l in a:items
|
|
||||||
let result += l
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" [ [0,1,2], [3,4], [5,6,7,8] ] -> [ [0,3,5],[1,4,6] ]
|
|
||||||
" This function doesn't change the list of argument.
|
|
||||||
function l9#zip(items)
|
|
||||||
let result = []
|
|
||||||
for i in range(min(map(copy(a:items), 'len(v:val)')))
|
|
||||||
call add(result, map(copy(a:items), 'v:val[i]'))
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" filter() with the maximum number of items
|
|
||||||
" This function doesn't change the list of argument.
|
|
||||||
function l9#filterWithLimit(items, expr, limit)
|
|
||||||
if a:limit <= 0
|
|
||||||
return filter(copy(a:items), a:expr)
|
|
||||||
endif
|
|
||||||
let result = []
|
|
||||||
let stride = a:limit * 3 / 2 " x1.5
|
|
||||||
for i in range(0, len(a:items) - 1, stride)
|
|
||||||
let result += filter(a:items[i : i + stride - 1], a:expr)
|
|
||||||
if len(result) >= a:limit
|
|
||||||
return remove(result, 0, a:limit - 1)
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Removes if a:expr is evaluated as non-zero and returns removed items.
|
|
||||||
" This function change the list of argument.
|
|
||||||
function l9#removeIf(items, expr)
|
|
||||||
let removed = filter(copy(a:items), a:expr)
|
|
||||||
call filter(a:items, '!( ' . a:expr . ')')
|
|
||||||
return removed
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" NUMERIC {{{1
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" STRING {{{1
|
|
||||||
|
|
||||||
" Snips a:str and add a:mask if the length of a:str is more than a:len
|
|
||||||
function l9#snipHead(str, len, mask)
|
|
||||||
if a:len >= len(a:str)
|
|
||||||
return a:str
|
|
||||||
elseif a:len <= len(a:mask)
|
|
||||||
return a:mask
|
|
||||||
endif
|
|
||||||
return a:mask . a:str[-a:len + len(a:mask):]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Snips a:str and add a:mask if the length of a:str is more than a:len
|
|
||||||
function l9#snipTail(str, len, mask)
|
|
||||||
if a:len >= len(a:str)
|
|
||||||
return a:str
|
|
||||||
elseif a:len <= len(a:mask)
|
|
||||||
return a:mask
|
|
||||||
endif
|
|
||||||
return a:str[:a:len - 1 - len(a:mask)] . a:mask
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Snips a:str and add a:mask if the length of a:str is more than a:len
|
|
||||||
function l9#snipMid(str, len, mask)
|
|
||||||
if a:len >= len(a:str)
|
|
||||||
return a:str
|
|
||||||
elseif a:len <= len(a:mask)
|
|
||||||
return a:mask
|
|
||||||
endif
|
|
||||||
let len_head = (a:len - len(a:mask)) / 2
|
|
||||||
let len_tail = a:len - len(a:mask) - len_head
|
|
||||||
return (len_head > 0 ? a:str[: len_head - 1] : '') . a:mask .
|
|
||||||
\ (len_tail > 0 ? a:str[-len_tail :] : '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#hash224(str)
|
|
||||||
let a = 0x00000800 " shift 11 bit (if unsigned)
|
|
||||||
let b = 0x001fffff " extract 11 bit (if unsigned)
|
|
||||||
let nHash = 7
|
|
||||||
let hashes = repeat([0], nHash)
|
|
||||||
for i in range(len(a:str))
|
|
||||||
let iHash = i % nHash
|
|
||||||
let hashes[iHash] = hashes[iHash] * a + hashes[iHash] / b
|
|
||||||
let hashes[iHash] += char2nr(a:str[i])
|
|
||||||
endfor
|
|
||||||
return join(map(hashes, 'printf("%08x", v:val)'), '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" wildcard -> regexp
|
|
||||||
function l9#convertWildcardToRegexp(expr)
|
|
||||||
let re = escape(a:expr, '\')
|
|
||||||
for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ]
|
|
||||||
let re = substitute(re, pat, sub, 'g')
|
|
||||||
endfor
|
|
||||||
return '\V' . re
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LINES {{{1
|
|
||||||
|
|
||||||
" Removes from the line matching with a:begin first to the line matching with
|
|
||||||
" a:end next and returns removed lines.
|
|
||||||
" If matching range is not found, returns []
|
|
||||||
function l9#removeLinesBetween(lines, begin, end)
|
|
||||||
for i in range(len(a:lines) - 1)
|
|
||||||
if a:lines[i] =~ a:begin
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
for j in range(i + 1, len(a:lines) - 1)
|
|
||||||
if a:lines[j] =~ a:end
|
|
||||||
let g:l0 += [a:lines[i : j]]
|
|
||||||
return remove(a:lines, i, j)
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" PATH {{{1
|
|
||||||
|
|
||||||
" returns the path separator charactor.
|
|
||||||
function l9#getPathSeparator()
|
|
||||||
return (!&shellslash && (has('win32') || has('win64')) ? '\' : '/')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" [ 'a', 'b/', '/c' ] -> 'a/b/c'
|
|
||||||
function l9#concatPaths(paths)
|
|
||||||
let result = ''
|
|
||||||
for p in a:paths
|
|
||||||
if empty(p)
|
|
||||||
continue
|
|
||||||
elseif empty(result)
|
|
||||||
let result = p
|
|
||||||
else
|
|
||||||
let result = substitute(result, '[/\\]$', '', '') . l9#getPathSeparator()
|
|
||||||
\ . substitute(p, '^[/\\]', '', '')
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return result
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" path: '/a/b/c/d', dir: '/a/b' => 'c/d'
|
|
||||||
function l9#modifyPathRelativeToDir(path, dir)
|
|
||||||
let pathFull = fnamemodify(a:path, ':p')
|
|
||||||
let dirFull = fnamemodify(a:dir, ':p')
|
|
||||||
if len(pathFull) < len(dirFull) || pathFull[:len(dirFull) - 1] !=# dirFull
|
|
||||||
return pathFull
|
|
||||||
endif
|
|
||||||
return pathFull[len(dirFull):]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" FILE {{{1
|
|
||||||
|
|
||||||
" Almost same as readfile().
|
|
||||||
function l9#readFile(...)
|
|
||||||
let args = copy(a:000)
|
|
||||||
let args[0] = expand(args[0])
|
|
||||||
try
|
|
||||||
return call('readfile', args)
|
|
||||||
catch
|
|
||||||
endtry
|
|
||||||
return []
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Almost same as writefile().
|
|
||||||
function l9#writeFile(...)
|
|
||||||
let args = copy(a:000)
|
|
||||||
let args[1] = expand(args[1])
|
|
||||||
let dir = fnamemodify(args[1], ':h')
|
|
||||||
try
|
|
||||||
if !isdirectory(dir)
|
|
||||||
call mkdir(dir, 'p')
|
|
||||||
endif
|
|
||||||
return call('writefile', args)
|
|
||||||
catch
|
|
||||||
endtry
|
|
||||||
return -1 " -1 is error code.
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" BUFFER {{{1
|
|
||||||
|
|
||||||
" :wall/:wall! wrapper. Useful for writing readonly buffers.
|
|
||||||
function l9#writeAll()
|
|
||||||
try
|
|
||||||
silent update " NOTE: avoiding a problem with a buftype=acwrite buffer.
|
|
||||||
silent wall
|
|
||||||
catch /^Vim/ " E45, E505
|
|
||||||
if l9#inputHl('Question', v:exception . "\nWrite readonly files? (Y/N) : ", 'Y') ==? 'y'
|
|
||||||
redraw
|
|
||||||
:wall!
|
|
||||||
endif
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Loads given files with :edit command
|
|
||||||
function l9#loadFilesToBuffers(files)
|
|
||||||
for file in filter(copy(a:files), '!bufloaded(v:val)')
|
|
||||||
execute 'edit ' . fnameescape(file)
|
|
||||||
if !exists('bufNrFirst')
|
|
||||||
let bufNrFirst = bufnr('%')
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
if exists('bufNrFirst')
|
|
||||||
execute bufNrFirst . 'buffer'
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Deletes all buffers except given files with :bdelete command
|
|
||||||
function l9#deleteAllBuffersExcept(files)
|
|
||||||
let bufNrExcepts = map(copy(a:files), 'bufnr("^" . v:val . "$")')
|
|
||||||
for bufNr in filter(range(1, bufnr('$')), 'bufloaded(v:val)')
|
|
||||||
if count(bufNrExcepts, bufNr) == 0
|
|
||||||
execute bufNr . 'bdelete'
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" WINDOW {{{1
|
|
||||||
|
|
||||||
" move current window to next tabpage.
|
|
||||||
function l9#shiftWinNextTabpage()
|
|
||||||
if tabpagenr('$') < 2
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let bufnr = bufnr('%')
|
|
||||||
tabnext
|
|
||||||
execute bufnr . 'sbuffer'
|
|
||||||
tabprevious
|
|
||||||
if winnr('$') > 1
|
|
||||||
close
|
|
||||||
tabnext
|
|
||||||
else
|
|
||||||
close " if tabpage is closed, next tabpage will become current
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" move current window to previous tabpage.
|
|
||||||
function l9#shiftWinPrevTabpage()
|
|
||||||
if tabpagenr('$') < 2
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let bufnr = bufnr('%')
|
|
||||||
tabprevious
|
|
||||||
execute bufnr . 'sbuffer'
|
|
||||||
tabnext
|
|
||||||
close
|
|
||||||
tabprevious
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" move to a window containing specified buffer.
|
|
||||||
" returns 0 if the buffer is not found.
|
|
||||||
function l9#moveToBufferWindowInCurrentTabpage(bufNr)
|
|
||||||
if bufnr('%') == a:bufNr
|
|
||||||
return 1
|
|
||||||
elseif count(tabpagebuflist(), a:bufNr) == 0
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
execute bufwinnr(a:bufNr) . 'wincmd w'
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" returns 0 if the buffer is not found.
|
|
||||||
function s:moveToOtherTabpageOpeningBuffer(bufNr)
|
|
||||||
for tabNr in range(1, tabpagenr('$'))
|
|
||||||
if tabNr != tabpagenr() && count(tabpagebuflist(tabNr), a:bufNr) > 0
|
|
||||||
execute 'tabnext ' . tabNr
|
|
||||||
return 1
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" move to a window containing specified buffer.
|
|
||||||
" returns 0 if the buffer is not found.
|
|
||||||
function l9#moveToBufferWindowInOtherTabpage(bufNr)
|
|
||||||
if !s:moveToOtherTabpageOpeningBuffer(a:bufNr)
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
return l9#moveToBufferWindowInCurrentTabpage(a:bufNr)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" COMMAND LINE {{{1
|
|
||||||
|
|
||||||
" echo/echomsg with highlighting.
|
|
||||||
function l9#echoHl(hl, msg, prefix, addingHistory)
|
|
||||||
let echoCmd = (a:addingHistory ? 'echomsg' : 'echo')
|
|
||||||
execute "echohl " . a:hl
|
|
||||||
try
|
|
||||||
for l in (type(a:msg) == type([]) ? a:msg : split(a:msg, "\n"))
|
|
||||||
execute echoCmd . ' a:prefix . l'
|
|
||||||
endfor
|
|
||||||
finally
|
|
||||||
echohl None
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" input() with highlighting.
|
|
||||||
" This function can take list as {completion} argument.
|
|
||||||
function l9#inputHl(hl, ...)
|
|
||||||
execute "echohl " . a:hl
|
|
||||||
try
|
|
||||||
let args = copy(a:000)
|
|
||||||
if len(args) > 2 && type(args[2]) == type([])
|
|
||||||
let s:candidatesForInputHl = args[2]
|
|
||||||
let args[2] = 'custom,l9#completeForInputHl'
|
|
||||||
endif
|
|
||||||
let s = call('input', args)
|
|
||||||
unlet! s:candidatesForInputHl
|
|
||||||
finally
|
|
||||||
echohl None
|
|
||||||
endtry
|
|
||||||
redraw " needed to show following echo to next line.
|
|
||||||
return s
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" only called by l9#inputHl() for completion.
|
|
||||||
function l9#completeForInputHl(lead, line, pos)
|
|
||||||
return join(s:candidatesForInputHl, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" VISUAL MODE {{{1
|
|
||||||
|
|
||||||
" returns last selected text in Visual mode.
|
|
||||||
function l9#getSelectedText()
|
|
||||||
let reg_ = [@", getregtype('"')]
|
|
||||||
let regA = [@a, getregtype('a')]
|
|
||||||
if mode() =~# "[vV\<C-v>]"
|
|
||||||
silent normal! "aygv
|
|
||||||
else
|
|
||||||
let pos = getpos('.')
|
|
||||||
silent normal! gv"ay
|
|
||||||
call setpos('.', pos)
|
|
||||||
endif
|
|
||||||
let text = @a
|
|
||||||
call setreg('"', reg_[0], reg_[1])
|
|
||||||
call setreg('a', regA[0], regA[1])
|
|
||||||
return text
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" EVAL {{{1
|
|
||||||
|
|
||||||
" loads given text as Vim script with :source command
|
|
||||||
function l9#loadScript(text)
|
|
||||||
let lines = (type(a:text) == type([]) ? a:text : split(a:text, "\n"))
|
|
||||||
let fname = tempname()
|
|
||||||
call writefile(lines, fname)
|
|
||||||
source `=fname`
|
|
||||||
call delete(fname)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" VARIABLES {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#defineVariableDefault(name, default)
|
|
||||||
if !exists(a:name)
|
|
||||||
let {a:name} = a:default
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GREP {{{1
|
|
||||||
|
|
||||||
" Execute :vimgrep and opens the quickfix window if matches are found.
|
|
||||||
"
|
|
||||||
" a:pattern: search pattern. If ommitted, last search pattern (@/) is used.
|
|
||||||
" a:files: List of files
|
|
||||||
function l9#grepFiles(pattern, files)
|
|
||||||
let target = join(map(a:files, 'escape(v:val, " ")'), ' ')
|
|
||||||
let pattern = (a:pattern[0] ==# '/' ? a:pattern[1:] : a:pattern)
|
|
||||||
let pattern = (empty(pattern) ? @/ : pattern)
|
|
||||||
try
|
|
||||||
execute printf('vimgrep/%s/j %s', pattern, target)
|
|
||||||
catch /^Vim/
|
|
||||||
call setqflist([])
|
|
||||||
endtry
|
|
||||||
call l9#quickfix#sort()
|
|
||||||
call l9#quickfix#openIfNotEmpty(1, 0)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Execute :vimgrep for buffers using l9#grepFiles()
|
|
||||||
" See also: :L9GrepBuffer :L9GrepBufferAll
|
|
||||||
function l9#grepBuffers(pattern, bufNrs)
|
|
||||||
let files = map(filter(a:bufNrs, 'bufloaded(v:val)'), 'bufname(v:val)')
|
|
||||||
call l9#grepFiles(a:pattern, files)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" SIGN {{{1
|
|
||||||
|
|
||||||
" Highlights lines using :sign define and :sign place.
|
|
||||||
"
|
|
||||||
" a:linehl, a:text, a:texthl: See |signs|. Ignored if empty string.
|
|
||||||
" a:locations: List of [{buffer number}, {line number}] for highlighting
|
|
||||||
function l9#placeSign(linehl, text, texthl, locations)
|
|
||||||
let argLinehl = (empty(a:linehl) ? '' : 'linehl=' . a:linehl)
|
|
||||||
let argText = (empty(a:text) ? '' : 'text=' . a:text)
|
|
||||||
let argTexthl = (empty(a:texthl) ? '' : 'texthl=' . a:texthl)
|
|
||||||
let name = 'l9--' . a:linehl . '--' . a:text . '--' . a:texthl
|
|
||||||
execute printf('sign define %s linehl=%s text=%s texthl=%s',
|
|
||||||
\ name, a:linehl, a:text, a:texthl)
|
|
||||||
for [bufNr, lnum] in a:locations
|
|
||||||
execute printf('sign place 1 line=%d name=%s buffer=%d', lnum, name, bufNr)
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" NOTIFY EXTERNALLY {{{1
|
|
||||||
|
|
||||||
" Notify a message using an external program.
|
|
||||||
" Currently supports Balloonly, Screen, and Tmux.
|
|
||||||
function l9#notifyExternally(msg)
|
|
||||||
return l9#notifyBalloonly(a:msg)
|
|
||||||
\ || l9#notifyScreen(a:msg)
|
|
||||||
\ || l9#notifyTmux(a:msg)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#notifyBalloonly(msg)
|
|
||||||
if !(has('win32') || has('win64')) || !executable(g:l9_balloonly)
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
execute 'silent !start ' . shellescape(g:l9_balloonly) . ' 4000 "l9" ' . shellescape(a:msg)
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#notifyScreen(msg)
|
|
||||||
if !has('unix') || has('gui_running') || $WINDOW !~ '\d' || !executable('screen')
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
call system('screen -X wall ' . shellescape('l9: ' . a:msg))
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#notifyTmux(msg)
|
|
||||||
if !has('unix') || has('gui_running') || empty($TMUX) || !executable('tmux')
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
call system('tmux display-message ' . shellescape('l9: ' . a:msg))
|
|
||||||
return 1
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
#!/usr/bin/env python
|
|
||||||
|
|
||||||
from __future__ import with_statement
|
|
||||||
import vim
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import threading
|
|
||||||
import Queue
|
|
||||||
|
|
||||||
|
|
||||||
class Asyncer:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self._workers = {}
|
|
||||||
|
|
||||||
def execute(self, var_key, var_command, var_cwd, var_input, var_appends):
|
|
||||||
key = vim.eval(var_key)
|
|
||||||
command = vim.eval(var_command)
|
|
||||||
cwd = vim.eval(var_cwd)
|
|
||||||
input = vim.eval(var_input)
|
|
||||||
appends = vim.eval(var_appends)
|
|
||||||
if key not in self._workers:
|
|
||||||
self._workers[key] = Worker()
|
|
||||||
self._workers[key].start()
|
|
||||||
self._workers[key].put(Executor(command, cwd, input, appends))
|
|
||||||
|
|
||||||
def print_output(self, var_key):
|
|
||||||
key = vim.eval(var_key)
|
|
||||||
if key not in self._workers:
|
|
||||||
return
|
|
||||||
for l in self._workers[key].copy_outputs():
|
|
||||||
print l,
|
|
||||||
|
|
||||||
def print_worker_keys(self):
|
|
||||||
for k in self._workers.keys():
|
|
||||||
print k
|
|
||||||
|
|
||||||
def print_active_worker_keys(self):
|
|
||||||
for k in self._workers.keys():
|
|
||||||
print k
|
|
||||||
|
|
||||||
|
|
||||||
class Worker(threading.Thread):
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
self._queue = Queue.Queue()
|
|
||||||
self._lines = []
|
|
||||||
self._lock = threading.Lock()
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
while True:
|
|
||||||
self._queue.get().execute(self)
|
|
||||||
self._queue.task_done()
|
|
||||||
|
|
||||||
def put(self, executor):
|
|
||||||
self._queue.put(executor)
|
|
||||||
|
|
||||||
def clear_outputs(self):
|
|
||||||
with self._lock:
|
|
||||||
self._lines = []
|
|
||||||
|
|
||||||
def record_output(self, line):
|
|
||||||
with self._lock:
|
|
||||||
self._lines.append(line)
|
|
||||||
|
|
||||||
def copy_outputs(self):
|
|
||||||
with self._lock:
|
|
||||||
return self._lines[:]
|
|
||||||
|
|
||||||
|
|
||||||
class Executor:
|
|
||||||
|
|
||||||
def __init__(self, command, cwd, input, appends):
|
|
||||||
self._command = command
|
|
||||||
self._cwd = cwd
|
|
||||||
self._input = input
|
|
||||||
self._appends = appends
|
|
||||||
|
|
||||||
def execute(self, worker):
|
|
||||||
if not self._appends:
|
|
||||||
worker.clear_outputs()
|
|
||||||
os.chdir(self._cwd)
|
|
||||||
p = subprocess.Popen(self._command, shell=True, stdin=subprocess.PIPE,
|
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
|
||||||
p.stdin.write(self._input)
|
|
||||||
line = p.stdout.readline()
|
|
||||||
while line:
|
|
||||||
worker.record_output(line)
|
|
||||||
line = p.stdout.readline()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,67 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (C) 2009-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, ['has("python")'])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" ASYNC EXECUTE {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:checkKey(key)
|
|
||||||
if a:key =~ '\n' || a:key !~ '\S'
|
|
||||||
throw "Asyncer: Invalid key: " . a:key
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#async#execute(key, cmd, cwd, input, appends)
|
|
||||||
call s:checkKey(a:key)
|
|
||||||
python asyncer.execute('a:key', 'a:cmd', 'a:cwd', 'a:input', 'a:appends')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#async#read(key)
|
|
||||||
call s:checkKey(a:key)
|
|
||||||
redir => result
|
|
||||||
silent python asyncer.print_output('a:key')
|
|
||||||
redir END
|
|
||||||
" NOTE: "\n" is somehow inserted by redir.
|
|
||||||
return (result[0] ==# "\n" ? result[1:] : result)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#async#listWorkers()
|
|
||||||
redir => result
|
|
||||||
silent python asyncer.print_worker_keys()
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#async#listActiveWorkers()
|
|
||||||
redir => result
|
|
||||||
silent python asyncer.print_active_worker_keys()
|
|
||||||
redir END
|
|
||||||
return split(result, "\n")
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" INITIALIZATION {{{1
|
|
||||||
|
|
||||||
let s:ASYNC_PY_PATH = fnamemodify(expand('<sfile>:p:h'), ':p') . 'async.py'
|
|
||||||
|
|
||||||
pyfile `=s:ASYNC_PY_PATH`
|
|
||||||
python asyncer = Asyncer()
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (C) 2009-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" QUICKFIX {{{1
|
|
||||||
|
|
||||||
" Returns non-zero if quickfix window is opened.
|
|
||||||
function l9#quickfix#isWindowOpened()
|
|
||||||
return count(map(range(1, winnr('$')), 'getwinvar(v:val, "&buftype")'), 'quickfix') > 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Opens quickfix window if quickfix is not empty, and echo the number of errors.
|
|
||||||
"
|
|
||||||
" a:onlyRecognized: if non-zero, opens only if quickfix has recognized errors.
|
|
||||||
" a:holdCursor: if non-zero, the cursor won't move to quickfix window.
|
|
||||||
function l9#quickfix#openIfNotEmpty(onlyRecognized, holdCursor)
|
|
||||||
let numErrors = len(filter(getqflist(), 'v:val.valid'))
|
|
||||||
let numOthers = len(getqflist()) - numErrors
|
|
||||||
if numErrors > 0 || (!a:onlyRecognized && numOthers > 0)
|
|
||||||
copen
|
|
||||||
if a:holdCursor
|
|
||||||
wincmd p
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
cclose
|
|
||||||
endif
|
|
||||||
redraw
|
|
||||||
if numOthers > 0
|
|
||||||
echo printf('Quickfix: %d(+%d)', numErrors, numOthers)
|
|
||||||
else
|
|
||||||
echo printf('Quickfix: %d', numErrors)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Toggles Quickfix window
|
|
||||||
function l9#quickfix#toggleWindow()
|
|
||||||
if l9#quickfix#isWindowOpened()
|
|
||||||
cclose
|
|
||||||
else
|
|
||||||
call l9#quickfix#openIfNotEmpty(0, 0)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Creates quickfix list form given lines and opens the quickfix window if
|
|
||||||
" errors exists.
|
|
||||||
"
|
|
||||||
" a:lines:
|
|
||||||
" a:jump: if non-zero, jump to the first error.
|
|
||||||
function l9#quickfix#setMakeResult(lines)
|
|
||||||
cexpr a:lines
|
|
||||||
call l9#quickfix#openIfNotEmpty(0, 1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Compares quickfix entries for sorting.
|
|
||||||
function l9#quickfix#compareEntries(e0, e1)
|
|
||||||
if a:e0.bufnr != a:e1.bufnr
|
|
||||||
let i0 = bufname(a:e0.bufnr)
|
|
||||||
let i1 = bufname(a:e1.bufnr)
|
|
||||||
elseif a:e0.lnum != a:e1.lnum
|
|
||||||
let i0 = a:e0.lnum
|
|
||||||
let i1 = a:e1.lnum
|
|
||||||
elseif a:e0.col != a:e1.col
|
|
||||||
let i0 = a:e0.col
|
|
||||||
let i1 = a:e1.col
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
return (i0 > i1 ? +1 : -1)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Sorts quickfix
|
|
||||||
function l9#quickfix#sort()
|
|
||||||
call setqflist(sort(getqflist(), 'l9#quickfix#compareEntries'), 'r')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Highlights Quickfix lines by :sign.
|
|
||||||
" Inspired by errormarker plugin.
|
|
||||||
"
|
|
||||||
" You can customize the highlighting via L9ErrorLine and L9WarningLine
|
|
||||||
" highlight groups.
|
|
||||||
function l9#quickfix#placeSign()
|
|
||||||
let warnings = []
|
|
||||||
let errors = []
|
|
||||||
for e in filter(getqflist(), 'v:val.valid')
|
|
||||||
let warning = (e.type ==? 'w' || e.text =~? '^\s*warning:')
|
|
||||||
call add((warning ? warnings : errors), [e.bufnr, e.lnum])
|
|
||||||
endfor
|
|
||||||
sign unplace *
|
|
||||||
call l9#placeSign('L9WarningLine', '>>', '', warnings)
|
|
||||||
call l9#placeSign('L9ErrorLine', '>>', '', errors)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
highlight default L9ErrorLine ctermfg=white ctermbg=52 guibg=#5F0000
|
|
||||||
highlight default L9WarningLine ctermfg=white ctermbg=17 guibg=#00005F
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
@ -1,112 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (C) 2009-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" TEMPORARY BUFFER {{{1
|
|
||||||
|
|
||||||
" each key is a buffer name.
|
|
||||||
let s:dataMap = {}
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:onBufDelete(bufname)
|
|
||||||
if exists('s:dataMap[a:bufname].listener.onClose')
|
|
||||||
call s:dataMap[a:bufname].listener.onClose(s:dataMap[a:bufname].written)
|
|
||||||
endif
|
|
||||||
if bufnr('%') == s:dataMap[a:bufname].bufNr && winnr('#') != 0
|
|
||||||
" if winnr('#') returns 0, "wincmd p" causes ringing the bell.
|
|
||||||
wincmd p
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:onBufWriteCmd(bufname)
|
|
||||||
if !exists('s:dataMap[a:bufname].listener.onWrite') ||
|
|
||||||
\ s:dataMap[a:bufname].listener.onWrite(getline(1, '$'))
|
|
||||||
setlocal nomodified
|
|
||||||
let s:dataMap[a:bufname].written = 1
|
|
||||||
call l9#tempbuffer#close(a:bufname)
|
|
||||||
else
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" a:bufname:
|
|
||||||
" a:height: Window height. If 0, default height is used.
|
|
||||||
" If less than 0, the window becomes full-screen.
|
|
||||||
" a:listener:
|
|
||||||
" a:listener.onClose(written)
|
|
||||||
function l9#tempbuffer#openScratch(bufname, filetype, lines, topleft, vertical, height, listener)
|
|
||||||
let openCmdPrefix = (a:topleft ? 'topleft ' : '')
|
|
||||||
\ . (a:vertical ? 'vertical ' : '')
|
|
||||||
\ . (a:height > 0 ? a:height : '')
|
|
||||||
if !exists('s:dataMap[a:bufname]') || !bufexists(s:dataMap[a:bufname].bufNr)
|
|
||||||
execute openCmdPrefix . 'new'
|
|
||||||
else
|
|
||||||
call l9#tempbuffer#close(a:bufname)
|
|
||||||
execute openCmdPrefix . 'split'
|
|
||||||
execute 'silent ' . s:dataMap[a:bufname].bufNr . 'buffer'
|
|
||||||
endif
|
|
||||||
if a:height < 0
|
|
||||||
only
|
|
||||||
endif
|
|
||||||
setlocal buflisted noswapfile bufhidden=delete modifiable noreadonly buftype=nofile
|
|
||||||
let &l:filetype = a:filetype
|
|
||||||
silent file `=a:bufname`
|
|
||||||
call setline(1, a:lines)
|
|
||||||
setlocal nomodified
|
|
||||||
augroup L9TempBuffer
|
|
||||||
autocmd! * <buffer>
|
|
||||||
execute printf('autocmd BufDelete <buffer> call s:onBufDelete (%s)', string(a:bufname))
|
|
||||||
execute printf('autocmd BufWriteCmd <buffer> nested call s:onBufWriteCmd(%s)', string(a:bufname))
|
|
||||||
augroup END
|
|
||||||
let s:dataMap[a:bufname] = {
|
|
||||||
\ 'bufNr': bufnr('%'),
|
|
||||||
\ 'written': 0,
|
|
||||||
\ 'listener': a:listener,
|
|
||||||
\ }
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#tempbuffer#openReadOnly(bufname, filetype, lines, topleft, vertical, height, listener)
|
|
||||||
call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener)
|
|
||||||
setlocal nomodifiable readonly
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" a:listener:
|
|
||||||
" a:listener.onClose(written)
|
|
||||||
" a:listener.onWrite(lines)
|
|
||||||
function l9#tempbuffer#openWritable(bufname, filetype, lines, topleft, vertical, height, listener)
|
|
||||||
call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener)
|
|
||||||
setlocal buftype=acwrite
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" makes specified temp buffer current.
|
|
||||||
function l9#tempbuffer#moveTo(bufname)
|
|
||||||
return l9#moveToBufferWindowInCurrentTabpage(s:dataMap[a:bufname].bufNr) ||
|
|
||||||
\ l9#moveToBufferWindowInOtherTabpage(s:dataMap[a:bufname].bufNr)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#tempbuffer#close(bufname)
|
|
||||||
if !l9#tempbuffer#isOpen(a:bufname)
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
execute printf('%dbdelete!', s:dataMap[a:bufname].bufNr)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function l9#tempbuffer#isOpen(bufname)
|
|
||||||
return exists('s:dataMap[a:bufname]') && bufloaded(s:dataMap[a:bufname].bufNr)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (C) 2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" TEMPORARY VARIABLES {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
let s:origMap = {}
|
|
||||||
|
|
||||||
" set temporary variables
|
|
||||||
function l9#tempvariables#set(group, name, value)
|
|
||||||
if !exists('s:origMap[a:group]')
|
|
||||||
let s:origMap[a:group] = {}
|
|
||||||
endif
|
|
||||||
if !exists('s:origMap[a:group][a:name]')
|
|
||||||
let s:origMap[a:group][a:name] = eval(a:name)
|
|
||||||
endif
|
|
||||||
execute 'let ' . a:name . ' = a:value'
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" set temporary variables
|
|
||||||
function l9#tempvariables#setList(group, variables)
|
|
||||||
for [name, value] in a:variables
|
|
||||||
call l9#tempvariables#set(a:group, name, value)
|
|
||||||
unlet value " to avoid E706
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" get temporary variables
|
|
||||||
function l9#tempvariables#getList(group)
|
|
||||||
if !exists('s:origMap[a:group]')
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
return map(keys(s:origMap[a:group]), '[v:val, eval(v:val)]')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" restore original variables and clean up.
|
|
||||||
function l9#tempvariables#end(group)
|
|
||||||
if !exists('s:origMap[a:group]')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
for [name, value] in items(s:origMap[a:group])
|
|
||||||
execute 'let ' . name . ' = value'
|
|
||||||
unlet value " to avoid E706
|
|
||||||
endfor
|
|
||||||
unlet s:origMap[a:group]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,327 +0,0 @@
|
||||||
" Tabular: Align columnar data using regex-designated column boundaries
|
|
||||||
" Maintainer: Matthew Wozniski (mjw@drexel.edu)
|
|
||||||
" Date: Thu, 11 Oct 2007 00:35:34 -0400
|
|
||||||
" Version: 0.1
|
|
||||||
|
|
||||||
" Stupid vimscript crap {{{1
|
|
||||||
let s:savecpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
" Private Functions {{{1
|
|
||||||
|
|
||||||
" Return the number of bytes in a string after expanding tabs to spaces. {{{2
|
|
||||||
" This expansion is done based on the current value of 'tabstop'
|
|
||||||
function! s:Strlen(string)
|
|
||||||
let rv = 0
|
|
||||||
let i = 0
|
|
||||||
|
|
||||||
for char in split(a:string, '\zs')
|
|
||||||
if char == "\t"
|
|
||||||
let rv += &ts - i
|
|
||||||
let i = 0
|
|
||||||
else
|
|
||||||
let rv += 1
|
|
||||||
let i = (i + 1) % &ts
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
return rv
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Align a string within a field {{{2
|
|
||||||
" These functions do not trim leading and trailing spaces.
|
|
||||||
|
|
||||||
" Right align 'string' in a field of size 'fieldwidth'
|
|
||||||
function! s:Right(string, fieldwidth)
|
|
||||||
let spaces = a:fieldwidth - s:Strlen(a:string)
|
|
||||||
return matchstr(a:string, '^\s*') . repeat(" ", spaces) . substitute(a:string, '^\s*', '', '')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Left align 'string' in a field of size 'fieldwidth'
|
|
||||||
function! s:Left(string, fieldwidth)
|
|
||||||
let spaces = a:fieldwidth - s:Strlen(a:string)
|
|
||||||
return a:string . repeat(" ", spaces)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Center align 'string' in a field of size 'fieldwidth'
|
|
||||||
function! s:Center(string, fieldwidth)
|
|
||||||
let spaces = a:fieldwidth - s:Strlen(a:string)
|
|
||||||
let right = spaces / 2
|
|
||||||
let left = right + (right * 2 != spaces)
|
|
||||||
return repeat(" ", left) . a:string . repeat(" ", right)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Remove spaces around a string {{{2
|
|
||||||
|
|
||||||
" Remove all trailing spaces from a string.
|
|
||||||
function! s:StripTrailingSpaces(string)
|
|
||||||
return matchstr(a:string, '^.\{-}\ze\s*$')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Remove all leading spaces from a string.
|
|
||||||
function! s:StripLeadingSpaces(string)
|
|
||||||
return matchstr(a:string, '^\s*\zs.*$')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Split a string into fields and delimiters {{{2
|
|
||||||
" Like split(), but include the delimiters as elements
|
|
||||||
" All odd numbered elements are delimiters
|
|
||||||
" All even numbered elements are non-delimiters (including zero)
|
|
||||||
function! s:SplitDelim(string, delim)
|
|
||||||
let rv = []
|
|
||||||
let beg = 0
|
|
||||||
|
|
||||||
let len = len(a:string)
|
|
||||||
let searchoff = 0
|
|
||||||
|
|
||||||
while 1
|
|
||||||
let mid = match(a:string, a:delim, beg + searchoff, 1)
|
|
||||||
if mid == -1 || mid == len
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
|
|
||||||
let matchstr = matchstr(a:string, a:delim, beg + searchoff, 1)
|
|
||||||
let length = strlen(matchstr)
|
|
||||||
|
|
||||||
if length == 0 && beg == mid
|
|
||||||
" Zero-length match for a zero-length delimiter - advance past it
|
|
||||||
let searchoff += 1
|
|
||||||
continue
|
|
||||||
endif
|
|
||||||
|
|
||||||
if beg == mid
|
|
||||||
let rv += [ "" ]
|
|
||||||
else
|
|
||||||
let rv += [ a:string[beg : mid-1] ]
|
|
||||||
endif
|
|
||||||
|
|
||||||
let rv += [ matchstr ]
|
|
||||||
|
|
||||||
let beg = mid + length
|
|
||||||
let searchoff = 0
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
let rv += [ strpart(a:string, beg) ]
|
|
||||||
|
|
||||||
return rv
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Replace lines from `start' to `start + len - 1' with the given strings. {{{2
|
|
||||||
" If more lines are needed to show all strings, they will be added.
|
|
||||||
" If there are too few strings to fill all lines, lines will be removed.
|
|
||||||
function! s:SetLines(start, len, strings)
|
|
||||||
if a:start > line('$') + 1 || a:start < 1
|
|
||||||
throw "Invalid start line!"
|
|
||||||
endif
|
|
||||||
|
|
||||||
if len(a:strings) > a:len
|
|
||||||
let fensave = &fen
|
|
||||||
let view = winsaveview()
|
|
||||||
call append(a:start + a:len - 1, repeat([''], len(a:strings) - a:len))
|
|
||||||
call winrestview(view)
|
|
||||||
let &fen = fensave
|
|
||||||
elseif len(a:strings) < a:len
|
|
||||||
let fensave = &fen
|
|
||||||
let view = winsaveview()
|
|
||||||
sil exe (a:start + len(a:strings)) . ',' . (a:start + a:len - 1) . 'd_'
|
|
||||||
call winrestview(view)
|
|
||||||
let &fen = fensave
|
|
||||||
endif
|
|
||||||
|
|
||||||
call setline(a:start, a:strings)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Runs the given commandstring argument as an expression. {{{2
|
|
||||||
" The commandstring expression is expected to reference the a:lines argument.
|
|
||||||
" If the commandstring expression returns a list the items of that list will
|
|
||||||
" replace the items in a:lines, otherwise the expression is assumed to have
|
|
||||||
" modified a:lines itself.
|
|
||||||
function! s:FilterString(lines, commandstring)
|
|
||||||
exe 'let rv = ' . a:commandstring
|
|
||||||
|
|
||||||
if type(rv) == type(a:lines) && rv isnot a:lines
|
|
||||||
call filter(a:lines, 0)
|
|
||||||
call extend(a:lines, rv)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Public API {{{1
|
|
||||||
|
|
||||||
if !exists("g:tabular_default_format")
|
|
||||||
let g:tabular_default_format = "l1"
|
|
||||||
endif
|
|
||||||
|
|
||||||
let s:formatelempat = '\%([lrc]\d\+\)'
|
|
||||||
|
|
||||||
function! tabular#ElementFormatPattern()
|
|
||||||
return s:formatelempat
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Given a list of strings and a delimiter, split each string on every
|
|
||||||
" occurrence of the delimiter pattern, format each element according to either
|
|
||||||
" the provided format (optional) or the default format, and join them back
|
|
||||||
" together with enough space padding to guarantee that the nth delimiter of
|
|
||||||
" each string is aligned.
|
|
||||||
function! tabular#TabularizeStrings(strings, delim, ...)
|
|
||||||
if a:0 > 1
|
|
||||||
echoerr "TabularizeStrings accepts only 2 or 3 arguments (got ".(a:0+2).")"
|
|
||||||
return 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
let formatstr = (a:0 ? a:1 : g:tabular_default_format)
|
|
||||||
|
|
||||||
if formatstr !~? s:formatelempat . '\+'
|
|
||||||
echoerr "Tabular: Invalid format \"" . formatstr . "\" specified!"
|
|
||||||
return 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
let format = split(formatstr, s:formatelempat . '\zs')
|
|
||||||
|
|
||||||
let lines = map(a:strings, 's:SplitDelim(v:val, a:delim)')
|
|
||||||
|
|
||||||
" Strip spaces
|
|
||||||
" - Only from non-delimiters; spaces in delimiters must have been matched
|
|
||||||
" intentionally
|
|
||||||
" - Don't strip leading spaces from the first element; we like indenting.
|
|
||||||
for line in lines
|
|
||||||
if line[0] !~ '^\s*$'
|
|
||||||
let line[0] = s:StripTrailingSpaces(line[0])
|
|
||||||
endif
|
|
||||||
if len(line) >= 3
|
|
||||||
for i in range(2, len(line)-1, 2)
|
|
||||||
let line[i] = s:StripLeadingSpaces(s:StripTrailingSpaces(line[i]))
|
|
||||||
endfor
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
" Find the max length of each field
|
|
||||||
let maxes = []
|
|
||||||
for line in lines
|
|
||||||
for i in range(len(line))
|
|
||||||
if i == len(maxes)
|
|
||||||
let maxes += [ s:Strlen(line[i]) ]
|
|
||||||
else
|
|
||||||
let maxes[i] = max( [ maxes[i], s:Strlen(line[i]) ] )
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let lead_blank = empty(filter(copy(lines), 'v:val[0] =~ "\\S"'))
|
|
||||||
|
|
||||||
" Concatenate the fields, according to the format pattern.
|
|
||||||
for idx in range(len(lines))
|
|
||||||
let line = lines[idx]
|
|
||||||
for i in range(len(line))
|
|
||||||
let how = format[i % len(format)][0]
|
|
||||||
let pad = format[i % len(format)][1:-1]
|
|
||||||
|
|
||||||
if how =~? 'l'
|
|
||||||
let field = s:Left(line[i], maxes[i])
|
|
||||||
elseif how =~? 'r'
|
|
||||||
let field = s:Right(line[i], maxes[i])
|
|
||||||
elseif how =~? 'c'
|
|
||||||
let field = s:Center(line[i], maxes[i])
|
|
||||||
endif
|
|
||||||
|
|
||||||
let line[i] = field . (lead_blank && i == 0 ? '' : repeat(" ", pad))
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let lines[idx] = s:StripTrailingSpaces(join(line, ''))
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Apply 0 or more filters, in sequence, to selected text in the buffer {{{2
|
|
||||||
" The lines to be filtered are determined as follows:
|
|
||||||
" If the function is called with a range containing multiple lines, then
|
|
||||||
" those lines will be used as the range.
|
|
||||||
" If the function is called with no range or with a range of 1 line, then
|
|
||||||
" if "includepat" is not specified,
|
|
||||||
" that 1 line will be filtered,
|
|
||||||
" if "includepat" is specified and that line does not match it,
|
|
||||||
" no lines will be filtered
|
|
||||||
" if "includepat" is specified and that line does match it,
|
|
||||||
" all contiguous lines above and below the specified line matching the
|
|
||||||
" pattern will be filtered.
|
|
||||||
"
|
|
||||||
" The remaining arguments must each be a filter to apply to the text.
|
|
||||||
" Each filter must either be a String evaluating to a function to be called.
|
|
||||||
function! tabular#PipeRange(includepat, ...) range
|
|
||||||
let top = a:firstline
|
|
||||||
let bot = a:lastline
|
|
||||||
|
|
||||||
if a:includepat != '' && top == bot
|
|
||||||
if top < 0 || top > line('$') || getline(top) !~ a:includepat
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
while top > 1 && getline(top-1) =~ a:includepat
|
|
||||||
let top -= 1
|
|
||||||
endwhile
|
|
||||||
while bot < line('$') && getline(bot+1) =~ a:includepat
|
|
||||||
let bot += 1
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
|
|
||||||
let lines = map(range(top, bot), 'getline(v:val)')
|
|
||||||
|
|
||||||
for filter in a:000
|
|
||||||
if type(filter) != type("")
|
|
||||||
echoerr "PipeRange: Bad filter: " . string(filter)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:FilterString(lines, filter)
|
|
||||||
|
|
||||||
unlet filter
|
|
||||||
endfor
|
|
||||||
|
|
||||||
call s:SetLines(top, bot - top + 1, lines)
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:SplitDelimTest(string, delim, expected)
|
|
||||||
let result = s:SplitDelim(a:string, a:delim)
|
|
||||||
|
|
||||||
if result !=# a:expected
|
|
||||||
echomsg 'Test failed!'
|
|
||||||
echomsg ' string=' . string(a:string) . ' delim=' . string(a:delim)
|
|
||||||
echomsg ' Returned=' . string(result)
|
|
||||||
echomsg ' Expected=' . string(a:expected)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! tabular#SplitDelimUnitTest()
|
|
||||||
let assignment = '[|&+*/%<>=!~-]\@<!\([<>!=]=\|=\~\)\@![|&+*/%<>=!~-]*='
|
|
||||||
let two_spaces = ' '
|
|
||||||
let ternary_operator = '^.\{-}\zs?\|:'
|
|
||||||
let cpp_io = '<<\|>>'
|
|
||||||
let pascal_assign = ':='
|
|
||||||
let trailing_c_comments = '\/\*\|\*\/\|\/\/'
|
|
||||||
|
|
||||||
call s:SplitDelimTest('a+=b', assignment, ['a', '+=', 'b'])
|
|
||||||
call s:SplitDelimTest('a-=b', assignment, ['a', '-=', 'b'])
|
|
||||||
call s:SplitDelimTest('a!=b', assignment, ['a!=b'])
|
|
||||||
call s:SplitDelimTest('a==b', assignment, ['a==b'])
|
|
||||||
call s:SplitDelimTest('a&=b', assignment, ['a', '&=', 'b'])
|
|
||||||
call s:SplitDelimTest('a|=b', assignment, ['a', '|=', 'b'])
|
|
||||||
call s:SplitDelimTest('a=b=c', assignment, ['a', '=', 'b', '=', 'c'])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('a b c', two_spaces, ['a', ' ', 'b', ' ', 'c'])
|
|
||||||
call s:SplitDelimTest('a b c', two_spaces, ['a b', ' ', ' c'])
|
|
||||||
call s:SplitDelimTest('ab c', two_spaces, ['ab', ' ', '', ' ', 'c'])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('a?b:c', ternary_operator, ['a', '?', 'b', ':', 'c'])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('a<<b<<c', cpp_io, ['a', '<<', 'b', '<<', 'c'])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('a:=b=c', pascal_assign, ['a', ':=', 'b=c'])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('x//foo', trailing_c_comments, ['x', '//', 'foo'])
|
|
||||||
call s:SplitDelimTest('x/*foo*/',trailing_c_comments, ['x', '/*', 'foo', '*/', ''])
|
|
||||||
|
|
||||||
call s:SplitDelimTest('#ab#cd#ef', '[^#]*', ['#', 'ab', '#', 'cd', '#', 'ef', ''])
|
|
||||||
call s:SplitDelimTest('#ab#cd#ef', '#\zs', ['#', '', 'ab#', '', 'cd#', '', 'ef'])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Stupid vimscript crap, part 2 {{{1
|
|
||||||
let &cpo = s:savecpo
|
|
||||||
unlet s:savecpo
|
|
||||||
|
|
||||||
" vim:set sw=2 sts=2 fdm=marker:
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,260 +0,0 @@
|
||||||
*Tabular.txt* Configurable, flexible, intuitive text aligning
|
|
||||||
|
|
||||||
*tabular* *tabular.vim*
|
|
||||||
|
|
||||||
#|#|#|#|#| #| #| ~
|
|
||||||
#| #|#|#| #|#|#| #| #| #| #|#|#| #| #|#| ~
|
|
||||||
#| #| #| #| #| #| #| #| #| #| #|#| ~
|
|
||||||
#| #| #| #| #| #| #| #| #| #| #| ~
|
|
||||||
#| #|#|#| #|#|#| #|#|#| #| #|#|#| #| ~
|
|
||||||
|
|
||||||
For Vim version 7.0 or newer
|
|
||||||
|
|
||||||
By Matt Wozniski
|
|
||||||
mjw@drexel.edu
|
|
||||||
|
|
||||||
Reference Manual ~
|
|
||||||
|
|
||||||
*tabular-toc*
|
|
||||||
|
|
||||||
1. Description |tabular-intro|
|
|
||||||
2. Walkthrough |tabular-walkthrough|
|
|
||||||
3. Scripting |tabular-scripting|
|
|
||||||
|
|
||||||
The functionality mentioned here is a plugin, see |add-plugin|.
|
|
||||||
You can avoid loading this plugin by setting the "Tabular_loaded" global
|
|
||||||
variable in your |vimrc| file: >
|
|
||||||
:let g:tabular_loaded = 1
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
1. Description *tabular-intro*
|
|
||||||
|
|
||||||
Sometimes, it's useful to line up text. Naturally, it's nicer to have the
|
|
||||||
computer do this for you, since aligning things by hand quickly becomes
|
|
||||||
unpleasant. While there are other plugins for aligning text, the ones I've
|
|
||||||
tried are either impossibly difficult to understand and use, or too simplistic
|
|
||||||
to handle complicated tasks. This plugin aims to make the easy things easy
|
|
||||||
and the hard things possible, without providing an unnecessarily obtuse
|
|
||||||
interface. It's still a work in progress, and criticisms are welcome.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
2. Walkthrough *tabular-walkthrough*
|
|
||||||
|
|
||||||
Tabular's commands are based largely on regular expressions. The basic
|
|
||||||
technique used by Tabular is taking some regex to match field delimiters,
|
|
||||||
splitting the input lines at those delimiters, trimming unnecessary spaces
|
|
||||||
from the non-delimiter parts, padding the non-delimiter parts of the lines
|
|
||||||
with spaces to make them the same length, and joining things back together
|
|
||||||
again.
|
|
||||||
|
|
||||||
For instance, consider starting with the following lines:
|
|
||||||
>
|
|
||||||
Some short phrase,some other phrase
|
|
||||||
A much longer phrase here,and another long phrase
|
|
||||||
<
|
|
||||||
Let's say we want to line these lines up at the commas. We can tell
|
|
||||||
Tabularize to do this by passing a pattern matching , to the Tabularize
|
|
||||||
command:
|
|
||||||
>
|
|
||||||
:Tabularize /,
|
|
||||||
|
|
||||||
Some short phrase , some other phrase
|
|
||||||
A much longer phrase here , and another long phrase
|
|
||||||
<
|
|
||||||
I encourage you to try copying those lines to another buffer and trying to
|
|
||||||
call :Tabularize. You'll want to take notice of two things quickly: First,
|
|
||||||
instead of requiring a range, Tabularize tries to figure out what you want to
|
|
||||||
happen. Since it knows that you want to act on lines matching a comma, it
|
|
||||||
will look upwards and downwards for lines around the current line that match a
|
|
||||||
comma, and consider all contiguous lines matching the pattern to be the range
|
|
||||||
to be acted upon. You can always override this by specifying a range, though.
|
|
||||||
|
|
||||||
The second thing you should notice is that you'll almost certainly be able to
|
|
||||||
abbreviate :Tabularize to :Tab - using this form in mappings and scripts is
|
|
||||||
discouraged as it will make conflicts with other scripts more likely, but for
|
|
||||||
interactive use it's a nice timesaver. Another convenience feature is that
|
|
||||||
running :Tabularize without providing a new pattern will cause it to reuse the
|
|
||||||
last pattern it was called with.
|
|
||||||
|
|
||||||
So, anyway, now the commas line up. Splitting the lines on commas, Tabular
|
|
||||||
realized that 'Some short phrase' would need to be padded with spaces to match
|
|
||||||
the length of 'A much longer phrase here', and it did that before joining the
|
|
||||||
lines back together. You'll also notice that, in addition to the spaces
|
|
||||||
inserting for padding, extra spaces were inserted between fields. That's
|
|
||||||
because by default, Tabular prints things left-aligned with one space between
|
|
||||||
fields. If you wanted to print things right-aligned with no spaces between
|
|
||||||
fields, you would provide a different format to the Tabularize command:
|
|
||||||
>
|
|
||||||
:Tabularize /,/r0
|
|
||||||
|
|
||||||
Some short phrase, some other phrase
|
|
||||||
A much longer phrase here,and another long phrase
|
|
||||||
<
|
|
||||||
A format specifier is either l, r, or c, followed by one or more digits. If
|
|
||||||
the letter is l, the field will be left aligned, similarly for r and right
|
|
||||||
aligning and c and center aligning. The number following the letter is the
|
|
||||||
number of spaces padding to insert before the start of the next field.
|
|
||||||
Multiple format specifiers can be added to the same command - each field will
|
|
||||||
be printed with the next format specifier in the list; when they all have been
|
|
||||||
used the first will be used again, and so on. So, the last command right
|
|
||||||
aligned every field, then inserted 0 spaces of padding before the next field.
|
|
||||||
What if we wanted to right align the text before the comma, and left align the
|
|
||||||
text after the comma? The command would look like this:
|
|
||||||
>
|
|
||||||
:Tabularize /,/r1c1l0
|
|
||||||
|
|
||||||
Some short phrase , some other phrase
|
|
||||||
A much longer phrase here , and another long phrase
|
|
||||||
<
|
|
||||||
That command would be read as "Align the matching text, splitting fields on
|
|
||||||
commas. Print everything before the first comma right aligned, then 1 space,
|
|
||||||
then the comma center aligned, then 1 space, then everything after the comma
|
|
||||||
left aligned." Notice that the alignment of the field the comma is in is
|
|
||||||
irrelevant - since it's only 1 cell wide, it looks the same whether it's right,
|
|
||||||
left, or center aligned. Also notice that the 0 padding spaces specified for
|
|
||||||
the 3rd field are unused - but they would be used if there were enough fields
|
|
||||||
to require looping through the fields again. For instance:
|
|
||||||
>
|
|
||||||
abc,def,ghi
|
|
||||||
a,b
|
|
||||||
a,b,c
|
|
||||||
|
|
||||||
:Tabularize /,/r1c1l0
|
|
||||||
|
|
||||||
abc , def, ghi
|
|
||||||
a , b
|
|
||||||
a , b , c
|
|
||||||
<
|
|
||||||
Notice that now, the format pattern has been reused; field 4 (the second comma)
|
|
||||||
is right aligned, field 5 is center aligned. No spaces were inserted between
|
|
||||||
the 3rd field (containing "def") and the 4th field (the second comma) because
|
|
||||||
the format specified 'l0'.
|
|
||||||
|
|
||||||
But, what if you only wanted to act on the first comma on the line, rather than
|
|
||||||
all of the commas on the line? Let's say we want everything before the first
|
|
||||||
comma right aligned, then the comma, then everything after the comma left
|
|
||||||
aligned:
|
|
||||||
>
|
|
||||||
abc,def,ghi
|
|
||||||
a,b
|
|
||||||
a,b,c
|
|
||||||
|
|
||||||
:Tabularize /^[^,]*\zs,/r0c0l0
|
|
||||||
|
|
||||||
abc,def,ghi
|
|
||||||
a,b
|
|
||||||
a,b,c
|
|
||||||
<
|
|
||||||
Here, we used a Vim regex that would only match the first comma on the line.
|
|
||||||
It matches the beginning of the line, followed by all the non-comma characters
|
|
||||||
up to the first comma, and then forgets about what it matched so far and
|
|
||||||
pretends that the match starts exactly at the comma.
|
|
||||||
|
|
||||||
But, now that this command does exactly what we want it to, it's become pretty
|
|
||||||
unwieldy. It would be unpleasant to need to type that more than once or
|
|
||||||
twice. The solution is to assign a name to it.
|
|
||||||
>
|
|
||||||
:AddTabularPattern first_comma /^[^,]*\zs,/r0c0l0
|
|
||||||
<
|
|
||||||
Now, typing ":Tabularize first_comma" will do the same thing as typing the
|
|
||||||
whole pattern out each time. Of course this is more useful if you store the
|
|
||||||
name in a file to be used later.
|
|
||||||
|
|
||||||
NOTE: In order to make these new commands available every time vim starts,
|
|
||||||
you'll need to put those new commands into a .vim file in a plugin directory
|
|
||||||
somewhere in your 'runtimepath'. In order to make sure that Tabular.vim has
|
|
||||||
already been loaded before your file tries to use :AddTabularPattern or
|
|
||||||
:AddTabularPipeline, the new file should be installed in an after/plugin
|
|
||||||
directory in 'runtimepath'. In general, it will be safe to find out where the
|
|
||||||
TabularMaps.vim plugin was installed, and place other files extending
|
|
||||||
Tabular.vim in the same directory as TabularMaps.vim. For more information,
|
|
||||||
and some suggested best practices, check out the |tabular-scripting| section.
|
|
||||||
|
|
||||||
Lastly, we'll approach the case where tabular cannot achieve your desired goal
|
|
||||||
just by splitting lines appart, trimming whitespace, padding with whitespace,
|
|
||||||
and rejoining the lines. As an example, consider the multiple_spaces command
|
|
||||||
from TabularMaps.vim. The goal is to split using two or more spaces as a
|
|
||||||
field delimiter, and join fields back together, properly lined up, with only
|
|
||||||
two spaces between the end of each field and the beginning of the next.
|
|
||||||
Unfortunately, Tabular can't do this with only the commands we know so far:
|
|
||||||
>
|
|
||||||
:Tabularize / /
|
|
||||||
<
|
|
||||||
The above function won't work, because it will consider "a b" as 5 fields
|
|
||||||
delimited by two pairs of 2 spaces ( 'a', ' ', '', ' ', 'b' ) instead of as
|
|
||||||
3 fields delimited by one set of 2 or more spaces ( 'a', ' ', 'b' ).
|
|
||||||
>
|
|
||||||
:Tabularize / \+/
|
|
||||||
<
|
|
||||||
The above function won't work either, because it will leave the delimiter as 4
|
|
||||||
spaces when used against "a b", meaning that we would fail at our goal of
|
|
||||||
collapsing everything down to two spaces between fields. So, we need a new
|
|
||||||
command to get around this:
|
|
||||||
>
|
|
||||||
:AddTabularPipeline multiple_spaces / \{2,}/
|
|
||||||
\ map(a:lines, "substitute(v:val, ' \{2,}', ' ', 'g')")
|
|
||||||
\ | tabular#TabularizeStrings(a:lines, ' ', 'l0')
|
|
||||||
<
|
|
||||||
Yeah. I know it looks complicated. Bear with me. I probably will try to add
|
|
||||||
in some shortcuts for this syntax, but this verbose will be guaranteed to
|
|
||||||
always work.
|
|
||||||
|
|
||||||
You should already recognize the name being assigned. The next thing to
|
|
||||||
happen is / \{2,}/ which is a pattern specifying which lines should
|
|
||||||
automatically be included in the range when no range is given. Without this,
|
|
||||||
there would be no pattern to use for extending the range. Everything after
|
|
||||||
that is a | separated list of expressions to be evaluated. In the context in
|
|
||||||
which they will be evaluated, a:lines will be set to a List of Strings
|
|
||||||
containing the text of the lines being filtered as they procede through the
|
|
||||||
pipeline you've set up. The \ at the start of the lines are just vim's line
|
|
||||||
continuation marker; you needn't worry much about them. So, the first
|
|
||||||
expression in the pipeline transforms each line by replacing every instance of
|
|
||||||
2 or more spaces with exactly two spaces. The second command in the pipeline
|
|
||||||
performs the equivalent of ":Tabularize / /l0"; the only difference is that
|
|
||||||
it is operating on a List of Strings rather than text in the buffer. At the
|
|
||||||
end of the pipeline, the Strings in the modified a:lines (or the return value
|
|
||||||
of the last expression in the pipeline, if it returns a List) will replace the
|
|
||||||
chosen range.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
3. Extending *tabular-scripting*
|
|
||||||
|
|
||||||
As mentioned above, the most important consideration when extending Tabular
|
|
||||||
with new maps or commands is that your plugin must be loaded after Tabular.vim
|
|
||||||
has finished loading, and only if Tabular.vim has loaded successfully. The
|
|
||||||
easiest approach to making sure it loads after Tabular.vim is simply putting
|
|
||||||
the new file (we'll call it "tabular_extra.vim" as an example) into an
|
|
||||||
"after/plugin/" directory in 'runtimepath', for instance:
|
|
||||||
>
|
|
||||||
~/.vim/after/plugin/tabular_extra.vim
|
|
||||||
<
|
|
||||||
The default set of mappings, found in "TabularMaps.vim", is installed in
|
|
||||||
the after/plugin/ subdirectory of whatever directory Tabular was installed to.
|
|
||||||
|
|
||||||
The other important consideration is making sure that your commands are only
|
|
||||||
called if Tabular.vim was actually loaded. The easiest way to do this is by
|
|
||||||
checking for the existence of the :Tabularize command at the start of your
|
|
||||||
plugin. A short example plugin would look like this:
|
|
||||||
>
|
|
||||||
" after/plugin/my_tabular_commands.vim
|
|
||||||
" Provides extra :Tabularize commands
|
|
||||||
|
|
||||||
if !exists(':Tabularize')
|
|
||||||
finish " Give up here; the Tabular plugin musn't have been loaded
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Make line wrapping possible by resetting the 'cpo' option, first saving it
|
|
||||||
let s:save_cpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
AddTabularPattern! asterisk /*/l1
|
|
||||||
|
|
||||||
AddTabularPipeline! remove_leading_spaces /^ /
|
|
||||||
\ map(a:lines, "substitute(v:val, '^ *', '', '')")
|
|
||||||
|
|
||||||
" Restore the saved value of 'cpo'
|
|
||||||
let &cpo = s:save_cpo
|
|
||||||
unlet s:save_cpo
|
|
||||||
<
|
|
||||||
==============================================================================
|
|
||||||
vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
|
|
||||||
|
|
@ -1,670 +0,0 @@
|
||||||
*ctrlp.txt* Fuzzy file, buffer, mru and tag finder. v1.6.4
|
|
||||||
*CtrlP* *ControlP* *'ctrlp'* *'ctrl-p'*
|
|
||||||
===============================================================================
|
|
||||||
# #
|
|
||||||
# :::::::: ::::::::::: ::::::::: ::: ::::::::: #
|
|
||||||
# :+: :+: :+: :+: :+: :+: :+: :+: #
|
|
||||||
# +:+ +:+ +:+ +:+ +:+ +:+ +:+ #
|
|
||||||
# +#+ +#+ +#++:++#: +#+ +#++:++#+ #
|
|
||||||
# +#+ +#+ +#+ +#+ +#+ +#+ #
|
|
||||||
# #+# #+# #+# #+# #+# #+# #+# #
|
|
||||||
# ######## ### ### ### ########## ### #
|
|
||||||
# #
|
|
||||||
===============================================================================
|
|
||||||
CONTENTS *ctrlp-contents*
|
|
||||||
|
|
||||||
1. Intro........................................|ctrlp-intro|
|
|
||||||
2. Options......................................|ctrlp-options|
|
|
||||||
3. Commands.....................................|ctrlp-commands|
|
|
||||||
4. Mappings.....................................|ctrlp-mappings|
|
|
||||||
5. Input Formats................................|ctrlp-input-formats|
|
|
||||||
6. Extensions...................................|ctrlp-extensions|
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
1. Intro *ctrlp-intro*
|
|
||||||
|
|
||||||
Full path fuzzy file, buffer and MRU file finder with an intuitive interface.
|
|
||||||
Written in pure Vimscript for MacVim and Vim version 7.0+. Has full support for
|
|
||||||
Vim’s |regexp| as search pattern, built-in MRU monitoring, project’s root
|
|
||||||
finder, and more.
|
|
||||||
|
|
||||||
To enable optional extensions (tag, quickfix, dir...), see |ctrlp-extensions|.
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
2. Options *ctrlp-options*
|
|
||||||
|
|
||||||
Below are the available options and their default values:~
|
|
||||||
|
|
||||||
*'g:ctrlp_map'*
|
|
||||||
Use this option to change the mapping to invoke |CtrlP| in |Normal| mode: >
|
|
||||||
let g:ctrlp_map = '<c-p>'
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:loaded_ctrlp'*
|
|
||||||
Use this option to disable the plugin completely: >
|
|
||||||
let g:loaded_ctrlp = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_by_filename'*
|
|
||||||
Set this to 1 to set search by filename (not full path) as the default: >
|
|
||||||
let g:ctrlp_by_filename = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_regexp_search'*
|
|
||||||
Set this to 1 to set |regexp| search as the default: >
|
|
||||||
let g:ctrlp_regexp_search = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_match_window_bottom'*
|
|
||||||
Set this to 0 to show the match window at the top of the screen: >
|
|
||||||
let g:ctrlp_match_window_bottom = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_match_window_reversed'*
|
|
||||||
Reverse the sort order of the matched files in the match window. The default
|
|
||||||
setting is from bottom to top: >
|
|
||||||
let g:ctrlp_match_window_reversed = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_max_height'*
|
|
||||||
Set the maximum height of the match window: >
|
|
||||||
let g:ctrlp_max_height = 10
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_jump_to_buffer'*
|
|
||||||
Set this to 0 to disable the jump-to-open-buffer feature. Set to 2 to also jump
|
|
||||||
tab if the selected buffer’s opened in another tab: >
|
|
||||||
let g:ctrlp_jump_to_buffer = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_working_path_mode'*
|
|
||||||
When starting up the prompt, temporarily set the working directory (i.e. the
|
|
||||||
|current-directory|) to:
|
|
||||||
1 - the parent directory of the current file.
|
|
||||||
2 - the nearest ancestor that contains one of these directories/files:
|
|
||||||
.git/
|
|
||||||
.hg/
|
|
||||||
.bzr/
|
|
||||||
_darcs/
|
|
||||||
root.dir
|
|
||||||
.vimprojects
|
|
||||||
0 - don’t manage working directory.
|
|
||||||
>
|
|
||||||
let g:ctrlp_working_path_mode = 2
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_root_markers'*
|
|
||||||
Use this to set your own root markers in addition to the default ones. Your
|
|
||||||
markers will take precedence: >
|
|
||||||
let g:ctrlp_root_markers = ['']
|
|
||||||
<
|
|
||||||
These markers (builtins and yours) will serve as identifiers for the '/' and
|
|
||||||
'\' special inputs (section 5.e)
|
|
||||||
|
|
||||||
*'g:ctrlp_use_caching'*
|
|
||||||
Set this to 0 to disable per-session caching. When disabled, caching will still
|
|
||||||
be enabled for directories that have more than 4000 files: >
|
|
||||||
let g:ctrlp_use_caching = 1
|
|
||||||
<
|
|
||||||
Note: you can quickly purge the cache by pressing <F5> while inside |CtrlP|.
|
|
||||||
|
|
||||||
*'g:ctrlp_clear_cache_on_exit'*
|
|
||||||
Set this to 0 to enable cross-sessions caching: >
|
|
||||||
let g:ctrlp_clear_cache_on_exit = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_cache_dir'*
|
|
||||||
Set the directory to store the cache files: >
|
|
||||||
let g:ctrlp_cache_dir = $HOME.'/.ctrlp_cache'
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_prompt_mappings'*
|
|
||||||
Use this to customize the mappings inside |CtrlP|’s prompt to your liking. You
|
|
||||||
only need to keep the lines that you’ve changed the values (inside []): >
|
|
||||||
let g:ctrlp_prompt_mappings = {
|
|
||||||
\ 'PrtBS()': ['<bs>'],
|
|
||||||
\ 'PrtDelete()': ['<del>'],
|
|
||||||
\ 'PrtDeleteWord()': ['<c-w>'],
|
|
||||||
\ 'PrtClear()': ['<c-u>'],
|
|
||||||
\ 'PrtSelectMove("j")': ['<c-j>', '<down>'],
|
|
||||||
\ 'PrtSelectMove("k")': ['<c-k>', '<up>'],
|
|
||||||
\ 'PrtHistory(-1)': ['<c-n>'],
|
|
||||||
\ 'PrtHistory(1)': ['<c-p>'],
|
|
||||||
\ 'AcceptSelection("e")': ['<cr>', '<2-LeftMouse>'],
|
|
||||||
\ 'AcceptSelection("h")': ['<c-x>', '<c-cr>', '<c-s>'],
|
|
||||||
\ 'AcceptSelection("t")': ['<c-t>', '<MiddleMouse>'],
|
|
||||||
\ 'AcceptSelection("v")': ['<c-v>', '<c-q>', '<RightMouse>'],
|
|
||||||
\ 'ToggleFocus()': ['<tab>'],
|
|
||||||
\ 'ToggleRegex()': ['<c-r>'],
|
|
||||||
\ 'ToggleByFname()': ['<c-d>'],
|
|
||||||
\ 'ToggleType(1)': ['<c-f>', '<c-up'],
|
|
||||||
\ 'ToggleType(-1)': ['<c-b>', '<c-down>'],
|
|
||||||
\ 'PrtCurStart()': ['<c-a>'],
|
|
||||||
\ 'PrtCurEnd()': ['<c-e>'],
|
|
||||||
\ 'PrtCurLeft()': ['<c-h>', '<left>'],
|
|
||||||
\ 'PrtCurRight()': ['<c-l>', '<right>'],
|
|
||||||
\ 'PrtClearCache()': ['<F5>'],
|
|
||||||
\ 'PrtDeleteMRU()': ['<F7>'],
|
|
||||||
\ 'CreateNewFile()': ['<c-y>'],
|
|
||||||
\ 'MarkToOpen()': ['<c-z>'],
|
|
||||||
\ 'OpenMulti()': ['<c-o>'],
|
|
||||||
\ 'PrtExit()': ['<esc>', '<c-c>', '<c-g>'],
|
|
||||||
\ }
|
|
||||||
<
|
|
||||||
If you have problem with <bs> moving left instead of deleting a char, add this
|
|
||||||
to your |vimrc|: >
|
|
||||||
let g:ctrlp_prompt_mappings = {
|
|
||||||
\ 'PrtBS()': ['<c-h>'],
|
|
||||||
\ 'PrtCurLeft()': ['<left>'],
|
|
||||||
\ }
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_mruf_max'*
|
|
||||||
Specify the number of recently opened files you want |CtrlP| to remember: >
|
|
||||||
let g:ctrlp_mruf_max = 250
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_mruf_exclude'*
|
|
||||||
Files you don’t want |CtrlP| to remember; use |regexp| to specify the patterns:
|
|
||||||
>
|
|
||||||
let g:ctrlp_mruf_exclude = ''
|
|
||||||
<
|
|
||||||
Examples: >
|
|
||||||
let g:ctrlp_mruf_exclude = '/tmp/.*\|/temp/.*' " MacOSX/Linux
|
|
||||||
let g:ctrlp_mruf_exclude = '^C:\\dev\\tmp\\.*' " Windows
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_mruf_include'*
|
|
||||||
And if you want |CtrlP| to only remember some files, specify them here: >
|
|
||||||
let g:ctrlp_mruf_include = ''
|
|
||||||
<
|
|
||||||
Example: >
|
|
||||||
let g:ctrlp_mruf_include = '\.py$\|\.rb$'
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_mruf_case_sensitive'*
|
|
||||||
Match this with your file system case-sensitivity setting to avoid duplicate
|
|
||||||
MRU entries: >
|
|
||||||
let g:ctrlp_mruf_case_sensitive = 1
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_dotfiles'*
|
|
||||||
Set this to 0 if you don’t want |CtrlP| to search for dotfiles and dotdirs: >
|
|
||||||
let g:ctrlp_dotfiles = 1
|
|
||||||
<
|
|
||||||
You can also use |'wildignore'| to exclude anything from the search.
|
|
||||||
e.g. exclude version control directories from the results: >
|
|
||||||
set wildignore+=*/.git/*,*/.hg/*,*/.svn/* " Linux/MacOSX
|
|
||||||
set wildignore+=.git\*,.hg\*,.svn\* " Windows
|
|
||||||
<
|
|
||||||
Note: the `*/` in front of each dotfile glob is required for the dotfiles
|
|
||||||
search feature to work correctly along side with |wildignore|. If you’ve
|
|
||||||
disabled dotfiles search (set |g:ctrlp_dotfiles| to 0), then you can ignore
|
|
||||||
this.
|
|
||||||
|
|
||||||
Other note: |wildignore| influences the result of |expand()|, |globpath()| and
|
|
||||||
|glob()| which many plugins use to find stuff on the system (e.g. fugitive.vim
|
|
||||||
looks for .git/, some other plugins look for external exe tools on Windows).
|
|
||||||
So be a little mindful of what you put in your |wildignore|.
|
|
||||||
|
|
||||||
*'g:ctrlp_highlight_match'*
|
|
||||||
Use this to enable/disable highlighting of the matched patterns and to specify
|
|
||||||
the highlight group that’ll be used: >
|
|
||||||
let g:ctrlp_highlight_match = [1, 'Identifier']
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_max_files'*
|
|
||||||
The maximum number of files to scan, set to 0 for no limit: >
|
|
||||||
let g:ctrlp_max_files = 20000
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_max_depth'*
|
|
||||||
The maximum depth of a directory tree to recurse into: >
|
|
||||||
let g:ctrlp_max_depth = 40
|
|
||||||
<
|
|
||||||
Note: the larger these values, the more memory Vim uses.
|
|
||||||
|
|
||||||
*'g:ctrlp_user_command'*
|
|
||||||
Specify an external tool to use for listing files instead of Vim’s globpath().
|
|
||||||
Use %s in place of the target directory: >
|
|
||||||
let g:ctrlp_user_command = ''
|
|
||||||
<
|
|
||||||
Examples: >
|
|
||||||
let g:ctrlp_user_command = 'find %s -type f' " MacOSX/Linux
|
|
||||||
let g:ctrlp_user_command = 'dir %s /-n /b /s /a-d' " Windows
|
|
||||||
<
|
|
||||||
You can also use 'grep', 'findstr' or something else to filter the results.
|
|
||||||
Examples: >
|
|
||||||
let g:ctrlp_user_command = 'find %s -type f | grep (?!tmp/.*)'
|
|
||||||
let g:ctrlp_user_command = 'dir %s /-n /b /s /a-d | findstr .*\.py$'
|
|
||||||
<
|
|
||||||
Use a version control listing command when inside a repository, this is a lot
|
|
||||||
faster when working with large projects: >
|
|
||||||
let g:ctrlp_user_command = [repo_marker, vcs_ls_command, fallback_command]
|
|
||||||
<
|
|
||||||
If the fallback_command is empty or not defined, globpath() will then be used
|
|
||||||
when searching outside a repo.
|
|
||||||
Examples: >
|
|
||||||
let g:ctrlp_user_command = ['.git/', 'cd %s && git ls-files']
|
|
||||||
let g:ctrlp_user_command = ['.hg/', 'hg --cwd %s locate --fullpath -I .']
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_open_new_file'*
|
|
||||||
Use this option to specify how the newly created file is to be opened when
|
|
||||||
pressing <c-y>:
|
|
||||||
1 - in a new tab
|
|
||||||
2 - in a new horizontal split
|
|
||||||
3 - in a new vertical split
|
|
||||||
0 - in the current window
|
|
||||||
>
|
|
||||||
let g:ctrlp_open_new_file = 3
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_max_history'*
|
|
||||||
The maximum number of input strings you want |CtrlP| to remember. The default
|
|
||||||
value mirrors Vim’s global |'history'| option: >
|
|
||||||
let g:ctrlp_max_history = &history
|
|
||||||
<
|
|
||||||
Set to 0 to disable prompt’s history.
|
|
||||||
|
|
||||||
*'g:ctrlp_open_multi'*
|
|
||||||
If non-zero, this will enable opening multiple files with <c-z> and <c-o>: >
|
|
||||||
let g:ctrlp_open_multi = '1v'
|
|
||||||
<
|
|
||||||
For the number:
|
|
||||||
If bigger than 1, it’ll be used as the maximum number of windows or tabs to
|
|
||||||
create when opening the files (the rest will be hidden buffers). If is 1,
|
|
||||||
<c-o> will open all files, each in a new window or new tab.
|
|
||||||
For the letter:
|
|
||||||
t - each in a tab
|
|
||||||
h - each in a horizontal split
|
|
||||||
v - each in a vertical split
|
|
||||||
|
|
||||||
*'g:ctrlp_dont_split'*
|
|
||||||
When opening a file with <cr>, |CtrlP| avoids opening it in windows created by
|
|
||||||
plugins, help and quickfix. Use this to setup some exceptions: >
|
|
||||||
let g:ctrlp_dont_split = ''
|
|
||||||
<
|
|
||||||
Acceptable values are partial names or filetypes of the special buffers. Use
|
|
||||||
|regexp| to specify the pattern. Example: >
|
|
||||||
let g:ctrlp_dont_split = 'netrw\|help'
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_follow_symlinks'*
|
|
||||||
Set this to 1 to follow symbolic links when listing files: >
|
|
||||||
let g:ctrlp_follow_symlinks = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
*'g:ctrlp_lazy_update'*
|
|
||||||
Set this to 1 to enable the lazy-update feature: only update the match window
|
|
||||||
after typing’s been stopped for a certain amount of time: >
|
|
||||||
let g:ctrlp_lazy_update = 0
|
|
||||||
<
|
|
||||||
If is 1, update after 250ms. If bigger than 1, the number will be used as the
|
|
||||||
delay time in milliseconds.
|
|
||||||
|
|
||||||
*'g:ctrlp_use_migemo'*
|
|
||||||
Set this to 1 to use Migemo Pattern for Japanese filenames. Migemo Search only
|
|
||||||
works in |regexp| mode. To split the pattern, separate words with space: >
|
|
||||||
let g:ctrlp_use_migemo = 0
|
|
||||||
<
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
3. Commands *ctrlp-commands*
|
|
||||||
|
|
||||||
*:CtrlP*
|
|
||||||
:CtrlP [starting-directory]
|
|
||||||
Open |CtrlP| in find file mode.
|
|
||||||
|
|
||||||
If no argument is given, the value of |g:ctrlp_working_path_mode| will be
|
|
||||||
used to determine the starting directory.
|
|
||||||
You can use <tab> to auto-complete the [starting-directory] when typing it.
|
|
||||||
|
|
||||||
*:CtrlPBuffer*
|
|
||||||
:CtrlPBuffer
|
|
||||||
Open |CtrlP| in find buffer mode.
|
|
||||||
|
|
||||||
*:CtrlPMRU*
|
|
||||||
:CtrlPMRU
|
|
||||||
Open |CtrlP| in find Most-Recently-Used file mode.
|
|
||||||
|
|
||||||
*:ClearCtrlPCache*
|
|
||||||
:ClearCtrlPCache
|
|
||||||
Flush the cache for the current working directory. The same as pressing <F5>
|
|
||||||
inside |CtrlP|.
|
|
||||||
|
|
||||||
*:ClearAllCtrlPCaches*
|
|
||||||
:ClearAllCtrlPCaches
|
|
||||||
Delete all the cache files saved in |ctrlp_cache_dir|.
|
|
||||||
|
|
||||||
*:ResetCtrlP*
|
|
||||||
:ResetCtrlP
|
|
||||||
Reset all options, take in new values of the option variables in section 2.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
The following commands ignore the current value of |g:ctrlp_working_path_mode|:
|
|
||||||
|
|
||||||
:CtrlPCurWD *:CtrlPCurWD*
|
|
||||||
This acts like |:CtrlP| with |path_mode| = 0
|
|
||||||
|
|
||||||
:CtrlPCurFile *:CtrlPCurFile*
|
|
||||||
This acts like |:CtrlP| with |path_mode| = 1
|
|
||||||
|
|
||||||
:CtrlPRoot *:CtrlPRoot*
|
|
||||||
This acts like |:CtrlP| with |path_mode| = 2
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
4. Mappings *ctrlp-mappings*
|
|
||||||
|
|
||||||
*'ctrlp-<c-p>'*
|
|
||||||
<c-p>
|
|
||||||
Default |Normal| mode mapping to open the |CtrlP| prompt in find file mode.
|
|
||||||
|
|
||||||
Once inside the prompt:~
|
|
||||||
|
|
||||||
<c-r> *'ctrlp-fullregexp'*
|
|
||||||
Toggle between the string mode (section 5.a & b) and full |regexp| mode.
|
|
||||||
(note: in full |regexp| mode, the prompt’s base is 'r>>' instead of '>>>')
|
|
||||||
|
|
||||||
See also |input-formats| and |g:ctrlp_regexp_search|.
|
|
||||||
|
|
||||||
<c-d>
|
|
||||||
Toggle between full path search and filename only search.
|
|
||||||
(note: in filename mode, the prompt’s base is '>d>' instead of '>>>')
|
|
||||||
|
|
||||||
<c-f>, 'forward'
|
|
||||||
<c-up>
|
|
||||||
Scroll to the 'next' search mode in the sequence.
|
|
||||||
|
|
||||||
<c-b>, 'backward'
|
|
||||||
<c-down>
|
|
||||||
Scroll to the 'previous' search mode in the sequence.
|
|
||||||
|
|
||||||
<tab>
|
|
||||||
Toggle the focus between the match window and the prompt.
|
|
||||||
|
|
||||||
<c-j>,
|
|
||||||
<down>
|
|
||||||
Move selection down
|
|
||||||
|
|
||||||
<c-k>,
|
|
||||||
<up>
|
|
||||||
Move selection up
|
|
||||||
|
|
||||||
<c-a>
|
|
||||||
Move the cursor to the 'start' of the prompt
|
|
||||||
|
|
||||||
<c-e>
|
|
||||||
Move the cursor to the 'end' of the prompt
|
|
||||||
|
|
||||||
<c-h>,
|
|
||||||
<left>
|
|
||||||
Move the cursor one character to the 'left'
|
|
||||||
|
|
||||||
<c-l>,
|
|
||||||
<right>
|
|
||||||
Move the cursor one character to the 'right'
|
|
||||||
|
|
||||||
<c-w>
|
|
||||||
Delete a preceding inner word
|
|
||||||
|
|
||||||
<c-u>
|
|
||||||
Clear the input field
|
|
||||||
|
|
||||||
<cr>
|
|
||||||
Open selected file in the active window if possible.
|
|
||||||
|
|
||||||
<c-t>
|
|
||||||
Open selected file in a new 'tab'
|
|
||||||
|
|
||||||
<c-v>
|
|
||||||
Open selected file in a 'vertical' split
|
|
||||||
|
|
||||||
<c-cr>,
|
|
||||||
<c-s>,
|
|
||||||
<c-x>
|
|
||||||
Open selected file in a 'horizontal' split
|
|
||||||
|
|
||||||
<c-y>
|
|
||||||
Create a new file and its parent directories.
|
|
||||||
|
|
||||||
<c-n>
|
|
||||||
Next string in the prompt’s history
|
|
||||||
|
|
||||||
<c-p>
|
|
||||||
Previous string in the prompt’s history
|
|
||||||
|
|
||||||
<c-z>
|
|
||||||
Mark/unmark a file to be opened with <c-o>.
|
|
||||||
|
|
||||||
<c-o>
|
|
||||||
Open files marked by <c-z>.
|
|
||||||
|
|
||||||
<F5>
|
|
||||||
- Refresh the match window and purge the cache for the current directory.
|
|
||||||
- Remove deleted files from MRU list.
|
|
||||||
|
|
||||||
<F7>
|
|
||||||
Clear MRU list.
|
|
||||||
|
|
||||||
<esc>,
|
|
||||||
<c-c>,
|
|
||||||
<c-g>
|
|
||||||
Exit |CtrlP|. <c-c> can also be used to stop the file scan.
|
|
||||||
|
|
||||||
Choose your own mappings with |g:ctrlp_prompt_mappings|.
|
|
||||||
|
|
||||||
When inside the match window (press <tab> to switch):~
|
|
||||||
|
|
||||||
a-z
|
|
||||||
0-9
|
|
||||||
~^-=;`',.+!@#$%&_(){}[]
|
|
||||||
Cycle through the lines with the first letter (of paths or filenames) that
|
|
||||||
matches that key.
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
5. Input Formats *ctrlp-input-formats*
|
|
||||||
|
|
||||||
Formats for inputting in the prompt:~
|
|
||||||
|
|
||||||
a) Simple string.
|
|
||||||
e.g. 'abc' is understood internally as 'a[^a]\{-}b[^b]\{-}c'
|
|
||||||
|
|
||||||
b) Vim |regexp|. If the input string contains '*' or '|', it’ll be treated as
|
|
||||||
a Vim’s |regexp| |pattern| without any modification.
|
|
||||||
e.g. 'abc\d*efg' will be read as 'abc\d*efg'.
|
|
||||||
|
|
||||||
See also |ctrlp-fullregexp| (key map) and |g:ctrlp_regexp_search| (option).
|
|
||||||
|
|
||||||
c) End the string with a colon ':' followed by a Vim command to execute that
|
|
||||||
command after opening the file. If you need to use ':' in the command,
|
|
||||||
escape it with a backslash: '\:'.
|
|
||||||
e.g. 'abc:45' will open the selected file and jump to line 45.
|
|
||||||
'abc:/my\:function' will open the selected file and jump to the first
|
|
||||||
instance of 'my:function'.
|
|
||||||
'abc:+setf\ myfiletype|50' will open the selected file and set its
|
|
||||||
filetype to 'myfiletype' then jump to line 50.
|
|
||||||
|
|
||||||
See also Vim’s |++opt| and |+cmd|.
|
|
||||||
|
|
||||||
d) Type exactly two dots '..' at the start of the prompt and press enter to go
|
|
||||||
backward in the directory tree by 1 level. If the parent directory is
|
|
||||||
large, this might be slow.
|
|
||||||
|
|
||||||
e) Similarly submit '/' or '\' to find and go to the project’s root. If the
|
|
||||||
project is large, using a VCS listing command to look for files might help
|
|
||||||
speeding up the intial scan (see |g:ctrlp_user_command| for more details).
|
|
||||||
|
|
||||||
f) Type the name of a non-existent file and press <c-y> to create it.
|
|
||||||
e.g. 'parentdir/file.txt' will create a directory named 'parentdir' as well
|
|
||||||
as 'file.txt'.
|
|
||||||
Use '\' in place of '/' on Windows (if |'ssl'| is not set).
|
|
||||||
|
|
||||||
g) Submit ? to open this help file.
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
6. Extensions *g:ctrlp-extensions*
|
|
||||||
|
|
||||||
Extensions are optional. To enable an extension, add its name to the variable
|
|
||||||
g:ctrlp_extensions: >
|
|
||||||
let g:ctrlp_extensions = ['tag', 'quickfix', 'dir']
|
|
||||||
<
|
|
||||||
The order of the items will be the order they appear on the statusline and when
|
|
||||||
using <c-f>, <c-b>.
|
|
||||||
|
|
||||||
Available extensions:~
|
|
||||||
|
|
||||||
*:CtrlPTag*
|
|
||||||
* Tag mode:~
|
|
||||||
- Name: 'tag'
|
|
||||||
- Command: ':CtrlPTag'
|
|
||||||
- Search for a tag within a generated central tags file, and jump to the
|
|
||||||
definition. Use the Vim’s option |'tags'| to specify the names and the
|
|
||||||
locations of the tags file(s). Example: `set tags+=tags/help,doc/tags`
|
|
||||||
|
|
||||||
*:CtrlPQuickfix*
|
|
||||||
* Quickfix mode:~
|
|
||||||
- Name: 'quickfix'
|
|
||||||
- Command: ':CtrlPQuickfix'
|
|
||||||
- Search for an entry in the current quickfix errors and jump to it.
|
|
||||||
|
|
||||||
*:CtrlPDir*
|
|
||||||
* Directory mode:~
|
|
||||||
- Name: 'dir'
|
|
||||||
- Command: ':CtrlPDir'
|
|
||||||
- Search for a directory and change the working directory to it.
|
|
||||||
- Mappings:
|
|
||||||
+ <cr> change the local working directory for |CtrlP| and keep it open.
|
|
||||||
+ <c-t> change the global working directory (exit).
|
|
||||||
+ <c-v> change the local working directory for the current window (exit).
|
|
||||||
+ <c-x> change the global working directory to |CtrlP|’s current local
|
|
||||||
working directory (exit).
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
EXTENDING *ctrlp-extending*
|
|
||||||
|
|
||||||
Extending |CtrlP| is very simple. Simply create a vim file following a short
|
|
||||||
guidelines, place it in autoload/ctrlp/ and add its name to your .vimrc.
|
|
||||||
|
|
||||||
To see how it works, get the sample.vim from the extensions branch on the main
|
|
||||||
git repository (https://github.com/kien/ctrlp.vim/tree/extensions), and place
|
|
||||||
it along with the parent directories somewhere in your runtimepath. Then put
|
|
||||||
this into your .vimrc: >
|
|
||||||
let g:ctrlp_extensions = ['sample']
|
|
||||||
<
|
|
||||||
A new search type will show up the next time you open |CtrlP|.
|
|
||||||
|
|
||||||
For more details, check out the comments inside sample.vim.~
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
CREDITS *ctrlp-credits*
|
|
||||||
|
|
||||||
Developed by Kien Nguyen <github.com/kien>, initially based on the Command-T
|
|
||||||
and the LustyExplorer plugins. No code was taken from these plugins, but I did
|
|
||||||
clone the majority of their (awesome) interfaces and the way they work.
|
|
||||||
|
|
||||||
This was originally written as a module for a would-be larger plugin called
|
|
||||||
AutoDoc.vim which I’ve stopped developing because of lost of interest. I really
|
|
||||||
liked the way Command-T and LustyExplorer deal with user’s input, so I wrote a
|
|
||||||
pure Vimscript version of their prompt window, intended to use it for the
|
|
||||||
aforementioned plugin.
|
|
||||||
|
|
||||||
Homepage: http://kien.github.com/ctrlp.vim
|
|
||||||
Git repository: https://github.com/kien/ctrlp.vim
|
|
||||||
Mercurial repository: https://bitbucket.org/kien/ctrlp.vim
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
THANKS *ctrlp-thanks*
|
|
||||||
|
|
||||||
Thanks to everyone that has submitted ideas, bug reports or helped debugging on
|
|
||||||
gibhub, bitbucket, and through email.
|
|
||||||
|
|
||||||
Special thanks:~
|
|
||||||
|
|
||||||
* Woojong Koh <github.com/wjkoh>
|
|
||||||
Forked and suggested the support for VCS listing commands.
|
|
||||||
|
|
||||||
* Yasuhiro Matsumoto <github.com/mattn>
|
|
||||||
Added option to use Migemo for Japanese language.
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
CHANGELOG *ctrlp-changelog*
|
|
||||||
|
|
||||||
Before 2011/11/30~
|
|
||||||
|
|
||||||
+ New features: Tag, Quickfix and Directory extensions.
|
|
||||||
+ New commands: |:CtrlPTag|, |:CtrlPQuickfix|, |:CtrlPDir|.
|
|
||||||
+ New options: |g:ctrlp_use_migemo|,
|
|
||||||
|g:ctrlp_lazy_update|,
|
|
||||||
|g:ctrlp_follow_symlinks|
|
|
||||||
|
|
||||||
Before 2011/11/13~
|
|
||||||
|
|
||||||
+ New special input: '/' and '\' find root (section 5.e)
|
|
||||||
+ Remove ctrlp#SetWorkingPath().
|
|
||||||
+ Remove |g:ctrlp_mru_files|, make MRU permanent.
|
|
||||||
+ Extend |g:ctrlp_open_multi|, add new ways to open files.
|
|
||||||
+ New option: |g:ctrlp_dont_split|,
|
|
||||||
|g:ctrlp_mruf_case_sensitive|
|
|
||||||
|
|
||||||
Before 2011/10/30~
|
|
||||||
|
|
||||||
+ New feature: Support for custom extensions.
|
|
||||||
<F5> also removes non-existent files from MRU list.
|
|
||||||
+ New option: |g:ctrlp_jump_to_buffer|
|
|
||||||
|
|
||||||
Before 2011/10/12~
|
|
||||||
|
|
||||||
+ New features: Open multiple files.
|
|
||||||
Pass Vim’s |++opt| and |+cmd| to the opening file
|
|
||||||
(section 5.c)
|
|
||||||
Auto-complete each dir for |:CtrlP| [starting-directory]
|
|
||||||
+ New mappings: <c-z> mark/unmark a file to be opened with <c-o>.
|
|
||||||
<c-o> open all marked files.
|
|
||||||
+ New option: |g:ctrlp_open_multi|
|
|
||||||
+ Remove |g:ctrlp_persistent_input|, |g:ctrlp_live_update| and <c-^>.
|
|
||||||
|
|
||||||
Before 2011/09/29~
|
|
||||||
|
|
||||||
+ New mappings: <c-n>, <c-p> next/prev string in the input history.
|
|
||||||
<c-y> create a new file and its parent dirs.
|
|
||||||
+ New options: |g:ctrlp_open_new_file|,
|
|
||||||
|g:ctrlp_max_history|
|
|
||||||
+ Added a new open-in-horizontal-split mapping: <c-x>
|
|
||||||
|
|
||||||
Before 2011/09/19~
|
|
||||||
|
|
||||||
+ New command: |ResetCtrlP|
|
|
||||||
+ New options: |g:ctrlp_max_files|,
|
|
||||||
|g:ctrlp_max_depth|,
|
|
||||||
|g:ctrlp_live_update|
|
|
||||||
+ New mapping: <c-^>
|
|
||||||
|
|
||||||
Before 2011/09/12~
|
|
||||||
|
|
||||||
+ Ability to cycle through matched lines in the match window.
|
|
||||||
+ Extend the behavior of |g:ctrlp_persistent_input|
|
|
||||||
+ Extend the behavior of |:CtrlP|
|
|
||||||
+ New options: |g:ctrlp_dotfiles|,
|
|
||||||
|g:ctrlp_clear_cache_on_exit|,
|
|
||||||
|g:ctrlp_highlight_match|,
|
|
||||||
|g:ctrlp_user_command|
|
|
||||||
+ New special input: '..' (section 5.d)
|
|
||||||
+ New mapping: <F5>.
|
|
||||||
+ New commands: |:CtrlPCurWD|,
|
|
||||||
|:CtrlPCurFile|,
|
|
||||||
|:CtrlPRoot|
|
|
||||||
|
|
||||||
+ New feature: Search in most recently used (MRU) files
|
|
||||||
+ New mapping: <c-b>.
|
|
||||||
+ Extended the behavior of <c-f>.
|
|
||||||
+ New options: |g:ctrlp_mru_files|,
|
|
||||||
|g:ctrlp_mruf_max|,
|
|
||||||
|g:ctrlp_mruf_exclude|,
|
|
||||||
|g:ctrlp_mruf_include|
|
|
||||||
+ New command: |:CtrlPMRUFiles|
|
|
||||||
|
|
||||||
First public release: 2011/09/06~
|
|
||||||
|
|
||||||
===============================================================================
|
|
||||||
vim:ft=help:et:ts=2:sw=2:sts=2:norl
|
|
||||||
1405
.vim/doc/fuf.jax
1405
.vim/doc/fuf.jax
File diff suppressed because it is too large
Load diff
1883
.vim/doc/fuf.txt
1883
.vim/doc/fuf.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,55 +0,0 @@
|
||||||
*l9.txt* Vimスクリプトライブラリ
|
|
||||||
|
|
||||||
Copyright (c) 2009-2010 Takeshi NISHIDA
|
|
||||||
|
|
||||||
l9 *l9*
|
|
||||||
|
|
||||||
概要 |l9-introduction|
|
|
||||||
インストール |l9-installation|
|
|
||||||
使い方 |l9-usage|
|
|
||||||
CHANGELOG |l9-changelog|
|
|
||||||
あばうと |l9-about|
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
概要 *l9-introduction*
|
|
||||||
|
|
||||||
l9はVimスクリプトの関数やコマンドを提供するライブラリです。
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
インストール *l9-installation*
|
|
||||||
|
|
||||||
ZIPファイルをランタイムディレクトリに展開します。
|
|
||||||
|
|
||||||
以下のようにファイルが配置されるはずです。
|
|
||||||
>
|
|
||||||
<your runtime directory>/plugin/l9.vim
|
|
||||||
<your runtime directory>/doc/l9.txt
|
|
||||||
...
|
|
||||||
<
|
|
||||||
もしランタイムディレクトリが多数のプラグインでごちゃごちゃになるのが嫌なら、各
|
|
||||||
プラグインを個別のディレクトリに配置し、そのディレクトリのパスを 'runtimepath'
|
|
||||||
に追加してください。アンインストールも楽になります。
|
|
||||||
|
|
||||||
その後、ヘルプを有効にするためにタグファイルを更新してください。詳しくは
|
|
||||||
|add-local-help|を参照してください。
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
使い方 *l9-usage*
|
|
||||||
|
|
||||||
ソースコードを参照してください。
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
あばうと *l9-about* *l9-contact* *l9-author*
|
|
||||||
|
|
||||||
作者: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
|
|
||||||
ライセンス: MIT Licence
|
|
||||||
URL: http://www.vim.org/scripts/script.php?script_id=3252
|
|
||||||
http://bitbucket.org/ns9tks/vim-l9/
|
|
||||||
|
|
||||||
バグや要望など ~
|
|
||||||
|
|
||||||
こちらへどうぞ: http://bitbucket.org/ns9tks/vim-l9/issues/
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
vim:tw=78:ts=8:ft=help:norl:
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
*l9.txt* Vim-script library
|
|
||||||
|
|
||||||
Copyright (c) 2009-2010 Takeshi NISHIDA
|
|
||||||
|
|
||||||
l9 *l9*
|
|
||||||
|
|
||||||
INTRODUCTION |l9-introduction|
|
|
||||||
INSTALLATION |l9-installation|
|
|
||||||
USAGE |l9-usage|
|
|
||||||
CHANGELOG |l9-changelog|
|
|
||||||
ABOUT |l9-about|
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
INTRODUCTION *l9-introduction*
|
|
||||||
|
|
||||||
l9 is a Vim-script library, which provides some utility functions and commands
|
|
||||||
for programming in Vim.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
INSTALLATION *l9-installation*
|
|
||||||
|
|
||||||
Put all files into your runtime directory. If you have the zip file, extract
|
|
||||||
it to your runtime directory.
|
|
||||||
|
|
||||||
You should place the files as follows:
|
|
||||||
>
|
|
||||||
<your runtime directory>/plugin/l9.vim
|
|
||||||
<your runtime directory>/doc/l9.txt
|
|
||||||
...
|
|
||||||
<
|
|
||||||
If you are disgusted to make your runtime directory confused with a lot of
|
|
||||||
plugins, put each of the plugins into a directory individually and just add
|
|
||||||
the directory path to 'runtimepath'. It's easy to uninstall the plugin.
|
|
||||||
|
|
||||||
Then update your help tags files to enable fuzzyfinder help. See
|
|
||||||
|add-local-help| for details.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
USAGE *l9-usage*
|
|
||||||
|
|
||||||
See source code.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
CHANGELOG *l9-changelog*
|
|
||||||
|
|
||||||
1.1:
|
|
||||||
- Added l9#zip()
|
|
||||||
- Added l9#tempvariables#getList()
|
|
||||||
- Changed l9#guardScriptLoading()
|
|
||||||
- Removed l9#tempvariables#swap()
|
|
||||||
|
|
||||||
1.0.1:
|
|
||||||
- Fixed a bug that floating point numbers weren't evaluated correctly and
|
|
||||||
caused errors on some non-English locales.
|
|
||||||
|
|
||||||
1.0:
|
|
||||||
- First release.
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
ABOUT *l9-about* *l9-contact* *l9-author*
|
|
||||||
|
|
||||||
Author: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
|
|
||||||
Licence: MIT Licence
|
|
||||||
URL: http://www.vim.org/scripts/script.php?script_id=3252
|
|
||||||
http://bitbucket.org/ns9tks/vim-l9/
|
|
||||||
|
|
||||||
Bugs/Issues/Suggestions/Improvements ~
|
|
||||||
|
|
||||||
Please submit to http://bitbucket.org/ns9tks/vim-l9/issues/ .
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
vim:tw=78:ts=8:ft=help:norl:
|
|
||||||
|
|
@ -1,406 +0,0 @@
|
||||||
*matchit.txt* Extended "%" matching
|
|
||||||
|
|
||||||
For instructions on installing this file, type
|
|
||||||
:help matchit-install
|
|
||||||
inside Vim.
|
|
||||||
|
|
||||||
For Vim version 6.3. Last change: 2007 Aug 29
|
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Benji Fisher
|
|
||||||
|
|
||||||
*matchit* *matchit.vim*
|
|
||||||
|
|
||||||
1. Extended matching with "%" |matchit-intro|
|
|
||||||
2. Activation |matchit-activate|
|
|
||||||
3. Configuration |matchit-configure|
|
|
||||||
4. Supporting a New Language |matchit-newlang|
|
|
||||||
5. Known Bugs and Limitations |matchit-bugs|
|
|
||||||
|
|
||||||
The functionality mentioned here is a plugin, see |add-plugin|.
|
|
||||||
This plugin is only available if 'compatible' is not set.
|
|
||||||
You can avoid loading this plugin by setting the "loaded_matchit" variable
|
|
||||||
in your |vimrc| file: >
|
|
||||||
:let loaded_matchit = 1
|
|
||||||
|
|
||||||
{Vi does not have any of this}
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
1. Extended matching with "%" *matchit-intro*
|
|
||||||
|
|
||||||
*matchit-%*
|
|
||||||
% Cycle forward through matching groups, such as "if", "else", "endif",
|
|
||||||
as specified by |b:match_words|.
|
|
||||||
|
|
||||||
*g%* *v_g%* *o_g%*
|
|
||||||
g% Cycle backwards through matching groups, as specified by
|
|
||||||
|b:match_words|. For example, go from "if" to "endif" to "else".
|
|
||||||
|
|
||||||
*[%* *v_[%* *o_[%*
|
|
||||||
[% Go to [count] previous unmatched group, as specified by
|
|
||||||
|b:match_words|. Similar to |[{|.
|
|
||||||
|
|
||||||
*]%* *v_]%* *o_]%*
|
|
||||||
]% Go to [count] next unmatched group, as specified by
|
|
||||||
|b:match_words|. Similar to |]}|.
|
|
||||||
|
|
||||||
*v_a%*
|
|
||||||
a% In Visual mode, select the matching group, as specified by
|
|
||||||
|b:match_words|, containing the cursor. Similar to |v_a[|.
|
|
||||||
A [count] is ignored, and only the first character of the closing
|
|
||||||
pattern is selected.
|
|
||||||
|
|
||||||
In Vim, as in plain vi, the percent key, |%|, jumps the cursor from a brace,
|
|
||||||
bracket, or paren to its match. This can be configured with the 'matchpairs'
|
|
||||||
option. The matchit plugin extends this in several ways:
|
|
||||||
|
|
||||||
You can match whole words, such as "if" and "endif", not just
|
|
||||||
single characters. You can also specify a |regular-expression|.
|
|
||||||
You can define groups with more than two words, such as "if",
|
|
||||||
"else", "endif". Banging on the "%" key will cycle from the "if" to
|
|
||||||
the first "else", the next "else", ..., the closing "endif", and back
|
|
||||||
to the opening "if". Nested structures are skipped. Using |g%| goes
|
|
||||||
in the reverse direction.
|
|
||||||
By default, words inside comments and strings are ignored, unless
|
|
||||||
the cursor is inside a comment or string when you type "%". If the
|
|
||||||
only thing you want to do is modify the behavior of "%" so that it
|
|
||||||
behaves this way, you do not have to define |b:match_words|, since the
|
|
||||||
script uses the 'matchpairs' option as well as this variable.
|
|
||||||
|
|
||||||
See |matchit-details| for details on what the script does, and |b:match_words|
|
|
||||||
for how to specify matching patterns.
|
|
||||||
|
|
||||||
MODES: *matchit-modes* *matchit-v_%* *matchit-o_%*
|
|
||||||
|
|
||||||
Mostly, % and related motions (|g%| and |[%| and |]%|) work just like built-in
|
|
||||||
|motion| commands in |Operator-pending| and |Visual| modes. However, you
|
|
||||||
cannot make these motions |linewise| or |characterwise|, since the |:omap|s
|
|
||||||
that define them start with "v" in order to make the default behavior
|
|
||||||
inclusive. (See |o_v|.) In other words, "dV%" will not work. The
|
|
||||||
work-around is to go through Visual mode: "V%d" will work.
|
|
||||||
|
|
||||||
LANGUAGES: *matchit-languages*
|
|
||||||
|
|
||||||
Currently, the following languages are supported: Ada, ASP with VBS, Csh,
|
|
||||||
DTD, Entity, Essbase, Fortran, HTML, JSP (same as HTML), LaTeX, Lua, Pascal,
|
|
||||||
SGML, Shell, Tcsh, Vim, XML. Other languages may already have support via
|
|
||||||
the default |filetype-plugin|s in the standard vim distribution.
|
|
||||||
|
|
||||||
To support a new language, see |matchit-newlang| below.
|
|
||||||
|
|
||||||
DETAILS: *matchit-details* *matchit-parse*
|
|
||||||
|
|
||||||
Here is an outline of what matchit.vim does each time you hit the "%" key. If
|
|
||||||
there are |backref|s in |b:match_words| then the first step is to produce a
|
|
||||||
version in which these back references have been eliminated; if there are no
|
|
||||||
|backref|s then this step is skipped. This step is called parsing. For
|
|
||||||
example, "\(foo\|bar\):end\1" is parsed to yield
|
|
||||||
"\(foo\|bar\):end\(foo\|bar\)". This can get tricky, especially if there are
|
|
||||||
nested groups. If debugging is turned on, the parsed version is saved as
|
|
||||||
|b:match_pat|.
|
|
||||||
|
|
||||||
*matchit-choose*
|
|
||||||
Next, the script looks for a word on the current line that matches the pattern
|
|
||||||
just constructed. It includes the patterns from the 'matchpairs' option.
|
|
||||||
The goal is to do what you expect, which turns out to be a little complicated.
|
|
||||||
The script follows these rules:
|
|
||||||
|
|
||||||
Insist on a match that ends on or after the cursor.
|
|
||||||
Prefer a match that includes the cursor position (that is, one that
|
|
||||||
starts on or before the cursor).
|
|
||||||
Prefer a match that starts as close to the cursor as possible.
|
|
||||||
If more than one pattern in |b:match_words| matches, choose the one
|
|
||||||
that is listed first.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
Suppose you >
|
|
||||||
:let b:match_words = '<:>,<tag>:</tag>'
|
|
||||||
< and hit "%" with the cursor on or before the "<" in "a <tag> is born".
|
|
||||||
The pattern '<' comes first, so it is preferred over '<tag>', which
|
|
||||||
also matches. If the cursor is on the "t", however, then '<tag>' is
|
|
||||||
preferred, because this matches a bit of text containing the cursor.
|
|
||||||
If the two groups of patterns were reversed then '<' would never be
|
|
||||||
preferred.
|
|
||||||
|
|
||||||
Suppose you >
|
|
||||||
:let b:match_words = 'if:end if'
|
|
||||||
< (Note the space!) and hit "%" with the cursor at the end of "end if".
|
|
||||||
Then "if" matches, which is probably not what you want, but if the
|
|
||||||
cursor starts on the "end " then "end if" is chosen. (You can avoid
|
|
||||||
this problem by using a more complicated pattern.)
|
|
||||||
|
|
||||||
If there is no match, the cursor does not move. (Before version 1.13 of the
|
|
||||||
script, it would fall back on the usual behavior of |%|). If debugging is
|
|
||||||
turned on, the matched bit of text is saved as |b:match_match| and the cursor
|
|
||||||
column of the start of the match is saved as |b:match_col|.
|
|
||||||
|
|
||||||
Next, the script looks through |b:match_words| (original and parsed versions)
|
|
||||||
for the group and pattern that match. If debugging is turned on, the group is
|
|
||||||
saved as |b:match_ini| (the first pattern) and |b:match_tail| (the rest). If
|
|
||||||
there are |backref|s then, in addition, the matching pattern is saved as
|
|
||||||
|b:match_word| and a table of translations is saved as |b:match_table|. If
|
|
||||||
there are |backref|s, these are determined from the matching pattern and
|
|
||||||
|b:match_match| and substituted into each pattern in the matching group.
|
|
||||||
|
|
||||||
The script decides whether to search forwards or backwards and chooses
|
|
||||||
arguments for the |searchpair()| function. Then, the cursor is moved to the
|
|
||||||
start of the match, and |searchpair()| is called. By default, matching
|
|
||||||
structures inside strings and comments are ignored. This can be changed by
|
|
||||||
setting |b:match_skip|.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
2. Activation *matchit-activate*
|
|
||||||
|
|
||||||
You can use this script as a plugin, by copying it to your plugin directory.
|
|
||||||
See |add-global-plugin| for instructions. You can also add a line to your
|
|
||||||
|vimrc| file, such as >
|
|
||||||
:source $VIMRUNTIME/macros/matchit.vim
|
|
||||||
or >
|
|
||||||
:runtime macros/matchit.vim
|
|
||||||
Either way, the script should start working the next time you start up Vim.
|
|
||||||
|
|
||||||
(Earlier versions of the script did nothing unless a |buffer-variable| named
|
|
||||||
|b:match_words| was defined. Even earlier versions contained autocommands
|
|
||||||
that set this variable for various file types. Now, |b:match_words| is
|
|
||||||
defined in many of the default |filetype-plugin|s instead.)
|
|
||||||
|
|
||||||
For a new language, you can add autocommands to the script or to your vimrc
|
|
||||||
file, but the recommended method is to add a line such as >
|
|
||||||
let b:match_words = '\<foo\>:\<bar\>'
|
|
||||||
to the |filetype-plugin| for your language. See |b:match_words| below for how
|
|
||||||
this variable is interpreted.
|
|
||||||
|
|
||||||
TROUBLESHOOTING *matchit-troubleshoot*
|
|
||||||
|
|
||||||
The script should work in most installations of Vim. It may not work if Vim
|
|
||||||
was compiled with a minimal feature set, for example if the |+syntax| option
|
|
||||||
was not enabled. If your Vim has support for syntax compiled in, but you do
|
|
||||||
not have |syntax| highlighting turned on, matchit.vim should work, but it may
|
|
||||||
fail to skip matching groups in comments and strings. If the |filetype|
|
|
||||||
mechanism is turned off, the |b:match_words| variable will probably not be
|
|
||||||
defined automatically.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
3. Configuration *matchit-configure*
|
|
||||||
|
|
||||||
There are several variables that govern the behavior of matchit.vim. Note
|
|
||||||
that these are variables local to the buffer, not options, so use |:let| to
|
|
||||||
define them, not |:set|. Some of these variables have values that matter; for
|
|
||||||
others, it only matters whether the variable has been defined. All of these
|
|
||||||
can be defined in the |filetype-plugin| or autocommand that defines
|
|
||||||
|b:match_words| or "on the fly."
|
|
||||||
|
|
||||||
The main variable is |b:match_words|. It is described in the section below on
|
|
||||||
supporting a new language.
|
|
||||||
|
|
||||||
*MatchError* *matchit-hl* *matchit-highlight*
|
|
||||||
MatchError is the highlight group for error messages from the script. By
|
|
||||||
default, it is linked to WarningMsg. If you do not want to be bothered by
|
|
||||||
error messages, you can define this to be something invisible. For example,
|
|
||||||
if you use the GUI version of Vim and your command line is normally white, you
|
|
||||||
can do >
|
|
||||||
:hi MatchError guifg=white guibg=white
|
|
||||||
<
|
|
||||||
*b:match_ignorecase*
|
|
||||||
If you >
|
|
||||||
:let b:match_ignorecase = 1
|
|
||||||
then matchit.vim acts as if 'ignorecase' is set: for example, "end" and "END"
|
|
||||||
are equivalent. If you >
|
|
||||||
:let b:match_ignorecase = 0
|
|
||||||
then matchit.vim treats "end" and "END" differently. (There will be no
|
|
||||||
b:match_infercase option unless someone requests it.)
|
|
||||||
|
|
||||||
*b:match_debug*
|
|
||||||
Define b:match_debug if you want debugging information to be saved. See
|
|
||||||
|matchit-debug|, below.
|
|
||||||
|
|
||||||
*b:match_skip*
|
|
||||||
If b:match_skip is defined, it is passed as the skip argument to
|
|
||||||
|searchpair()|. This controls when matching structures are skipped, or
|
|
||||||
ignored. By default, they are ignored inside comments and strings, as
|
|
||||||
determined by the |syntax| mechanism. (If syntax highlighting is turned off,
|
|
||||||
nothing is skipped.) You can set b:match_skip to a string, which evaluates to
|
|
||||||
a non-zero, numerical value if the match is to be skipped or zero if the match
|
|
||||||
should not be skipped. In addition, the following special values are
|
|
||||||
supported by matchit.vim:
|
|
||||||
s:foo becomes (current syntax item) =~ foo
|
|
||||||
S:foo becomes (current syntax item) !~ foo
|
|
||||||
r:foo becomes (line before cursor) =~ foo
|
|
||||||
R:foo becomes (line before cursor) !~ foo
|
|
||||||
(The "s" is meant to suggest "syntax", and the "r" is meant to suggest
|
|
||||||
"regular expression".)
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
|
|
||||||
You can get the default behavior with >
|
|
||||||
:let b:match_skip = 's:comment\|string'
|
|
||||||
<
|
|
||||||
If you want to skip matching structures unless they are at the start
|
|
||||||
of the line (ignoring whitespace) then you can >
|
|
||||||
:let b:match_skip = 'R:^\s*'
|
|
||||||
< Do not do this if strings or comments can span several lines, since
|
|
||||||
the normal syntax checking will not be done if you set b:match_skip.
|
|
||||||
|
|
||||||
In LaTeX, since "%" is used as the comment character, you can >
|
|
||||||
:let b:match_skip = 'r:%'
|
|
||||||
< Unfortunately, this will skip anything after "\%", an escaped "%". To
|
|
||||||
allow for this, and also "\\%" (an excaped backslash followed by the
|
|
||||||
comment character) you can >
|
|
||||||
:let b:match_skip = 'r:\(^\|[^\\]\)\(\\\\\)*%'
|
|
||||||
<
|
|
||||||
See the $VIMRUNTIME/ftplugin/vim.vim for an example that uses both
|
|
||||||
syntax and a regular expression.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
4. Supporting a New Language *matchit-newlang*
|
|
||||||
*b:match_words*
|
|
||||||
In order for matchit.vim to support a new language, you must define a suitable
|
|
||||||
pattern for |b:match_words|. You may also want to set some of the
|
|
||||||
|matchit-configure| variables, as described above. If your language has a
|
|
||||||
complicated syntax, or many keywords, you will need to know something about
|
|
||||||
Vim's |regular-expression|s.
|
|
||||||
|
|
||||||
The format for |b:match_words| is similar to that of the 'matchpairs' option:
|
|
||||||
it is a comma (,)-separated list of groups; each group is a colon(:)-separated
|
|
||||||
list of patterns (regular expressions). Commas and backslashes that are part
|
|
||||||
of a pattern should be escaped with backslashes ('\:' and '\,'). It is OK to
|
|
||||||
have only one group; the effect is undefined if a group has only one pattern.
|
|
||||||
A simple example is >
|
|
||||||
:let b:match_words = '\<if\>:\<endif\>,'
|
|
||||||
\ . '\<while\>:\<continue\>:\<break\>:\<endwhile\>'
|
|
||||||
(In Vim regular expressions, |\<| and |\>| denote word boundaries. Thus "if"
|
|
||||||
matches the end of "endif" but "\<if\>" does not.) Then banging on the "%"
|
|
||||||
key will bounce the cursor between "if" and the matching "endif"; and from
|
|
||||||
"while" to any matching "continue" or "break", then to the matching "endwhile"
|
|
||||||
and back to the "while". It is almost always easier to use |literal-string|s
|
|
||||||
(single quotes) as above: '\<if\>' rather than "\\<if\\>" and so on.
|
|
||||||
|
|
||||||
Exception: If the ":" character does not appear in b:match_words, then it is
|
|
||||||
treated as an expression to be evaluated. For example, >
|
|
||||||
:let b:match_words = 'GetMatchWords()'
|
|
||||||
allows you to define a function. This can return a different string depending
|
|
||||||
on the current syntax, for example.
|
|
||||||
|
|
||||||
Once you have defined the appropriate value of |b:match_words|, you will
|
|
||||||
probably want to have this set automatically each time you edit the
|
|
||||||
appropriate file type. The recommended way to do this is by adding the
|
|
||||||
definition to a |filetype-plugin| file.
|
|
||||||
|
|
||||||
Tips: Be careful that your initial pattern does not match your final pattern.
|
|
||||||
See the example above for the use of word-boundary expressions. It is usually
|
|
||||||
better to use ".\{-}" (as many as necessary) instead of ".*" (as many as
|
|
||||||
possible). See |\{-|. For example, in the string "<tag>label</tag>", "<.*>"
|
|
||||||
matches the whole string whereas "<.\{-}>" and "<[^>]*>" match "<tag>" and
|
|
||||||
"</tag>".
|
|
||||||
|
|
||||||
*matchit-spaces* *matchit-s:notend*
|
|
||||||
If "if" is to be paired with "end if" (Note the space!) then word boundaries
|
|
||||||
are not enough. Instead, define a regular expression s:notend that will match
|
|
||||||
anything but "end" and use it as follows: >
|
|
||||||
:let s:notend = '\%(\<end\s\+\)\@<!'
|
|
||||||
:let b:match_words = s:notend . '\<if\>:\<end\s\+if\>'
|
|
||||||
< *matchit-s:sol*
|
|
||||||
This is a simplified version of what is done for Ada. The s:notend is a
|
|
||||||
|script-variable|. Similarly, you may want to define a start-of-line regular
|
|
||||||
expression >
|
|
||||||
:let s:sol = '\%(^\|;\)\s*'
|
|
||||||
if keywords are only recognized after the start of a line or after a
|
|
||||||
semicolon (;), with optional white space.
|
|
||||||
|
|
||||||
*matchit-backref* *matchit-\1*
|
|
||||||
In any group, the expressions |\1|, |\2|, ..., |\9| refer to parts of the
|
|
||||||
INITIAL pattern enclosed in |\(|escaped parentheses|\)|. These are referred
|
|
||||||
to as back references, or backrefs. For example, >
|
|
||||||
:let b:match_words = '\<b\(o\+\)\>:\(h\)\1\>'
|
|
||||||
means that "bo" pairs with "ho" and "boo" pairs with "hoo" and so on. Note
|
|
||||||
that "\1" does not refer to the "\(h\)" in this example. If you have
|
|
||||||
"\(nested \(parentheses\)\) then "\d" refers to the d-th "\(" and everything
|
|
||||||
up to and including the matching "\)": in "\(nested\(parentheses\)\)", "\1"
|
|
||||||
refers to everything and "\2" refers to "\(parentheses\)". If you use a
|
|
||||||
variable such as |s:notend| or |s:sol| in the previous paragraph then remember
|
|
||||||
to count any "\(" patterns in this variable. You do not have to count groups
|
|
||||||
defined by |\%(\)|.
|
|
||||||
|
|
||||||
It should be possible to resolve back references from any pattern in the
|
|
||||||
group. For example, >
|
|
||||||
:let b:match_words = '\(foo\)\(bar\):more\1:and\2:end\1\2'
|
|
||||||
would not work because "\2" cannot be determined from "morefoo" and "\1"
|
|
||||||
cannot be determined from "andbar". On the other hand, >
|
|
||||||
:let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
|
|
||||||
should work (and have the same effect as "foobar:barfoo:endfoobar"), although
|
|
||||||
this has not been thoroughly tested.
|
|
||||||
|
|
||||||
You can use |zero-width| patterns such as |\@<=| and |\zs|. (The latter has
|
|
||||||
not been thouroughly tested in matchit.vim.) For example, if the keyword "if"
|
|
||||||
must occur at the start of the line, with optional white space, you might use
|
|
||||||
the pattern "\(^\s*\)\@<=if" so that the cursor will end on the "i" instead of
|
|
||||||
at the start of the line. For another example, if HTML had only one tag then
|
|
||||||
one could >
|
|
||||||
:let b:match_words = '<:>,<\@<=tag>:<\@<=/tag>'
|
|
||||||
so that "%" can bounce between matching "<" and ">" pairs or (starting on
|
|
||||||
"tag" or "/tag") between matching tags. Without the |\@<=|, the script would
|
|
||||||
bounce from "tag" to the "<" in "</tag>", and another "%" would not take you
|
|
||||||
back to where you started.
|
|
||||||
|
|
||||||
DEBUGGING *matchit-debug* *:MatchDebug*
|
|
||||||
|
|
||||||
If you are having trouble figuring out the appropriate definition of
|
|
||||||
|b:match_words| then you can take advantage of the same information I use when
|
|
||||||
debugging the script. This is especially true if you are not sure whether
|
|
||||||
your patterns or my script are at fault! To make this more convenient, I have
|
|
||||||
made the command :MatchDebug, which defines the variable |b:match_debug| and
|
|
||||||
creates a Matchit menu. This menu makes it convenient to check the values of
|
|
||||||
the variables described below. You will probably also want to read
|
|
||||||
|matchit-details| above.
|
|
||||||
|
|
||||||
Defining the variable |b:match_debug| causes the script to set the following
|
|
||||||
variables, each time you hit the "%" key. Several of these are only defined
|
|
||||||
if |b:match_words| includes |backref|s.
|
|
||||||
|
|
||||||
*b:match_pat*
|
|
||||||
The b:match_pat variable is set to |b:match_words| with |backref|s parsed.
|
|
||||||
*b:match_match*
|
|
||||||
The b:match_match variable is set to the bit of text that is recognized as a
|
|
||||||
match.
|
|
||||||
*b:match_col*
|
|
||||||
The b:match_col variable is set to the cursor column of the start of the
|
|
||||||
matching text.
|
|
||||||
*b:match_wholeBR*
|
|
||||||
The b:match_wholeBR variable is set to the comma-separated group of patterns
|
|
||||||
that matches, with |backref|s unparsed.
|
|
||||||
*b:match_iniBR*
|
|
||||||
The b:match_iniBR variable is set to the first pattern in |b:match_wholeBR|.
|
|
||||||
*b:match_ini*
|
|
||||||
The b:match_ini variable is set to the first pattern in |b:match_wholeBR|,
|
|
||||||
with |backref|s resolved from |b:match_match|.
|
|
||||||
*b:match_tail*
|
|
||||||
The b:match_tail variable is set to the remaining patterns in
|
|
||||||
|b:match_wholeBR|, with |backref|s resolved from |b:match_match|.
|
|
||||||
*b:match_word*
|
|
||||||
The b:match_word variable is set to the pattern from |b:match_wholeBR| that
|
|
||||||
matches |b:match_match|.
|
|
||||||
*b:match_table*
|
|
||||||
The back reference '\'.d refers to the same thing as '\'.b:match_table[d] in
|
|
||||||
|b:match_word|.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
5. Known Bugs and Limitations *matchit-bugs*
|
|
||||||
|
|
||||||
Just because I know about a bug does not mean that it is on my todo list. I
|
|
||||||
try to respond to reports of bugs that cause real problems. If it does not
|
|
||||||
cause serious problems, or if there is a work-around, a bug may sit there for
|
|
||||||
a while. Moral: if a bug (known or not) bothers you, let me know.
|
|
||||||
|
|
||||||
The various |:vmap|s defined in the script (%, |g%|, |[%|, |]%|, |a%|) may
|
|
||||||
have undesired effects in Select mode |Select-mode-mapping|. At least, if you
|
|
||||||
want to replace the selection with any character in "ag%[]" there will be a
|
|
||||||
pause of |'updatetime'| first.
|
|
||||||
|
|
||||||
It would be nice if "\0" were recognized as the entire pattern. That is, it
|
|
||||||
would be nice if "foo:\end\0" had the same effect as "\(foo\):\end\1". I may
|
|
||||||
try to implement this in a future version. (This is not so easy to arrange as
|
|
||||||
you might think!)
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
vim:tw=78:fo=tcq2:
|
|
||||||
|
|
@ -1,710 +0,0 @@
|
||||||
*project.txt* Plugin for managing multiple projects with multiple sources
|
|
||||||
For Vim version 6.x and Vim version 7.x.
|
|
||||||
Last Change: Fri 13 Oct 2006 10:20:13 AM EDT
|
|
||||||
|
|
||||||
|
|
||||||
By Aric Blumer
|
|
||||||
aricvim email-at-sign charter.net
|
|
||||||
|
|
||||||
*project* *project-plugin*
|
|
||||||
Contents:
|
|
||||||
|
|
||||||
Commands...................|project-invoking|
|
|
||||||
Inheritance.............|project-inheritance|
|
|
||||||
Mappings...................|project-mappings|
|
|
||||||
Adding Mappings.....|project-adding-mappings|
|
|
||||||
Settings...................|project-settings|
|
|
||||||
Example File................|project-example|
|
|
||||||
Tips...........................|project-tips|
|
|
||||||
|
|
||||||
|
|
||||||
You can use this plugin's basic functionality to set up a list of
|
|
||||||
frequently-accessed files for easy navigation. The list of files will be
|
|
||||||
displayed in a window on the left side of the Vim window, and you can press
|
|
||||||
<Return> or double-click on filenames in the list to open the files. I find
|
|
||||||
this easier to use than having to navigate a directory hierarchy with the
|
|
||||||
|file-explorer|.
|
|
||||||
|
|
||||||
You can also instruct the Plugin to change to a directory and to run Vim
|
|
||||||
scripts when you select a file. These scripts can, for example, modify the
|
|
||||||
environment to include compilers in $PATH. This makes it very easy to use
|
|
||||||
quickfix with multiple projects that use different environments.
|
|
||||||
|
|
||||||
Other features include:
|
|
||||||
o Loading/Unloading all the files in a Project (\l, \L, \w, and \W)
|
|
||||||
o Grepping all the files in a Project (\g and \G)
|
|
||||||
o Running a user-specified script on a file (can be used to launch an
|
|
||||||
external program on the file) (\1 through \9)
|
|
||||||
o Running a user-specified script on all the files in a Project
|
|
||||||
(\f1-\f9 and \F1-\F9)
|
|
||||||
o High degree of user-configurability
|
|
||||||
o Also works with |netrw| using the XXXX://... notation where XXXX is
|
|
||||||
ftp, rcp, scp, or http.
|
|
||||||
|
|
||||||
All of this is specified within a simple text file and a few global variables
|
|
||||||
in your vimrc file.
|
|
||||||
|
|
||||||
You must set 'nocompatible' in your |vimrc| file to use this plugin. You can
|
|
||||||
stop the plugin from being loaded by setting the "loaded_project" variable: >
|
|
||||||
:let loaded_project = 1
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
COMMANDS *project-invoking*
|
|
||||||
|
|
||||||
You can use the plugin by placing it in your plugin directory (e.g.,
|
|
||||||
~/.vim/plugin). See |add-global-plugin|. When you start vim the next time, you
|
|
||||||
then enter the command >
|
|
||||||
:Project
|
|
||||||
or >
|
|
||||||
:Project {file}
|
|
||||||
|
|
||||||
If you do not specify the filename, $HOME/.vimprojects is used.
|
|
||||||
|
|
||||||
To have Vim come up with the Project Window enabled automatically (say, from a
|
|
||||||
GUI launcher), run Vim like this: [g]vim +Project
|
|
||||||
|
|
||||||
Note that you can invoke :Project on only one file at a time. If you wish to
|
|
||||||
change the Project File, do a :bwipe in the Project Buffer, then re-invoke the
|
|
||||||
Plugin as described above.
|
|
||||||
|
|
||||||
Several Projects can be kept and displayed in the same file, each in a fold
|
|
||||||
delimited by { and } (see |fold.txt|). There can be any number of nested
|
|
||||||
folds to provide you with a Project hierarchy. Any line without a { or a } in
|
|
||||||
the file is considered to be a filename. Blank lines are ignored, and any
|
|
||||||
text after a # is ignored.
|
|
||||||
|
|
||||||
Because the plugin uses standard Vim folds, you can use any of the
|
|
||||||
|fold-commands|. You can double-click on the first line of a fold to open and
|
|
||||||
close it. You can select a file to open by putting the cursor on its name and
|
|
||||||
pressing <Return> or by double-clicking on it. The plugin will create a new
|
|
||||||
window to the right or use the |CTRL-W_p| equivalent if it exists.
|
|
||||||
|
|
||||||
*project-syntax*
|
|
||||||
Each Project Entry has this form:
|
|
||||||
|
|
||||||
project_entry ::=
|
|
||||||
<Description>={projpath} [{options}] {
|
|
||||||
[ filename ]
|
|
||||||
[ project_entry ]
|
|
||||||
}
|
|
||||||
|
|
||||||
{options} is one or more of the following (on the same line):
|
|
||||||
CD={path}
|
|
||||||
in={filename}
|
|
||||||
out={filename}
|
|
||||||
filter="{pat}"
|
|
||||||
flags={flag}
|
|
||||||
|
|
||||||
Note that a project_entry can reside within a project_entry. This allows you
|
|
||||||
to set up a hierarchy within your Project.
|
|
||||||
|
|
||||||
The <Description> will be displayed in the foldtext and cannot contain "=".
|
|
||||||
There can be no space character directly on either side of the =.
|
|
||||||
|
|
||||||
The {projpath} is the path in which the files listed in the Project's fold
|
|
||||||
will be found, and it may contain environment variables. If the path is a
|
|
||||||
relative path, then the plugin constructs the whole path from the Project's
|
|
||||||
parent, grandparent, etc., all the way up the hierarchy. An outermost
|
|
||||||
project_entry must have an absolute path. See the |project-inheritance|
|
|
||||||
example below. {projpath} may contain spaces, but they must be escaped like
|
|
||||||
normal Vim escapes. Here are two examples of the same directory:
|
|
||||||
>
|
|
||||||
Example=/my/directory/with\ spaces {
|
|
||||||
}
|
|
||||||
Example="/my/directory/with spaces" {
|
|
||||||
}
|
|
||||||
|
|
||||||
I recommend this for Windows®: >
|
|
||||||
|
|
||||||
Example="c:\My Documents" {
|
|
||||||
}
|
|
||||||
|
|
||||||
But Vim is smart enough to do this, too: >
|
|
||||||
|
|
||||||
Example=c:\My\ Documents {
|
|
||||||
}
|
|
||||||
|
|
||||||
CD= provides the directory that Vim will change to when you select a file in
|
|
||||||
that fold (using |:cd|). This allows you, for example, to enter |:make| to use
|
|
||||||
the local Makefile. A CD=. means that Vim will make {projpath} or its
|
|
||||||
inherited equivalent the current working directory. When CD is omitted, the
|
|
||||||
directory is not changed. There can be no space on either side of the =. The
|
|
||||||
value of CD can also be a relative path from a parent's CD. See the
|
|
||||||
|project-inheritance| example below. This directive is ignored for |netrw|
|
|
||||||
projects. Spaces are allowed in the path as for {projpath}.
|
|
||||||
|
|
||||||
in= and out= provide the means to run arbitrary Vim scripts whenever you enter
|
|
||||||
or leave a file's buffer (see the |BufEnter| and |BufLeave| autocommand
|
|
||||||
events). The idea is to have a Vim script that sets up or tears down the
|
|
||||||
environment for the Project like this:
|
|
||||||
|
|
||||||
in.vim: >
|
|
||||||
let $PROJECT_HOME='~/my_project'
|
|
||||||
" Put the compiler in $PATH
|
|
||||||
if $PATH !~ '/path/to/my/compiler'
|
|
||||||
let $PATH=$PATH.':/path/to/my/compiler'
|
|
||||||
endif
|
|
||||||
|
|
||||||
out.vim: >
|
|
||||||
" Remove compiler from $PATH
|
|
||||||
if $PATH =~ '/path/to/my/compiler'
|
|
||||||
let $PATH=substitute($PATH, ':/path/to/my/compiler', '', 'g')
|
|
||||||
endif
|
|
||||||
|
|
||||||
Then you can use :make with the proper environment depending on what file you
|
|
||||||
are currently editing. If the path to the script is relative, then it is
|
|
||||||
relative from {projpath}. These directives are inherited by Subprojects
|
|
||||||
unless the Subproject specifies its own. For use with |netrw| projects, the
|
|
||||||
paths specified for in= and out= must be absolute and local.
|
|
||||||
|
|
||||||
filter= specifies a |glob()| file pattern. It is used to regenerate the list
|
|
||||||
of files in a Project fold when using the \r (<LocalLeader>r) map in the
|
|
||||||
Project Window. The filter value must be in quotes because it can contain
|
|
||||||
multiple file patterns. If filter is omitted, then the * pattern is used.
|
|
||||||
There can be no space on either side of the =. A Subproject will inherit the
|
|
||||||
filter of its parent unless it specifies its own filter.
|
|
||||||
|
|
||||||
flags= provides the means to enable/disable features for a particular fold.
|
|
||||||
The general mnemonic scheme is for lower case to turn something off and upper
|
|
||||||
case to turn something on. {flag} can contain any of the following
|
|
||||||
characters:
|
|
||||||
|
|
||||||
flag Description ~
|
|
||||||
|
|
||||||
l Turn off recursion for this fold for \L. Subfolds are also
|
|
||||||
blocked from the recursion.
|
|
||||||
|
|
||||||
r Turn off refresh. When present, do not refresh this fold when
|
|
||||||
\r or \R is used. This does not affect subfold recursion.
|
|
||||||
|
|
||||||
S Turn on sorting for refresh and create.
|
|
||||||
|
|
||||||
s Turn off sorting for refresh and create.
|
|
||||||
|
|
||||||
T Turn on top gravity. Forces folds to the top of the current
|
|
||||||
fold when refreshing. It has the same affect as the 'T' flag
|
|
||||||
in g:proj_flags, but controls the feature on a per-fold basis.
|
|
||||||
|
|
||||||
t Turn off top gravity. Forces folds to the bottom of the
|
|
||||||
current fold when refreshing.
|
|
||||||
|
|
||||||
w Turn off recursion for this fold for \W. Subfolds are also
|
|
||||||
blocked from the recursion.
|
|
||||||
|
|
||||||
|
|
||||||
Flags are not inherited by Subprojects.
|
|
||||||
|
|
||||||
Any text outside a fold is ignored.
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
INHERITANCE *project-inheritance*
|
|
||||||
|
|
||||||
It's best to show inheritance by comparing these two Project Files:
|
|
||||||
>
|
|
||||||
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
|
|
||||||
Child1=c_code {
|
|
||||||
}
|
|
||||||
Child2=include CD=. filter="*.h" {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Child1's path is "~/my_project/c_code" because ~/my_project is inherited. It
|
|
||||||
also inherits the CD from Parent. Since Parent has CD=., the Parent's cwd is
|
|
||||||
"~/my_project". Child1 therefore inherits a CD of "~/my_project". Finally,
|
|
||||||
Child1 inherits the filter from Parent. The flags are not inherited.
|
|
||||||
|
|
||||||
Child2 only inherits the "~/my_project" from Parent.
|
|
||||||
|
|
||||||
Thus, the example above is exactly equivalent to this:
|
|
||||||
>
|
|
||||||
Parent=~/my_project CD=. filter="Make* *.mk" flags=r {
|
|
||||||
Child1=~/my_project/c_code CD=~/my_project filter="Make* *.mk" {
|
|
||||||
}
|
|
||||||
Child2=~/my_project/include CD=~/my_project/include filter="*.h" {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(For a real Project, Child1 would not want to inherit its parent's filter, but
|
|
||||||
this example shows the concept.) You can always enter \i to display what the
|
|
||||||
cursor's project inherits.
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
MAPPINGS *project-mappings*
|
|
||||||
|
|
||||||
Map Action ~
|
|
||||||
|
|
||||||
\r Refreshes the Project fold that the cursor is in by placing in the
|
|
||||||
fold all the files that match the filter. The Project is refreshed
|
|
||||||
using an indent of one space for every foldlevel in the hierarchy.
|
|
||||||
|
|
||||||
You may place a "# pragma keep" (without the quotes) at the end of a
|
|
||||||
line, and the file entry on that line will not be removed when you
|
|
||||||
refresh. This is useful, for example, when you have . as an entry so
|
|
||||||
you can easily browse the directory.
|
|
||||||
|
|
||||||
Note that this mapping is actually <LocalLeader>r, and the default of
|
|
||||||
|<LocalLeader>| is \.
|
|
||||||
|
|
||||||
This does not work for Projects using |netrw|.
|
|
||||||
|
|
||||||
\R Executes \r recursively in the current fold and all folds below.
|
|
||||||
This does not work for Projects using |netrw|.
|
|
||||||
|
|
||||||
\c Creates a Project fold entry. It asks for the description, the path
|
|
||||||
to the files, the CD parameter, and the filename |glob()| pattern.
|
|
||||||
From this information, it will create the Project Entry below the
|
|
||||||
cursor.
|
|
||||||
|
|
||||||
This does not work for Projects using |netrw|.
|
|
||||||
|
|
||||||
\C Creates a Project fold entry like \c, but recursively includes all the
|
|
||||||
subdirectories.
|
|
||||||
|
|
||||||
<Return>
|
|
||||||
Select a file to open in the |CTRL-W_p| window or in a new window. If
|
|
||||||
the cursor is on a fold, open or close it.
|
|
||||||
|
|
||||||
<S-Return>
|
|
||||||
\s
|
|
||||||
Same as <Return> but horizontally split the target window.
|
|
||||||
<LocalLeader>s is provided for those terminals that don't recognize
|
|
||||||
<S-Return>.
|
|
||||||
|
|
||||||
\S
|
|
||||||
Load all files in a project by doing horizontal splits.
|
|
||||||
|
|
||||||
<C-Return>
|
|
||||||
\o
|
|
||||||
Same as <Return> but ensure that the opened file is the only other
|
|
||||||
window. <LocalLeader>o is provided for those terminals that don't
|
|
||||||
recognize <C-Return>.
|
|
||||||
|
|
||||||
<M-Return>
|
|
||||||
\v
|
|
||||||
Same as <Return> but only display the file--the cursor stays in the
|
|
||||||
Project Window.
|
|
||||||
|
|
||||||
<2-LeftMouse>
|
|
||||||
(Double-click) If on a closed fold, open it. If on an open fold
|
|
||||||
boundary, close it. If on a filename, open the file in the |CTRL-W_p|
|
|
||||||
window or in a new window.
|
|
||||||
|
|
||||||
<S-2-LeftMouse>
|
|
||||||
Same as <S-Return>.
|
|
||||||
|
|
||||||
<C-2-LeftMouse>
|
|
||||||
Same as <C-Return>.
|
|
||||||
|
|
||||||
<RightMouse>
|
|
||||||
Increase the width of the Project Window by g:proj_window_increment or
|
|
||||||
toggle between a width of
|
|
||||||
g:proj_window_width + g:proj_window_increment
|
|
||||||
and
|
|
||||||
g:proj_window_width.
|
|
||||||
|
|
||||||
Whether you toggle or monotonically increase the width is determined
|
|
||||||
by the 't' flag of the g:proj_flags variable (see |project-flags|).
|
|
||||||
|
|
||||||
Note that a Right Mouse click will not automatically place the cursor
|
|
||||||
in the Project Window if it is in a different window. The window will
|
|
||||||
go back to the g:proj_window_width width when you leave the window.
|
|
||||||
|
|
||||||
<space> Same as <RightMouse>
|
|
||||||
|
|
||||||
<CTRL-Up>
|
|
||||||
\<Up>
|
|
||||||
Move the text or fold under the cursor up one row. This may not work
|
|
||||||
in a terminal because the terminal is unaware of this key combination.
|
|
||||||
<LocalLeader><Up> is provided for those terminals that don't recognize
|
|
||||||
<C-Up>.
|
|
||||||
|
|
||||||
|
|
||||||
<CTRL-Down>
|
|
||||||
\<Down>
|
|
||||||
Move the text or fold under the cursor down one row. This may not work
|
|
||||||
in a terminal because the terminal is unaware of this key combination.
|
|
||||||
<LocalLeader><Down> is provided for those terminals that don't
|
|
||||||
recognize <C-Down>.
|
|
||||||
|
|
||||||
\i Show in the status line the completely resolved and inherited
|
|
||||||
parameters for the fold the cursor is in. This is intended for
|
|
||||||
debugging your relative path and inherited parameters for manually
|
|
||||||
entered Projects.
|
|
||||||
|
|
||||||
\I Show in the status line the completely resolved filename. Uses the
|
|
||||||
Project_GetFname(line('.')) function.
|
|
||||||
|
|
||||||
\1 - \9
|
|
||||||
Run the command specified in g:proj_run{x} where {x} is the number
|
|
||||||
of the key. See the documentation of g:proj_run1 below.
|
|
||||||
|
|
||||||
\f1-\f9
|
|
||||||
Run the command specified in g:proj_run_fold{x} where {x} is the
|
|
||||||
number of the key. The command is run on the files at the current
|
|
||||||
Project level. See the |project-settings| below.
|
|
||||||
|
|
||||||
\F1-\F9
|
|
||||||
Run the command specified in g:proj_run_fold{x} where {x} is the
|
|
||||||
number of the key. The command is run on the files at the current
|
|
||||||
Project level and all Subprojects. See the |project-settings| below.
|
|
||||||
|
|
||||||
\0 Display the commands that are defined for \1 through \9.
|
|
||||||
|
|
||||||
\f0 Display the commands that are defined for \f1 through \f9 and \F1
|
|
||||||
through \F0. Same as \F0.
|
|
||||||
|
|
||||||
\l Load all the files in the current Project level into Vim. While files
|
|
||||||
are being loaded, you may press any key to stop.
|
|
||||||
|
|
||||||
\L Load all the files in the current Project and all Subprojects into
|
|
||||||
Vim. Use this mapping with caution--I wouldn't suggest using \L to
|
|
||||||
load a Project with thousands of files. (BTW, my Project file has more
|
|
||||||
than 5,300 files in it!) While files are being loaded, you may press
|
|
||||||
any key to stop.
|
|
||||||
|
|
||||||
\w Wipe all the files in the current Project level from Vim. (If files
|
|
||||||
are modified, they will be saved first.) While files are being wiped,
|
|
||||||
you may press any key to stop.
|
|
||||||
|
|
||||||
\W Wipe all the files in the current Project and all Subprojects from
|
|
||||||
Vim. (If files are modified, they will be saved first.) While files
|
|
||||||
are being wiped, you may press any key to stop.
|
|
||||||
|
|
||||||
\g Grep all the files in the current Project level.
|
|
||||||
|
|
||||||
\G Grep all the files in the current Project level and all Subprojects.
|
|
||||||
|
|
||||||
\e Set up the Environment for the Project File as though you had selected
|
|
||||||
it with <Return>. This allows you to do a \e and a :make without
|
|
||||||
having to open any files in the project.
|
|
||||||
|
|
||||||
\E Explore (using |file-explorer|) the directory of the project the
|
|
||||||
cursor is in. Does not work with netrw.
|
|
||||||
|
|
||||||
<F12> When the 'g' flag is present in g:proj_flags (see |project-flags|)
|
|
||||||
this key toggles the Project Window open and closed. You may remap
|
|
||||||
this toggle function by putting the following in your vimrc and
|
|
||||||
replacing <Leader>P with whatever key combination you wish:
|
|
||||||
|
|
||||||
nmap <silent> <Leader>P <Plug>ToggleProject
|
|
||||||
|
|
||||||
Note that the Project Plugin remaps :help because the Help Window and the
|
|
||||||
Project Window get into a fight over placement. The mapping avoids the
|
|
||||||
problem.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
ADDING MAPPINGS *project-adding-mappings*
|
|
||||||
|
|
||||||
You can add your own mappings or change the mappings of the plugin by placing
|
|
||||||
them in the file $HOME/.vimproject_mappings. This file, if it exists, will be
|
|
||||||
sourced when the plugin in loaded. Here is an example that will count the
|
|
||||||
number of entries in a project when you press \K (Kount, C is taken :-): >
|
|
||||||
|
|
||||||
function! s:Wc()
|
|
||||||
let b:loadcount=0
|
|
||||||
function! SpawnExec(infoline, fname, lineno, data)
|
|
||||||
let b:loadcount = b:loadcount + 1
|
|
||||||
if getchar(0) != 0 | let b:stop_everything=1 | endif
|
|
||||||
endfunction
|
|
||||||
call Project_ForEach(1, line('.'), "*SpawnExec", 0, '')
|
|
||||||
delfunction SpawnExec
|
|
||||||
echon b:loadcount." Files\r"
|
|
||||||
unlet b:loadcount
|
|
||||||
if exists("b:stop_everything")
|
|
||||||
unlet b:stop_everything
|
|
||||||
echon "Aborted.\r"
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
nnoremap <buffer> <silent> <LocalLeader>K :call <SID>Wc()<CR>
|
|
||||||
|
|
||||||
Here's another example of how I integrated the use of perforce with the plugin
|
|
||||||
in my $HOME/.vimproject_mappings:
|
|
||||||
>
|
|
||||||
function! s:DoP4(cmd)
|
|
||||||
let name=Project_GetFname(line('.'))
|
|
||||||
let dir=substitute(name, '\(.*\)/.*', '\1', 'g')
|
|
||||||
exec 'cd '.dir
|
|
||||||
exec "!".a:cmd.' '.Project_GetFname(line('.'))
|
|
||||||
cd -
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
nmap <buffer> <silent> \pa :call <SID>DoP4("p4add")<CR>
|
|
||||||
nmap <buffer> <silent> \pe :call <SID>DoP4("p4edit")<CR>
|
|
||||||
<
|
|
||||||
(Note that I CD to the directory the file is in so I can pick of the $P4CONFIG
|
|
||||||
file. See the perforce documentation.)
|
|
||||||
|
|
||||||
This creates the mappings \pe to check out the file for edit and \pa to add
|
|
||||||
the file to the depot.
|
|
||||||
|
|
||||||
Here is another example where I remap the <Return> mapping to use an external
|
|
||||||
program to launch a special kind of file (in this case, it launches ee to view
|
|
||||||
a jpg file). It is a bit contrived, but it works.
|
|
||||||
>
|
|
||||||
let s:sid = substitute(maparg('<Return>', 'n'), '.*\(<SNR>.\{-}\)_.*', '\1', '')
|
|
||||||
function! s:LaunchOrWhat()
|
|
||||||
let fname=Project_GetFname(line('.'))
|
|
||||||
if fname =~ '\.jpg$'
|
|
||||||
exec 'silent! !ee "'.fname.'"&'
|
|
||||||
else
|
|
||||||
call {s:sid}_DoFoldOrOpenEntry('', 'e')
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
nnoremap <buffer> <silent> <Return> \|:call <SID>LaunchOrWhat()<CR>
|
|
||||||
<
|
|
||||||
If the file ends in .jpg, the external program is launched, otherwise the
|
|
||||||
original mapping of <Return> is run.
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
SETTINGS *project-settings*
|
|
||||||
|
|
||||||
You can set these variables in your vimrc file before the plugin is loaded to
|
|
||||||
change its default behavior
|
|
||||||
|
|
||||||
g:proj_window_width
|
|
||||||
The width of the Project Window that the plugin attempts to maintain.
|
|
||||||
Default: 24
|
|
||||||
|
|
||||||
The Project Plugin is not always successful in keeping the window
|
|
||||||
where I want it with the size specified here, but it does a decent
|
|
||||||
job.
|
|
||||||
|
|
||||||
g:proj_window_increment
|
|
||||||
The increment by which to increase the width of the Project Window
|
|
||||||
when pressing <space> or clicking the <LeftMouse>. Default: 100
|
|
||||||
(See |project-mappings|.)
|
|
||||||
|
|
||||||
*project-flags*
|
|
||||||
g:proj_flags
|
|
||||||
Default: "imst"
|
|
||||||
Various flags to control the behavior of the Project Plugin. This
|
|
||||||
variable can contain any of the following character flags.
|
|
||||||
|
|
||||||
flag Description ~
|
|
||||||
|
|
||||||
b When present, use the |browse()| when selecting directories
|
|
||||||
for \c and \C. This is off by default for Windows, because
|
|
||||||
the windows browser does not allow you to select directories.
|
|
||||||
|
|
||||||
c When present, the Project Window will automatically close when
|
|
||||||
you select a file.
|
|
||||||
|
|
||||||
F Float the Project Window. That is, turn off automatic
|
|
||||||
resizing and placement. This allows placement between other
|
|
||||||
windows that wish to share similar placement at the side of
|
|
||||||
the screen. It is also particularly helpful for external
|
|
||||||
window managers.
|
|
||||||
|
|
||||||
g When present, the mapping for <F12> will be created to toggle
|
|
||||||
the Project Window open and closed.
|
|
||||||
|
|
||||||
i When present, display the filename and the current working
|
|
||||||
directory in the command line when a file is selected for
|
|
||||||
opening.
|
|
||||||
|
|
||||||
l When present, the Project Plugin will use the |:lcd| command
|
|
||||||
rather than |:cd| to change directories when you select a file
|
|
||||||
to open. This flag is really obsolete and not of much use
|
|
||||||
because of L below.
|
|
||||||
|
|
||||||
L Similar to l, but install a BufEnter/Leave |:autocommand| to
|
|
||||||
ensure that the current working directory is changed to the
|
|
||||||
one specified in the fold CD specification whenever that
|
|
||||||
buffer is active. (|:lcd| only changes the CWD for a window,
|
|
||||||
not a buffer.)
|
|
||||||
|
|
||||||
m Turn on mapping of the |CTRL-W_o| and |CTRL-W_CTRL_O| normal
|
|
||||||
mode commands to make the current buffer the only visible
|
|
||||||
buffer, but keep the Project Window visible, too.
|
|
||||||
|
|
||||||
n When present, numbers will be turned on for the project
|
|
||||||
window.
|
|
||||||
|
|
||||||
s When present, the Project Plugin will use syntax highlighting
|
|
||||||
in the Project Window.
|
|
||||||
|
|
||||||
S Turn on sorting for refresh and create.
|
|
||||||
|
|
||||||
t When present, toggle the size of the window rather than just
|
|
||||||
increase the size when pressing <space> or right-clicking.
|
|
||||||
See the entry for <RightMouse> in |project-mappings|.
|
|
||||||
|
|
||||||
T When present, put Subproject folds at the top of the fold when
|
|
||||||
refreshing.
|
|
||||||
|
|
||||||
v When present, use :vimgrep rather than :grep when using \G.
|
|
||||||
|
|
||||||
g:proj_run1 ... g:proj_run9
|
|
||||||
Contains a Vim command to execute on the file. See the
|
|
||||||
mappings of \1 to \9 above.
|
|
||||||
|
|
||||||
%f is replaced with the full path and filename
|
|
||||||
%F is replaced with the full path and filename with spaces
|
|
||||||
quoted
|
|
||||||
%n is replaced with the filename alone
|
|
||||||
%N is replaced with the filename alone with spaces quoted
|
|
||||||
%h is replaced with the home directory
|
|
||||||
%H is replaced with the home directory with spaces quoted
|
|
||||||
%r is replaced with the directory relative to the CD path
|
|
||||||
%R is replaced with the directory relative to the CD path
|
|
||||||
with spaces quoted
|
|
||||||
%d is replaced with the CD directory.
|
|
||||||
%D is replaced with the CD directory.with spaces quoted
|
|
||||||
%% is replaced with a single % that is not used in
|
|
||||||
expansion.
|
|
||||||
|
|
||||||
(Deprecated: %s is also replaced with the full path and
|
|
||||||
filename for backward compatibility.)
|
|
||||||
|
|
||||||
For example, gvim will be launched on the file under the
|
|
||||||
cursor when you enter \3 if the following is in your vimrc
|
|
||||||
file: >
|
|
||||||
let g:proj_run3='silent !gvim %f'
|
|
||||||
< Here are a few other examples: >
|
|
||||||
let g:proj_run1='!p4 edit %f'
|
|
||||||
let g:proj_run2='!p4 add %f'
|
|
||||||
let g:proj_run4="echo 'Viewing %f'|sil !xterm -e less %f &"
|
|
||||||
<
|
|
||||||
On Windows systems you will want to put the %f, %h, and %d in
|
|
||||||
single quotes to avoid \ escaping.
|
|
||||||
|
|
||||||
g:proj_run_fold1 ... g:proj_run_fold9
|
|
||||||
Contains a Vim command to execute on the files in a fold. See
|
|
||||||
the mappings of \f1 to \f9 and \F1 to \F9 above.
|
|
||||||
|
|
||||||
%f is the filename, %h is replaced with the project home
|
|
||||||
directory, and %d is replaced with the CD directory. Multiple
|
|
||||||
filenames can be handled in two ways:
|
|
||||||
|
|
||||||
The first (default) way is to have %f replaced with all the
|
|
||||||
absolute filenames, and the command is run once. The second
|
|
||||||
is to have the command run for each of the non-absolute
|
|
||||||
filenames (%f is replaced with one filename at a time). To
|
|
||||||
select the second behavior, put an '*' character at the
|
|
||||||
beginning of the g:proj_run_fold{x} variable. (The '*' is
|
|
||||||
stripped before the command is run.)
|
|
||||||
|
|
||||||
For example, note the difference between the following: >
|
|
||||||
let g:proj_run_fold3="*echo '%h/%f'"
|
|
||||||
let g:proj_run_fold4="echo '%f'"
|
|
||||||
<
|
|
||||||
Note that on Windows systems, you will want the %f, %h, and %c
|
|
||||||
within single quotes, or the \ in the paths will cause
|
|
||||||
problems. The alternative is to put them in |escape()|.
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
PROJECT EXAMPLE FILE *project-example*
|
|
||||||
|
|
||||||
Here is an example ~/.vimprojects file: >
|
|
||||||
|
|
||||||
1 My Project=~/c/project CD=. in=in.vim out=out.vim flags=r {
|
|
||||||
2 Makefile
|
|
||||||
3 in.vim
|
|
||||||
4 out.vim
|
|
||||||
5 GUI Files=. filter="gui*.c gui*.h" {
|
|
||||||
6 gui_window.c
|
|
||||||
7 gui_dialog.c
|
|
||||||
8 gui_list.c
|
|
||||||
9 gui.h # Header file
|
|
||||||
10 }
|
|
||||||
11 Database Files=. filter="data*.c data*.h" {
|
|
||||||
12 data_read.c
|
|
||||||
13 data_write.c
|
|
||||||
14 data.h
|
|
||||||
15 }
|
|
||||||
16 OS-Specific Files {
|
|
||||||
17 Win32=. filter="os_win32*.c os_win32*.h" {
|
|
||||||
18 os_win32_gui.c
|
|
||||||
19 os_win32_io.c
|
|
||||||
20 }
|
|
||||||
21 Unix=. filter="os_unix*.c os_unix*.h" {
|
|
||||||
22 os_unix_gui.c
|
|
||||||
23 os_unix_io.c
|
|
||||||
24 }
|
|
||||||
25 }
|
|
||||||
26 }
|
|
||||||
|
|
||||||
(Don't type in the line numbers, of course.)
|
|
||||||
|
|
||||||
|
|
||||||
==============================================================================
|
|
||||||
TIPS ON USING PROJECT PLUGIN *project-tips*
|
|
||||||
|
|
||||||
1. You can create a Project Entry by entering this: >
|
|
||||||
|
|
||||||
Label=~/wherever CD=. filter="*.c *.h" {
|
|
||||||
}
|
|
||||||
<
|
|
||||||
Then you can put the cursor in the fold and press \r. The script will fill
|
|
||||||
in the files (C files in this case) from this directory for you. This is
|
|
||||||
equivalent to \c without any dialogs.
|
|
||||||
|
|
||||||
2. You can edit the Project File at any time to add, remove, or reorder files
|
|
||||||
in the Project list.
|
|
||||||
|
|
||||||
3. If the Project Window ever gets closed, you can just enter >
|
|
||||||
:Project
|
|
||||||
< to bring it back again. (You don't need to give it the filename; the
|
|
||||||
plugin remembers.)
|
|
||||||
|
|
||||||
If you have the 'm' flag set in g:proj_flags, then you get the Project
|
|
||||||
Window to show up again by pressing |CTRL-W_o|. This, of course, will
|
|
||||||
close any other windows that may be open that the cursor is not in.
|
|
||||||
|
|
||||||
4. Adding files to a Project is very easy. To add, for example, the 'more.c'
|
|
||||||
file to the Project, just insert the filename in the Project Entry then
|
|
||||||
hit <Return> on it.
|
|
||||||
|
|
||||||
5. When |quickfix| loads files, it is not equivalent to pressing <Return> on
|
|
||||||
a filename, so the directory will not be changed and the scripts will not
|
|
||||||
be run. (If I could make this otherwise, I would.) The solution is to use
|
|
||||||
the \L key to load all of the files in the Project before running
|
|
||||||
quickfix.
|
|
||||||
|
|
||||||
6. If the Project window gets a bit cluttered with folds partially
|
|
||||||
open/closed, you can press |zM| to close everything and tidy it up.
|
|
||||||
|
|
||||||
7. For advanced users, I am exporting the function Project_GetAllFnames()
|
|
||||||
which returns all the filenames within a fold and optionally all its
|
|
||||||
Subprojects. Also, I export Project_ForEach() for running a function for
|
|
||||||
each filename in the project. See the code for examples on how to use
|
|
||||||
these. Finally, I export Project_GetFname(line_number) so that you can
|
|
||||||
write your own mappings and get the filename for it.
|
|
||||||
|
|
||||||
8. Some people have asked how to do a global mapping to take the cursor to
|
|
||||||
the Project window. One of my goals for the plugin is for it to be as
|
|
||||||
self-contained as possible, so I'm not going to add it by default. But you
|
|
||||||
can put this in your vimrc:
|
|
||||||
>
|
|
||||||
nmap <silent> <Leader>P :Project<CR>
|
|
||||||
|
|
||||||
<
|
|
||||||
9. You can put the . entry in a project, and it will launch the
|
|
||||||
|file-explorer| plugin on the directory. To avoid removal when you
|
|
||||||
refresh, make the entry look like this:
|
|
||||||
>
|
|
||||||
. # pragma keep
|
|
||||||
<
|
|
||||||
==============================================================================
|
|
||||||
THANKS
|
|
||||||
|
|
||||||
The following people have sent me patches to help with the Project
|
|
||||||
Plugin development:
|
|
||||||
|
|
||||||
Tomas Zellerin
|
|
||||||
Lawrence Kesteloot
|
|
||||||
Dave Eggum
|
|
||||||
A Harrison
|
|
||||||
Thomas Link
|
|
||||||
Richard Bair
|
|
||||||
Eric Arnold
|
|
||||||
Peter Jones
|
|
||||||
Eric Van Dewoestine
|
|
||||||
|
|
||||||
|
|
||||||
vim:ts=8 sw=8 noexpandtab tw=78 ft=help:
|
|
||||||
1192
.vim/doc/rails.txt
1192
.vim/doc/rails.txt
File diff suppressed because it is too large
Load diff
|
|
@ -1,41 +0,0 @@
|
||||||
" ============================================================================
|
|
||||||
" File: exec_menuitem.vim
|
|
||||||
" Description: plugin for NERD Tree that provides an execute file menu item
|
|
||||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
|
||||||
" Last Change: 22 July, 2009
|
|
||||||
" License: This program is free software. It comes without any warranty,
|
|
||||||
" to the extent permitted by applicable law. You can redistribute
|
|
||||||
" it and/or modify it under the terms of the Do What The Fuck You
|
|
||||||
" Want To Public License, Version 2, as published by Sam Hocevar.
|
|
||||||
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
|
||||||
"
|
|
||||||
" ============================================================================
|
|
||||||
if exists("g:loaded_nerdtree_exec_menuitem")
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_nerdtree_exec_menuitem = 1
|
|
||||||
|
|
||||||
call NERDTreeAddMenuItem({
|
|
||||||
\ 'text': '(!)Execute file',
|
|
||||||
\ 'shortcut': '!',
|
|
||||||
\ 'callback': 'NERDTreeExecFile',
|
|
||||||
\ 'isActiveCallback': 'NERDTreeExecFileActive' })
|
|
||||||
|
|
||||||
function! NERDTreeExecFileActive()
|
|
||||||
let node = g:NERDTreeFileNode.GetSelected()
|
|
||||||
return !node.path.isDirectory && node.path.isExecutable
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! NERDTreeExecFile()
|
|
||||||
let treenode = g:NERDTreeFileNode.GetSelected()
|
|
||||||
echo "==========================================================\n"
|
|
||||||
echo "Complete the command to execute (add arguments etc):\n"
|
|
||||||
let cmd = treenode.path.str({'escape': 1})
|
|
||||||
let cmd = input(':!', cmd . ' ')
|
|
||||||
|
|
||||||
if cmd != ''
|
|
||||||
exec ':!' . cmd
|
|
||||||
else
|
|
||||||
echo "Aborted"
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
@ -1,194 +0,0 @@
|
||||||
" ============================================================================
|
|
||||||
" File: fs_menu.vim
|
|
||||||
" Description: plugin for the NERD Tree that provides a file system menu
|
|
||||||
" Maintainer: Martin Grenfell <martin.grenfell at gmail dot com>
|
|
||||||
" Last Change: 17 July, 2009
|
|
||||||
" License: This program is free software. It comes without any warranty,
|
|
||||||
" to the extent permitted by applicable law. You can redistribute
|
|
||||||
" it and/or modify it under the terms of the Do What The Fuck You
|
|
||||||
" Want To Public License, Version 2, as published by Sam Hocevar.
|
|
||||||
" See http://sam.zoy.org/wtfpl/COPYING for more details.
|
|
||||||
"
|
|
||||||
" ============================================================================
|
|
||||||
if exists("g:loaded_nerdtree_fs_menu")
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_nerdtree_fs_menu = 1
|
|
||||||
|
|
||||||
call NERDTreeAddMenuItem({'text': '(a)dd a childnode', 'shortcut': 'a', 'callback': 'NERDTreeAddNode'})
|
|
||||||
call NERDTreeAddMenuItem({'text': '(m)ove the curent node', 'shortcut': 'm', 'callback': 'NERDTreeMoveNode'})
|
|
||||||
call NERDTreeAddMenuItem({'text': '(d)elete the curent node', 'shortcut': 'd', 'callback': 'NERDTreeDeleteNode'})
|
|
||||||
if g:NERDTreePath.CopyingSupported()
|
|
||||||
call NERDTreeAddMenuItem({'text': '(c)copy the current node', 'shortcut': 'c', 'callback': 'NERDTreeCopyNode'})
|
|
||||||
endif
|
|
||||||
|
|
||||||
"FUNCTION: s:echo(msg){{{1
|
|
||||||
function! s:echo(msg)
|
|
||||||
redraw
|
|
||||||
echomsg "NERDTree: " . a:msg
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"FUNCTION: s:echoWarning(msg){{{1
|
|
||||||
function! s:echoWarning(msg)
|
|
||||||
echohl warningmsg
|
|
||||||
call s:echo(a:msg)
|
|
||||||
echohl normal
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"FUNCTION: s:promptToDelBuffer(bufnum, msg){{{1
|
|
||||||
"prints out the given msg and, if the user responds by pushing 'y' then the
|
|
||||||
"buffer with the given bufnum is deleted
|
|
||||||
"
|
|
||||||
"Args:
|
|
||||||
"bufnum: the buffer that may be deleted
|
|
||||||
"msg: a message that will be echoed to the user asking them if they wish to
|
|
||||||
" del the buffer
|
|
||||||
function! s:promptToDelBuffer(bufnum, msg)
|
|
||||||
echo a:msg
|
|
||||||
if nr2char(getchar()) ==# 'y'
|
|
||||||
exec "silent bdelete! " . a:bufnum
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"FUNCTION: NERDTreeAddNode(){{{1
|
|
||||||
function! NERDTreeAddNode()
|
|
||||||
let curDirNode = g:NERDTreeDirNode.GetSelected()
|
|
||||||
|
|
||||||
let newNodeName = input("Add a childnode\n".
|
|
||||||
\ "==========================================================\n".
|
|
||||||
\ "Enter the dir/file name to be created. Dirs end with a '/'\n" .
|
|
||||||
\ "", curDirNode.path.str({'format': 'Glob'}) . g:NERDTreePath.Slash())
|
|
||||||
|
|
||||||
if newNodeName ==# ''
|
|
||||||
call s:echo("Node Creation Aborted.")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
try
|
|
||||||
let newPath = g:NERDTreePath.Create(newNodeName)
|
|
||||||
let parentNode = b:NERDTreeRoot.findNode(newPath.getParent())
|
|
||||||
|
|
||||||
let newTreeNode = g:NERDTreeFileNode.New(newPath)
|
|
||||||
if parentNode.isOpen || !empty(parentNode.children)
|
|
||||||
call parentNode.addChild(newTreeNode, 1)
|
|
||||||
call NERDTreeRender()
|
|
||||||
call newTreeNode.putCursorHere(1, 0)
|
|
||||||
endif
|
|
||||||
catch /^NERDTree/
|
|
||||||
call s:echoWarning("Node Not Created.")
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"FUNCTION: NERDTreeMoveNode(){{{1
|
|
||||||
function! NERDTreeMoveNode()
|
|
||||||
let curNode = g:NERDTreeFileNode.GetSelected()
|
|
||||||
let newNodePath = input("Rename the current node\n" .
|
|
||||||
\ "==========================================================\n" .
|
|
||||||
\ "Enter the new path for the node: \n" .
|
|
||||||
\ "", curNode.path.str())
|
|
||||||
|
|
||||||
if newNodePath ==# ''
|
|
||||||
call s:echo("Node Renaming Aborted.")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
try
|
|
||||||
let bufnum = bufnr(curNode.path.str())
|
|
||||||
|
|
||||||
call curNode.rename(newNodePath)
|
|
||||||
call NERDTreeRender()
|
|
||||||
|
|
||||||
"if the node is open in a buffer, ask the user if they want to
|
|
||||||
"close that buffer
|
|
||||||
if bufnum != -1
|
|
||||||
let prompt = "\nNode renamed.\n\nThe old file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
|
|
||||||
call s:promptToDelBuffer(bufnum, prompt)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call curNode.putCursorHere(1, 0)
|
|
||||||
|
|
||||||
redraw
|
|
||||||
catch /^NERDTree/
|
|
||||||
call s:echoWarning("Node Not Renamed.")
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" FUNCTION: NERDTreeDeleteNode() {{{1
|
|
||||||
function! NERDTreeDeleteNode()
|
|
||||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
|
||||||
let confirmed = 0
|
|
||||||
|
|
||||||
if currentNode.path.isDirectory
|
|
||||||
let choice =input("Delete the current node\n" .
|
|
||||||
\ "==========================================================\n" .
|
|
||||||
\ "STOP! To delete this entire directory, type 'yes'\n" .
|
|
||||||
\ "" . currentNode.path.str() . ": ")
|
|
||||||
let confirmed = choice ==# 'yes'
|
|
||||||
else
|
|
||||||
echo "Delete the current node\n" .
|
|
||||||
\ "==========================================================\n".
|
|
||||||
\ "Are you sure you wish to delete the node:\n" .
|
|
||||||
\ "" . currentNode.path.str() . " (yN):"
|
|
||||||
let choice = nr2char(getchar())
|
|
||||||
let confirmed = choice ==# 'y'
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
if confirmed
|
|
||||||
try
|
|
||||||
call currentNode.delete()
|
|
||||||
call NERDTreeRender()
|
|
||||||
|
|
||||||
"if the node is open in a buffer, ask the user if they want to
|
|
||||||
"close that buffer
|
|
||||||
let bufnum = bufnr(currentNode.path.str())
|
|
||||||
if buflisted(bufnum)
|
|
||||||
let prompt = "\nNode deleted.\n\nThe file is open in buffer ". bufnum . (bufwinnr(bufnum) ==# -1 ? " (hidden)" : "") .". Delete this buffer? (yN)"
|
|
||||||
call s:promptToDelBuffer(bufnum, prompt)
|
|
||||||
endif
|
|
||||||
|
|
||||||
redraw
|
|
||||||
catch /^NERDTree/
|
|
||||||
call s:echoWarning("Could not remove node")
|
|
||||||
endtry
|
|
||||||
else
|
|
||||||
call s:echo("delete aborted")
|
|
||||||
endif
|
|
||||||
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" FUNCTION: NERDTreeCopyNode() {{{1
|
|
||||||
function! NERDTreeCopyNode()
|
|
||||||
let currentNode = g:NERDTreeFileNode.GetSelected()
|
|
||||||
let newNodePath = input("Copy the current node\n" .
|
|
||||||
\ "==========================================================\n" .
|
|
||||||
\ "Enter the new path to copy the node to: \n" .
|
|
||||||
\ "", currentNode.path.str())
|
|
||||||
|
|
||||||
if newNodePath != ""
|
|
||||||
"strip trailing slash
|
|
||||||
let newNodePath = substitute(newNodePath, '\/$', '', '')
|
|
||||||
|
|
||||||
let confirmed = 1
|
|
||||||
if currentNode.path.copyingWillOverwrite(newNodePath)
|
|
||||||
call s:echo("Warning: copying may overwrite files! Continue? (yN)")
|
|
||||||
let choice = nr2char(getchar())
|
|
||||||
let confirmed = choice ==# 'y'
|
|
||||||
endif
|
|
||||||
|
|
||||||
if confirmed
|
|
||||||
try
|
|
||||||
let newNode = currentNode.copy(newNodePath)
|
|
||||||
call NERDTreeRender()
|
|
||||||
call newNode.putCursorHere(0, 0)
|
|
||||||
catch /^NERDTree/
|
|
||||||
call s:echoWarning("Could not copy node")
|
|
||||||
endtry
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
call s:echo("Copy aborted.")
|
|
||||||
endif
|
|
||||||
redraw
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" vim: set sw=4 sts=4 et fdm=marker:
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,293 +0,0 @@
|
||||||
" Tabular: Align columnar data using regex-designated column boundaries
|
|
||||||
" Maintainer: Matthew Wozniski (mjw@drexel.edu)
|
|
||||||
" Date: Thu, 11 Oct 2007 00:35:34 -0400
|
|
||||||
" Version: 0.1
|
|
||||||
|
|
||||||
" Abort if running in vi-compatible mode or the user doesn't want us.
|
|
||||||
if &cp || exists('g:tabular_loaded')
|
|
||||||
if &cp && &verbose
|
|
||||||
echo "Not loading Tabular in compatible mode."
|
|
||||||
endif
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
let g:tabular_loaded = 1
|
|
||||||
|
|
||||||
" Stupid vimscript crap {{{1
|
|
||||||
let s:savecpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
" Private Things {{{1
|
|
||||||
|
|
||||||
" Dictionary of command name to command
|
|
||||||
let s:TabularCommands = {}
|
|
||||||
|
|
||||||
" Generate tab completion list for :Tabularize {{{2
|
|
||||||
" Return a list of commands that match the command line typed so far.
|
|
||||||
" NOTE: Tries to handle commands with spaces in the name, but Vim doesn't seem
|
|
||||||
" to handle that terribly well... maybe I should give up on that.
|
|
||||||
function! s:CompleteTabularizeCommand(argstart, cmdline, cursorpos)
|
|
||||||
let names = keys(s:TabularCommands)
|
|
||||||
if exists("b:TabularCommands")
|
|
||||||
let names += keys(b:TabularCommands)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmdstart = substitute(a:cmdline, '^\s*\S\+\s*', '', '')
|
|
||||||
|
|
||||||
return filter(names, 'v:val =~# ''^\V'' . escape(cmdstart, ''\'')')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Choose the proper command map from the given command line {{{2
|
|
||||||
" Returns [ command map, command line with leading <buffer> removed ]
|
|
||||||
function! s:ChooseCommandMap(commandline)
|
|
||||||
let map = s:TabularCommands
|
|
||||||
let cmd = a:commandline
|
|
||||||
|
|
||||||
if cmd =~# '^<buffer>\s\+'
|
|
||||||
if !exists('b:TabularCommands')
|
|
||||||
let b:TabularCommands = {}
|
|
||||||
endif
|
|
||||||
let map = b:TabularCommands
|
|
||||||
let cmd = substitute(cmd, '^<buffer>\s\+', '', '')
|
|
||||||
endif
|
|
||||||
|
|
||||||
return [ map, cmd ]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Parse '/pattern/format' into separate pattern and format parts. {{{2
|
|
||||||
" If parsing fails, return [ '', '' ]
|
|
||||||
function! s:ParsePattern(string)
|
|
||||||
if a:string[0] != '/'
|
|
||||||
return ['','']
|
|
||||||
endif
|
|
||||||
|
|
||||||
let pat = '\\\@<!\%(\\\\\)\{-}\zs/' . tabular#ElementFormatPattern() . '*$'
|
|
||||||
let format = matchstr(a:string[1:-1], pat)
|
|
||||||
if !empty(format)
|
|
||||||
let format = format[1 : -1]
|
|
||||||
let pattern = a:string[1 : -len(format) - 2]
|
|
||||||
else
|
|
||||||
let pattern = a:string[1 : -1]
|
|
||||||
endif
|
|
||||||
|
|
||||||
return [pattern, format]
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Split apart a list of | separated expressions. {{{2
|
|
||||||
function! s:SplitCommands(string)
|
|
||||||
if a:string =~ '^\s*$'
|
|
||||||
return []
|
|
||||||
endif
|
|
||||||
|
|
||||||
let end = match(a:string, "[\"'|]")
|
|
||||||
|
|
||||||
" Loop until we find a delimiting | or end-of-string
|
|
||||||
while end != -1 && (a:string[end] != '|' || a:string[end+1] == '|')
|
|
||||||
if a:string[end] == "'"
|
|
||||||
let end = match(a:string, "'", end+1) + 1
|
|
||||||
if end == 0
|
|
||||||
throw "No matching end single quote"
|
|
||||||
endif
|
|
||||||
elseif a:string[end] == '"'
|
|
||||||
" Find a " preceded by an even number of \ (or 0)
|
|
||||||
let pattern = '\%(\\\@<!\%(\\\\\)*\)\@<="'
|
|
||||||
let end = matchend(a:string, pattern, end+1) + 1
|
|
||||||
if end == 0
|
|
||||||
throw "No matching end double quote"
|
|
||||||
endif
|
|
||||||
else " Found ||
|
|
||||||
let end += 2
|
|
||||||
endif
|
|
||||||
|
|
||||||
let end = match(a:string, "[\"'|]", end)
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
if end == 0 || a:string[0 : end - (end > 0)] =~ '^\s*$'
|
|
||||||
throw "Empty element"
|
|
||||||
endif
|
|
||||||
|
|
||||||
if end == -1
|
|
||||||
let rv = [ a:string ]
|
|
||||||
else
|
|
||||||
let rv = [ a:string[0 : end-1] ] + s:SplitCommands(a:string[end+1 : -1])
|
|
||||||
endif
|
|
||||||
|
|
||||||
return rv
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Public Things {{{1
|
|
||||||
|
|
||||||
" Command associating a command name with a simple pattern command {{{2
|
|
||||||
" AddTabularPattern[!] [<buffer>] name /pattern[/format]
|
|
||||||
"
|
|
||||||
" If <buffer> is provided, the command will only be available in the current
|
|
||||||
" buffer, and will be used instead of any global command with the same name.
|
|
||||||
"
|
|
||||||
" If a command with the same name and scope already exists, it is an error,
|
|
||||||
" unless the ! is provided, in which case the existing command will be
|
|
||||||
" replaced.
|
|
||||||
"
|
|
||||||
" pattern is a regex describing the delimiter to be used.
|
|
||||||
"
|
|
||||||
" format describes the format pattern to be used. The default will be used if
|
|
||||||
" none is provided.
|
|
||||||
com! -nargs=+ -bang AddTabularPattern
|
|
||||||
\ call AddTabularPattern(<q-args>, <bang>0)
|
|
||||||
|
|
||||||
function! AddTabularPattern(command, force)
|
|
||||||
try
|
|
||||||
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
|
|
||||||
|
|
||||||
let name = matchstr(rest, '.\{-}\ze\s*/')
|
|
||||||
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
|
|
||||||
|
|
||||||
let [ pattern, format ] = s:ParsePattern(pattern)
|
|
||||||
|
|
||||||
if empty(name) || empty(pattern)
|
|
||||||
throw "Invalid arguments!"
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !a:force && has_key(commandmap, name)
|
|
||||||
throw string(name) . " is already defined, use ! to overwrite."
|
|
||||||
endif
|
|
||||||
|
|
||||||
let command = "tabular#TabularizeStrings(a:lines, " . string(pattern)
|
|
||||||
|
|
||||||
if !empty(format)
|
|
||||||
let command .= ", " . string(format)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let command .= ")"
|
|
||||||
|
|
||||||
let commandmap[name] = ":call tabular#PipeRange("
|
|
||||||
\ . string(pattern) . ","
|
|
||||||
\ . string(command) . ")"
|
|
||||||
catch
|
|
||||||
echohl ErrorMsg
|
|
||||||
echomsg "AddTabularPattern: " . v:exception
|
|
||||||
echohl None
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Command associating a command name with a pipeline of functions {{{2
|
|
||||||
" AddTabularPipeline[!] [<buffer>] name /pattern/ func [ | func2 [ | func3 ] ]
|
|
||||||
"
|
|
||||||
" If <buffer> is provided, the command will only be available in the current
|
|
||||||
" buffer, and will be used instead of any global command with the same name.
|
|
||||||
"
|
|
||||||
" If a command with the same name and scope already exists, it is an error,
|
|
||||||
" unless the ! is provided, in which case the existing command will be
|
|
||||||
" replaced.
|
|
||||||
"
|
|
||||||
" pattern is a regex that will be used to determine which lines will be
|
|
||||||
" filtered. If the cursor line doesn't match the pattern, using the command
|
|
||||||
" will be a no-op, otherwise the cursor and all contiguous lines matching the
|
|
||||||
" pattern will be filtered.
|
|
||||||
"
|
|
||||||
" Each 'func' argument represents a function to be called. This function
|
|
||||||
" will have access to a:lines, a List containing one String per line being
|
|
||||||
" filtered.
|
|
||||||
com! -nargs=+ -bang AddTabularPipeline
|
|
||||||
\ call AddTabularPipeline(<q-args>, <bang>0)
|
|
||||||
|
|
||||||
function! AddTabularPipeline(command, force)
|
|
||||||
try
|
|
||||||
let [ commandmap, rest ] = s:ChooseCommandMap(a:command)
|
|
||||||
|
|
||||||
let name = matchstr(rest, '.\{-}\ze\s*/')
|
|
||||||
let pattern = substitute(rest, '.\{-}\s*\ze/', '', '')
|
|
||||||
|
|
||||||
let commands = matchstr(pattern, '^/.\{-}\\\@<!\%(\\\\\)\{-}/\zs.*')
|
|
||||||
let pattern = matchstr(pattern, '/\zs.\{-}\\\@<!\%(\\\\\)\{-}\ze/')
|
|
||||||
|
|
||||||
if empty(name) || empty(pattern)
|
|
||||||
throw "Invalid arguments!"
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !a:force && has_key(commandmap, name)
|
|
||||||
throw string(name) . " is already defined, use ! to overwrite."
|
|
||||||
endif
|
|
||||||
|
|
||||||
let commandlist = s:SplitCommands(commands)
|
|
||||||
|
|
||||||
if empty(commandlist)
|
|
||||||
throw "Must provide a list of functions!"
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd = ":call tabular#PipeRange(" . string(pattern)
|
|
||||||
|
|
||||||
for command in commandlist
|
|
||||||
let cmd .= "," . string(command)
|
|
||||||
endfor
|
|
||||||
|
|
||||||
let cmd .= ")"
|
|
||||||
|
|
||||||
let commandmap[name] = cmd
|
|
||||||
catch
|
|
||||||
echohl ErrorMsg
|
|
||||||
echomsg "AddTabularPipeline: " . v:exception
|
|
||||||
echohl None
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Tabularize /pattern[/format] {{{2
|
|
||||||
" Tabularize name
|
|
||||||
"
|
|
||||||
" Align text, either using the given pattern, or the command associated with
|
|
||||||
" the given name.
|
|
||||||
com! -nargs=* -range -complete=customlist,<SID>CompleteTabularizeCommand
|
|
||||||
\ Tabularize <line1>,<line2>call Tabularize(<q-args>)
|
|
||||||
|
|
||||||
function! Tabularize(command) range
|
|
||||||
if empty(a:command)
|
|
||||||
if !exists("s:last_tabularize_command")
|
|
||||||
echohl ErrorMsg
|
|
||||||
echomsg "Tabularize hasn't been called yet; no pattern/command to reuse!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
let s:last_tabularize_command = a:command
|
|
||||||
endif
|
|
||||||
|
|
||||||
let command = s:last_tabularize_command
|
|
||||||
|
|
||||||
let range = a:firstline . ',' . a:lastline
|
|
||||||
|
|
||||||
try
|
|
||||||
let [ pattern, format ] = s:ParsePattern(command)
|
|
||||||
|
|
||||||
if !empty(pattern)
|
|
||||||
let cmd = "tabular#TabularizeStrings(a:lines, " . string(pattern)
|
|
||||||
|
|
||||||
if !empty(format)
|
|
||||||
let cmd .= "," . string(format)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let cmd .= ")"
|
|
||||||
|
|
||||||
exe range . 'call tabular#PipeRange(pattern, cmd)'
|
|
||||||
else
|
|
||||||
if exists('b:TabularCommands') && has_key(b:TabularCommands, command)
|
|
||||||
let command = b:TabularCommands[command]
|
|
||||||
elseif has_key(s:TabularCommands, command)
|
|
||||||
let command = s:TabularCommands[command]
|
|
||||||
else
|
|
||||||
throw "Unrecognized command " . string(command)
|
|
||||||
endif
|
|
||||||
|
|
||||||
exe range . command
|
|
||||||
endif
|
|
||||||
catch
|
|
||||||
echohl ErrorMsg
|
|
||||||
echomsg "Tabularize: " . v:exception
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endtry
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" Stupid vimscript crap, part 2 {{{1
|
|
||||||
let &cpo = s:savecpo
|
|
||||||
unlet s:savecpo
|
|
||||||
|
|
||||||
" vim:set sw=2 sts=2 fdm=marker:
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
" =============================================================================
|
|
||||||
" File: plugin/ctrlp.vim
|
|
||||||
" Description: Fuzzy file, buffer, mru and tag finder.
|
|
||||||
" Author: Kien Nguyen <github.com/kien>
|
|
||||||
" =============================================================================
|
|
||||||
" GetLatestVimScripts: 3736 1 :AutoInstall: ctrlp.zip
|
|
||||||
|
|
||||||
if ( exists('g:loaded_ctrlp') && g:loaded_ctrlp ) || v:version < 700 || &cp
|
|
||||||
fini
|
|
||||||
en
|
|
||||||
let [g:loaded_ctrlp, g:ctrlp_lines, g:ctrlp_allfiles] = [1, [], []]
|
|
||||||
|
|
||||||
if !exists('g:ctrlp_map') | let g:ctrlp_map = '<c-p>' | en
|
|
||||||
|
|
||||||
com! -na=? -comp=custom,ctrlp#cpl CtrlP cal ctrlp#init(0, <q-args>)
|
|
||||||
|
|
||||||
com! CtrlPBuffer cal ctrlp#init(1)
|
|
||||||
com! CtrlPMRUFiles cal ctrlp#init(2)
|
|
||||||
|
|
||||||
com! ClearCtrlPCache cal ctrlp#clr()
|
|
||||||
com! ClearAllCtrlPCaches cal ctrlp#clra()
|
|
||||||
com! ResetCtrlP cal ctrlp#reset()
|
|
||||||
|
|
||||||
com! CtrlPCurWD cal ctrlp#init(0, 0)
|
|
||||||
com! CtrlPCurFile cal ctrlp#init(0, 1)
|
|
||||||
com! CtrlPRoot cal ctrlp#init(0, 2)
|
|
||||||
|
|
||||||
exe 'nn <silent>' g:ctrlp_map ':<c-u>CtrlP<cr>'
|
|
||||||
|
|
||||||
cal ctrlp#mrufiles#init()
|
|
||||||
|
|
||||||
if !exists('g:ctrlp_extensions') | fini | en
|
|
||||||
|
|
||||||
if index(g:ctrlp_extensions, 'tag') >= 0
|
|
||||||
let g:ctrlp_alltags = [] | com! CtrlPTag cal ctrlp#init(ctrlp#tag#id())
|
|
||||||
en
|
|
||||||
|
|
||||||
if index(g:ctrlp_extensions, 'quickfix') >= 0
|
|
||||||
com! CtrlPQuickfix cal ctrlp#init(ctrlp#quickfix#id())
|
|
||||||
en
|
|
||||||
|
|
||||||
if index(g:ctrlp_extensions, 'dir') >= 0
|
|
||||||
let g:ctrlp_alldirs = [] | com! CtrlPDir cal ctrlp#init(ctrlp#dir#id())
|
|
||||||
en
|
|
||||||
|
|
@ -1,158 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (c) 2007-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
" GetLatestVimScripts: 1984 1 :AutoInstall: FuzzyFinder
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
try
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 101, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
catch /E117/
|
|
||||||
echoerr '***** L9 library must be installed! *****'
|
|
||||||
finish
|
|
||||||
endtry
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" LOCAL FUNCTIONS {{{1
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:initialize()
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_modesDisable' , [ 'mrufile', 'mrucmd', ])
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyOpen' , '<CR>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyOpenSplit' , '<C-j>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyOpenVsplit' , '<C-k>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyOpenTabpage' , '<C-l>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyPreview' , '<C-@>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyNextMode' , '<C-t>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyPrevMode' , '<C-y>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyPrevPattern' , '<C-s>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keyNextPattern' , '<C-_>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_keySwitchMatching', '<C-\><C-\>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_dataDir' , '~/.vim-fuf-data')
|
|
||||||
call l9#defineVariableDefault('g:fuf_abbrevMap' , {})
|
|
||||||
call l9#defineVariableDefault('g:fuf_patternSeparator' , ';')
|
|
||||||
call l9#defineVariableDefault('g:fuf_promptHighlight' , 'Question')
|
|
||||||
call l9#defineVariableDefault('g:fuf_ignoreCase' , 1)
|
|
||||||
call l9#defineVariableDefault('g:fuf_splitPathMatching', 1)
|
|
||||||
call l9#defineVariableDefault('g:fuf_fuzzyRefining' , 0)
|
|
||||||
call l9#defineVariableDefault('g:fuf_smartBs' , 1)
|
|
||||||
call l9#defineVariableDefault('g:fuf_reuseWindow' , 1)
|
|
||||||
call l9#defineVariableDefault('g:fuf_timeFormat' , '(%Y-%m-%d %H:%M:%S)')
|
|
||||||
call l9#defineVariableDefault('g:fuf_learningLimit' , 100)
|
|
||||||
call l9#defineVariableDefault('g:fuf_enumeratingLimit' , 50)
|
|
||||||
call l9#defineVariableDefault('g:fuf_maxMenuWidth' , 78)
|
|
||||||
call l9#defineVariableDefault('g:fuf_previewHeight' , 0)
|
|
||||||
call l9#defineVariableDefault('g:fuf_autoPreview' , 0)
|
|
||||||
call l9#defineVariableDefault('g:fuf_useMigemo' , 0)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffer_prompt' , '>Buffer[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffer_switchOrder', 10)
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffer_mruOrder' , 1)
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffer_keyDelete' , '<C-]>')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_file_prompt' , '>File[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_file_switchOrder', 20)
|
|
||||||
call l9#defineVariableDefault('g:fuf_file_exclude' , '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_prompt' , '>CoverageFile[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_switchOrder', 30)
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_exclude' , '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])')
|
|
||||||
call l9#defineVariableDefault('g:fuf_coveragefile_globPatterns', ['**/.*', '**/*'])
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_dir_prompt' , '>Dir[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_dir_switchOrder', 40)
|
|
||||||
call l9#defineVariableDefault('g:fuf_dir_exclude' , '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_prompt' , '>MRU-File[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_switchOrder', 50)
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_exclude' , '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)')
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_maxItem' , 200)
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_maxItemDir' , 50)
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrufile_keyExpand' , '<C-]>')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrucmd_prompt' , '>MRU-Cmd[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrucmd_switchOrder', 60)
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrucmd_exclude' , '^$')
|
|
||||||
call l9#defineVariableDefault('g:fuf_mrucmd_maxItem' , 200)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkfile_prompt' , '>Bookmark-File[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkfile_switchOrder', 70)
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkfile_searchRange', 400)
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkfile_keyDelete' , '<C-]>')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkdir_prompt' , '>Bookmark-Dir[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkdir_switchOrder', 80)
|
|
||||||
call l9#defineVariableDefault('g:fuf_bookmarkdir_keyDelete' , '<C-]>')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_tag_prompt' , '>Tag[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_tag_switchOrder', 90)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag_prompt' , '>Buffer-Tag[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag_switchOrder', 100)
|
|
||||||
call l9#defineVariableDefault('g:fuf_buffertag_ctagsPath' , 'ctags')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_taggedfile_prompt' , '>Tagged-File[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_taggedfile_switchOrder', 110)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_jumplist_prompt' , '>Jump-List[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_jumplist_switchOrder', 120)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_changelist_prompt' , '>Change-List[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_changelist_switchOrder', 130)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_quickfix_prompt' , '>Quickfix[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_quickfix_switchOrder', 140)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_line_prompt' , '>Line[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_line_switchOrder', 150)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call l9#defineVariableDefault('g:fuf_help_prompt' , '>Help[]>')
|
|
||||||
call l9#defineVariableDefault('g:fuf_help_switchOrder', 160)
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
command! -bang -narg=0 FufEditDataFile call fuf#editDataFile()
|
|
||||||
command! -bang -narg=0 FufRenewCache call s:renewCachesOfAllModes()
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
call fuf#addMode('buffer')
|
|
||||||
call fuf#addMode('file')
|
|
||||||
call fuf#addMode('coveragefile')
|
|
||||||
call fuf#addMode('dir')
|
|
||||||
call fuf#addMode('mrufile')
|
|
||||||
call fuf#addMode('mrucmd')
|
|
||||||
call fuf#addMode('bookmarkfile')
|
|
||||||
call fuf#addMode('bookmarkdir')
|
|
||||||
call fuf#addMode('tag')
|
|
||||||
call fuf#addMode('buffertag')
|
|
||||||
call fuf#addMode('taggedfile')
|
|
||||||
call fuf#addMode('jumplist')
|
|
||||||
call fuf#addMode('changelist')
|
|
||||||
call fuf#addMode('quickfix')
|
|
||||||
call fuf#addMode('line')
|
|
||||||
call fuf#addMode('help')
|
|
||||||
call fuf#addMode('givenfile')
|
|
||||||
call fuf#addMode('givendir')
|
|
||||||
call fuf#addMode('givencmd')
|
|
||||||
call fuf#addMode('callbackfile')
|
|
||||||
call fuf#addMode('callbackitem')
|
|
||||||
"---------------------------------------------------------------------------
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
"
|
|
||||||
function s:renewCachesOfAllModes()
|
|
||||||
for m in fuf#getModeNames()
|
|
||||||
call fuf#{m}#renewCache()
|
|
||||||
endfor
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" INITIALIZATION {{{1
|
|
||||||
|
|
||||||
call s:initialize()
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,967 +0,0 @@
|
||||||
" Name: gnupg.vim
|
|
||||||
" Version: $Id: gnupg.vim 1933 2008-01-23 09:49:33Z mbr $
|
|
||||||
" Author: Markus Braun <markus.braun@krawel.de>
|
|
||||||
" Summary: Vim plugin for transparent editing of gpg encrypted files.
|
|
||||||
" Licence: This program is free software; you can redistribute it and/or
|
|
||||||
" modify it under the terms of the GNU General Public License.
|
|
||||||
" See http://www.gnu.org/copyleft/gpl.txt
|
|
||||||
" Section: Documentation {{{1
|
|
||||||
" Description:
|
|
||||||
"
|
|
||||||
" This script implements transparent editing of gpg encrypted files. The
|
|
||||||
" filename must have a ".gpg", ".pgp" or ".asc" suffix. When opening such
|
|
||||||
" a file the content is decrypted, when opening a new file the script will
|
|
||||||
" ask for the recipients of the encrypted file. The file content will be
|
|
||||||
" encrypted to all recipients before it is written. The script turns off
|
|
||||||
" viminfo and swapfile to increase security.
|
|
||||||
"
|
|
||||||
" Installation:
|
|
||||||
"
|
|
||||||
" Copy the gnupg.vim file to the $HOME/.vim/plugin directory.
|
|
||||||
" Refer to ':help add-plugin', ':help add-global-plugin' and ':help
|
|
||||||
" runtimepath' for more details about Vim plugins.
|
|
||||||
"
|
|
||||||
" Commands:
|
|
||||||
"
|
|
||||||
" :GPGEditRecipients
|
|
||||||
" Opens a scratch buffer to change the list of recipients. Recipients that
|
|
||||||
" are unknown (not in your public key) are highlighted and have
|
|
||||||
" a prepended "!". Closing the buffer makes the changes permanent.
|
|
||||||
"
|
|
||||||
" :GPGViewRecipients
|
|
||||||
" Prints the list of recipients.
|
|
||||||
"
|
|
||||||
" :GPGEditOptions
|
|
||||||
" Opens a scratch buffer to change the options for encryption (symmetric,
|
|
||||||
" asymmetric, signing). Closing the buffer makes the changes permanent.
|
|
||||||
" WARNING: There is no check of the entered options, so you need to know
|
|
||||||
" what you are doing.
|
|
||||||
"
|
|
||||||
" :GPGViewOptions
|
|
||||||
" Prints the list of options.
|
|
||||||
"
|
|
||||||
" Variables:
|
|
||||||
"
|
|
||||||
" g:GPGUseAgent
|
|
||||||
" If set to 0 a possible available gpg-agent won't be used. Defaults to 1.
|
|
||||||
"
|
|
||||||
" g:GPGPreferSymmetric
|
|
||||||
" If set to 1 symmetric encryption is preferred for new files. Defaults to 0.
|
|
||||||
"
|
|
||||||
" g:GPGPreferArmor
|
|
||||||
" If set to 1 armored data is preferred for new files. Defaults to 0.
|
|
||||||
"
|
|
||||||
" Credits:
|
|
||||||
" Mathieu Clabaut for inspirations through his vimspell.vim script.
|
|
||||||
" Richard Bronosky for patch to enable ".pgp" suffix.
|
|
||||||
" Erik Remmelzwaal for patch to enable windows support and patient beta
|
|
||||||
" testing.
|
|
||||||
" Lars Becker for patch to make gpg2 working.
|
|
||||||
"
|
|
||||||
" Section: Plugin header {{{1
|
|
||||||
if (exists("g:loaded_gnupg") || &cp || exists("#BufReadPre#*.\(gpg\|asc\|pgp\)"))
|
|
||||||
finish
|
|
||||||
endi
|
|
||||||
let g:loaded_gnupg = "$Revision: 1933 $"
|
|
||||||
|
|
||||||
" Section: Autocmd setup {{{1
|
|
||||||
augroup GnuPG
|
|
||||||
autocmd!
|
|
||||||
|
|
||||||
" initialize the internal variables
|
|
||||||
autocmd BufNewFile,BufReadPre,FileReadPre *.\(gpg\|asc\|pgp\) call s:GPGInit()
|
|
||||||
" force the user to edit the recipient list if he opens a new file and public
|
|
||||||
" keys are preferred
|
|
||||||
autocmd BufNewFile *.\(gpg\|asc\|pgp\) if (exists("g:GPGPreferSymmetric") && g:GPGPreferSymmetric == 0) | call s:GPGEditRecipients() | endi
|
|
||||||
" do the decryption
|
|
||||||
autocmd BufReadPost,FileReadPost *.\(gpg\|asc\|pgp\) call s:GPGDecrypt()
|
|
||||||
|
|
||||||
" convert all text to encrypted text before writing
|
|
||||||
autocmd BufWritePre,FileWritePre *.\(gpg\|asc\|pgp\) call s:GPGEncrypt()
|
|
||||||
" undo the encryption so we are back in the normal text, directly
|
|
||||||
" after the file has been written.
|
|
||||||
autocmd BufWritePost,FileWritePost *.\(gpg\|asc\|pgp\) call s:GPGEncryptPost()
|
|
||||||
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" Section: Highlight setup {{{1
|
|
||||||
highlight default link GPGWarning WarningMsg
|
|
||||||
highlight default link GPGError ErrorMsg
|
|
||||||
highlight default link GPGHighlightUnknownRecipient ErrorMsg
|
|
||||||
|
|
||||||
" Section: Functions {{{1
|
|
||||||
" Function: s:GPGInit() {{{2
|
|
||||||
"
|
|
||||||
" initialize the plugin
|
|
||||||
"
|
|
||||||
fun s:GPGInit()
|
|
||||||
" first make sure nothing is written to ~/.viminfo while editing
|
|
||||||
" an encrypted file.
|
|
||||||
set viminfo=
|
|
||||||
|
|
||||||
" we don't want a swap file, as it writes unencrypted data to disk
|
|
||||||
set noswapfile
|
|
||||||
|
|
||||||
" check if gpg-agent is allowed
|
|
||||||
if (!exists("g:GPGUseAgent"))
|
|
||||||
let g:GPGUseAgent = 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
" check if symmetric encryption is preferred
|
|
||||||
if (!exists("g:GPGPreferSymmetric"))
|
|
||||||
let g:GPGPreferSymmetric = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
" check if armored files are preferred
|
|
||||||
if (!exists("g:GPGPreferArmor"))
|
|
||||||
let g:GPGPreferArmor = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
" check if debugging is turned on
|
|
||||||
if (!exists("g:GPGDebugLevel"))
|
|
||||||
let g:GPGDebugLevel = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
" print version
|
|
||||||
call s:GPGDebug(1, "gnupg.vim ". g:loaded_gnupg)
|
|
||||||
|
|
||||||
" determine if gnupg can use the gpg-agent
|
|
||||||
if (exists("$GPG_AGENT_INFO") && g:GPGUseAgent == 1)
|
|
||||||
if (!exists("$GPG_TTY"))
|
|
||||||
echohl GPGError
|
|
||||||
echo "The GPG_TTY is not set!"
|
|
||||||
echo "gpg-agent might not work."
|
|
||||||
echohl None
|
|
||||||
endif
|
|
||||||
let s:GPGCommand="gpg --use-agent"
|
|
||||||
else
|
|
||||||
let s:GPGCommand="gpg --no-use-agent"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" don't use tty in gvim
|
|
||||||
" FIXME find a better way to avoid an error.
|
|
||||||
" with this solution only --use-agent will work
|
|
||||||
if has("gui_running")
|
|
||||||
let s:GPGCommand=s:GPGCommand . " --no-tty"
|
|
||||||
endif
|
|
||||||
|
|
||||||
" setup shell environment for unix and windows
|
|
||||||
let s:shellredirsave=&shellredir
|
|
||||||
let s:shellsave=&shell
|
|
||||||
if (match(&shell,"\\(cmd\\|command\\).exe") >= 0)
|
|
||||||
" windows specific settings
|
|
||||||
let s:shellredir = '>%s'
|
|
||||||
let s:shell = &shell
|
|
||||||
let s:stderrredirnull = '2>nul'
|
|
||||||
else
|
|
||||||
" unix specific settings
|
|
||||||
let s:shellredir = &shellredir
|
|
||||||
let s:shell = 'sh'
|
|
||||||
let s:stderrredirnull ='2>/dev/null'
|
|
||||||
let s:GPGCommand="LANG=C LC_ALL=C " . s:GPGCommand
|
|
||||||
endi
|
|
||||||
|
|
||||||
" find the supported algorithms
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
let output=system(s:GPGCommand . " --version")
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
|
|
||||||
let s:GPGPubkey=substitute(output, ".*Pubkey: \\(.\\{-}\\)\n.*", "\\1", "")
|
|
||||||
let s:GPGCipher=substitute(output, ".*Cipher: \\(.\\{-}\\)\n.*", "\\1", "")
|
|
||||||
let s:GPGHash=substitute(output, ".*Hash: \\(.\\{-}\\)\n.*", "\\1", "")
|
|
||||||
let s:GPGCompress=substitute(output, ".*Compress: \\(.\\{-}\\)\n.*", "\\1", "")
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGDecrypt() {{{2
|
|
||||||
"
|
|
||||||
" decrypt the buffer and find all recipients of the encrypted file
|
|
||||||
"
|
|
||||||
fun s:GPGDecrypt()
|
|
||||||
" switch to binary mode to read the encrypted file
|
|
||||||
set bin
|
|
||||||
|
|
||||||
" get the filename of the current buffer
|
|
||||||
let filename=escape(expand("%:p"), '\"')
|
|
||||||
|
|
||||||
" clear GPGEncrypted, GPGRecipients, GPGUnknownRecipients and GPGOptions
|
|
||||||
let b:GPGEncrypted=0
|
|
||||||
let b:GPGRecipients=""
|
|
||||||
let b:GPGUnknownRecipients=""
|
|
||||||
let b:GPGOptions=""
|
|
||||||
|
|
||||||
" find the recipients of the file
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
let output=system(s:GPGCommand . " --verbose --decrypt --list-only --dry-run --batch --no-use-agent --logger-fd 1 \"" . filename . "\"")
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
call s:GPGDebug(1, "output of command '" . s:GPGCommand . " --verbose --decrypt --list-only --dry-run --batch --no-use-agent --logger-fd 1 \"" . filename . "\"' is:")
|
|
||||||
call s:GPGDebug(1, ">>>>> " . output . " <<<<<")
|
|
||||||
|
|
||||||
" check if the file is symmetric/asymmetric encrypted
|
|
||||||
if (match(output, "gpg: encrypted with [[:digit:]]\\+ passphrase") >= 0)
|
|
||||||
" file is symmetric encrypted
|
|
||||||
let b:GPGEncrypted=1
|
|
||||||
call s:GPGDebug(1, "this file is symmetric encrypted")
|
|
||||||
|
|
||||||
let b:GPGOptions=b:GPGOptions . "symmetric:"
|
|
||||||
|
|
||||||
let cipher=substitute(output, ".*gpg: \\([^ ]\\+\\) encrypted data.*", "\\1", "")
|
|
||||||
if (match(s:GPGCipher, "\\<" . cipher . "\\>") >= 0)
|
|
||||||
let b:GPGOptions=b:GPGOptions . "cipher-algo " . cipher . ":"
|
|
||||||
call s:GPGDebug(1, "cipher-algo is " . cipher)
|
|
||||||
else
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "The cipher " . cipher . " is not known by the local gpg command. Using default!"
|
|
||||||
echo
|
|
||||||
echohl None
|
|
||||||
endi
|
|
||||||
elseif (match(output, "gpg: public key is [[:xdigit:]]\\{8}") >= 0)
|
|
||||||
" file is asymmetric encrypted
|
|
||||||
let b:GPGEncrypted=1
|
|
||||||
call s:GPGDebug(1, "this file is asymmetric encrypted")
|
|
||||||
|
|
||||||
let b:GPGOptions=b:GPGOptions . "encrypt:"
|
|
||||||
|
|
||||||
let start=match(output, "gpg: public key is [[:xdigit:]]\\{8}")
|
|
||||||
while (start >= 0)
|
|
||||||
let start=start + strlen("gpg: public key is ")
|
|
||||||
let recipient=strpart(output, start, 8)
|
|
||||||
call s:GPGDebug(1, "recipient is " . recipient)
|
|
||||||
let name=s:GPGNameToID(recipient)
|
|
||||||
if (strlen(name) > 0)
|
|
||||||
let b:GPGRecipients=b:GPGRecipients . name . ":"
|
|
||||||
call s:GPGDebug(1, "name of recipient is " . name)
|
|
||||||
else
|
|
||||||
let b:GPGUnknownRecipients=b:GPGUnknownRecipients . recipient . ":"
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "The recipient " . recipient . " is not in your public keyring!"
|
|
||||||
echohl None
|
|
||||||
end
|
|
||||||
let start=match(output, "gpg: public key is [[:xdigit:]]\\{8}", start)
|
|
||||||
endw
|
|
||||||
else
|
|
||||||
" file is not encrypted
|
|
||||||
let b:GPGEncrypted=0
|
|
||||||
call s:GPGDebug(1, "this file is not encrypted")
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
set nobin
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" check if the message is armored
|
|
||||||
if (match(output, "gpg: armor header") >= 0)
|
|
||||||
call s:GPGDebug(1, "this file is armored")
|
|
||||||
let b:GPGOptions=b:GPGOptions . "armor:"
|
|
||||||
endi
|
|
||||||
|
|
||||||
" finally decrypt the buffer content
|
|
||||||
" since even with the --quiet option passphrase typos will be reported,
|
|
||||||
" we must redirect stderr (using shell temporarily)
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
exec "'[,']!" . s:GPGCommand . " --quiet --decrypt " . s:stderrredirnull
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
if (v:shell_error) " message could not be decrypted
|
|
||||||
silent u
|
|
||||||
echohl GPGError
|
|
||||||
let asd=input("Message could not be decrypted! (Press ENTER)")
|
|
||||||
echohl None
|
|
||||||
bwipeout
|
|
||||||
set nobin
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" turn off binary mode
|
|
||||||
set nobin
|
|
||||||
|
|
||||||
" call the autocommand for the file minus .gpg$
|
|
||||||
execute ":doautocmd BufReadPost " . escape(expand("%:r"), ' *?\"'."'")
|
|
||||||
call s:GPGDebug(2, "called autocommand for " . escape(expand("%:r"), ' *?\"'."'"))
|
|
||||||
|
|
||||||
" refresh screen
|
|
||||||
redraw!
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGEncrypt() {{{2
|
|
||||||
"
|
|
||||||
" encrypts the buffer to all previous recipients
|
|
||||||
"
|
|
||||||
fun s:GPGEncrypt()
|
|
||||||
" save window view
|
|
||||||
let s:GPGWindowView = winsaveview()
|
|
||||||
call s:GPGDebug(2, "saved window view " . string(s:GPGWindowView))
|
|
||||||
|
|
||||||
" store encoding and switch to a safe one
|
|
||||||
if &fileencoding != &encoding
|
|
||||||
let s:GPGEncoding = &encoding
|
|
||||||
let &encoding = &fileencoding
|
|
||||||
call s:GPGDebug(2, "encoding was \"" . s:GPGEncoding . "\", switched to \"" . &encoding . "\"")
|
|
||||||
else
|
|
||||||
let s:GPGEncoding = ""
|
|
||||||
call s:GPGDebug(2, "encoding and fileencoding are the same (\"" . &encoding . "\"), not switching")
|
|
||||||
endi
|
|
||||||
|
|
||||||
" switch buffer to binary mode
|
|
||||||
set bin
|
|
||||||
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
let options=""
|
|
||||||
let recipients=""
|
|
||||||
let field=0
|
|
||||||
|
|
||||||
" built list of options
|
|
||||||
if (!exists("b:GPGOptions") || strlen(b:GPGOptions) == 0)
|
|
||||||
if (exists("g:GPGPreferSymmetric") && g:GPGPreferSymmetric == 1)
|
|
||||||
let b:GPGOptions="symmetric:"
|
|
||||||
else
|
|
||||||
let b:GPGOptions="encrypt:"
|
|
||||||
endi
|
|
||||||
if (exists("g:GPGPreferArmor") && g:GPGPreferArmor == 1)
|
|
||||||
let b:GPGOptions=b:GPGOptions . "armor:"
|
|
||||||
endi
|
|
||||||
call s:GPGDebug(1, "no options set, so using default options: " . b:GPGOptions)
|
|
||||||
endi
|
|
||||||
let field=0
|
|
||||||
let option=s:GetField(b:GPGOptions, ":", field)
|
|
||||||
while (strlen(option))
|
|
||||||
let options=options . " --" . option . " "
|
|
||||||
let field=field+1
|
|
||||||
let option=s:GetField(b:GPGOptions, ":", field)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" check if there are unknown recipients and warn
|
|
||||||
if (exists("b:GPGUnknownRecipients") && strlen(b:GPGUnknownRecipients) > 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "There are unknown recipients!!"
|
|
||||||
echo "Please use GPGEditRecipients to correct!!"
|
|
||||||
echo
|
|
||||||
echohl None
|
|
||||||
call s:GPGDebug(1, "unknown recipients are: " . b:GPGUnknownRecipients)
|
|
||||||
endi
|
|
||||||
|
|
||||||
" built list of recipients
|
|
||||||
if (exists("b:GPGRecipients") && strlen(b:GPGRecipients) > 0)
|
|
||||||
call s:GPGDebug(1, "recipients are: " . b:GPGRecipients)
|
|
||||||
let field=0
|
|
||||||
let gpgid=s:GetField(b:GPGRecipients, ":", field)
|
|
||||||
while (strlen(gpgid))
|
|
||||||
let recipients=recipients . " -r " . gpgid
|
|
||||||
let field=field+1
|
|
||||||
let gpgid=s:GetField(b:GPGRecipients, ":", field)
|
|
||||||
endw
|
|
||||||
else
|
|
||||||
if (match(b:GPGOptions, "encrypt:") >= 0)
|
|
||||||
echohl GPGError
|
|
||||||
echo "There are no recipients!!"
|
|
||||||
echo "Please use GPGEditRecipients to correct!!"
|
|
||||||
echo
|
|
||||||
echohl None
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
|
|
||||||
" encrypt the buffer
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
silent exec "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
call s:GPGDebug(1, "called gpg command is: " . "'[,']!" . s:GPGCommand . " --quiet --no-encrypt-to " . options . recipients . " " . s:stderrredirnull)
|
|
||||||
if (v:shell_error) " message could not be encrypted
|
|
||||||
silent u
|
|
||||||
echohl GPGError
|
|
||||||
let asd=input("Message could not be encrypted! File might be empty! (Press ENTER)")
|
|
||||||
echohl None
|
|
||||||
bwipeout
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGEncryptPost() {{{2
|
|
||||||
"
|
|
||||||
" undo changes don by encrypt, after writing
|
|
||||||
"
|
|
||||||
fun s:GPGEncryptPost()
|
|
||||||
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" undo encryption of buffer content
|
|
||||||
silent u
|
|
||||||
|
|
||||||
" switch back from binary mode
|
|
||||||
set nobin
|
|
||||||
|
|
||||||
" restore encoding
|
|
||||||
if s:GPGEncoding != ""
|
|
||||||
let &encoding = s:GPGEncoding
|
|
||||||
call s:GPGDebug(2, "restored encoding \"" . &encoding . "\"")
|
|
||||||
endi
|
|
||||||
|
|
||||||
" restore window view
|
|
||||||
call winrestview(s:GPGWindowView)
|
|
||||||
call s:GPGDebug(2, "restored window view" . string(s:GPGWindowView))
|
|
||||||
|
|
||||||
" refresh screen
|
|
||||||
redraw!
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGViewRecipients() {{{2
|
|
||||||
"
|
|
||||||
" echo the recipients
|
|
||||||
"
|
|
||||||
fun s:GPGViewRecipients()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
if (exists("b:GPGRecipients"))
|
|
||||||
echo 'This file has following recipients (Unknown recipients have a prepended "!"):'
|
|
||||||
" echo the recipients
|
|
||||||
let field=0
|
|
||||||
let name=s:GetField(b:GPGRecipients, ":", field)
|
|
||||||
while (strlen(name) > 0)
|
|
||||||
let name=s:GPGIDToName(name)
|
|
||||||
echo name
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let name=s:GetField(b:GPGRecipients, ":", field)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" put the unknown recipients in the scratch buffer
|
|
||||||
let field=0
|
|
||||||
echohl GPGWarning
|
|
||||||
let name=s:GetField(b:GPGUnknownRecipients, ":", field)
|
|
||||||
while (strlen(name) > 0)
|
|
||||||
let name="!" . name
|
|
||||||
echo name
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let name=s:GetField(b:GPGUnknownRecipients, ":", field)
|
|
||||||
endw
|
|
||||||
echohl None
|
|
||||||
|
|
||||||
" check if there is any known recipient
|
|
||||||
if (strlen(s:GetField(b:GPGRecipients, ":", 0)) == 0)
|
|
||||||
echohl GPGError
|
|
||||||
echo 'There are no known recipients!'
|
|
||||||
echohl None
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGEditRecipients() {{{2
|
|
||||||
"
|
|
||||||
" create a scratch buffer with all recipients to add/remove recipients
|
|
||||||
"
|
|
||||||
fun s:GPGEditRecipients()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" only do this if it isn't already a GPGRecipients_* buffer
|
|
||||||
if (match(bufname("%"), "^\\(GPGRecipients_\\|GPGOptions_\\)") != 0 && match(bufname("%"), "\.\\(gpg\\|asc\\|pgp\\)$") >= 0)
|
|
||||||
|
|
||||||
" save buffer name
|
|
||||||
let buffername=bufname("%")
|
|
||||||
let editbuffername="GPGRecipients_" . buffername
|
|
||||||
|
|
||||||
" check if this buffer exists
|
|
||||||
if (!bufexists(editbuffername))
|
|
||||||
" create scratch buffer
|
|
||||||
exe 'silent! split ' . escape(editbuffername, ' *?\"'."'")
|
|
||||||
|
|
||||||
" add a autocommand to regenerate the recipients after a write
|
|
||||||
autocmd BufHidden,BufUnload <buffer> call s:GPGFinishRecipientsBuffer()
|
|
||||||
else
|
|
||||||
if (bufwinnr(editbuffername) >= 0)
|
|
||||||
" switch to scratch buffer window
|
|
||||||
exe 'silent! ' . bufwinnr(editbuffername) . "wincmd w"
|
|
||||||
else
|
|
||||||
" split scratch buffer window
|
|
||||||
exe 'silent! sbuffer ' . escape(editbuffername, ' *?\"'."'")
|
|
||||||
|
|
||||||
" add a autocommand to regenerate the recipients after a write
|
|
||||||
autocmd BufHidden,BufUnload <buffer> call s:GPGFinishRecipientsBuffer()
|
|
||||||
endi
|
|
||||||
|
|
||||||
" empty the buffer
|
|
||||||
silent normal! 1GdG
|
|
||||||
endi
|
|
||||||
|
|
||||||
" Mark the buffer as a scratch buffer
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nowrap
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal nonumber
|
|
||||||
|
|
||||||
" so we know for which other buffer this edit buffer is
|
|
||||||
let b:corresponding_to=buffername
|
|
||||||
|
|
||||||
" put some comments to the scratch buffer
|
|
||||||
silent put ='GPG: ----------------------------------------------------------------------'
|
|
||||||
silent put ='GPG: Please edit the list of recipients, one recipient per line'
|
|
||||||
silent put ='GPG: Unknown recipients have a prepended \"!\"'
|
|
||||||
silent put ='GPG: Lines beginning with \"GPG:\" are removed automatically'
|
|
||||||
silent put ='GPG: Closing this buffer commits changes'
|
|
||||||
silent put ='GPG: ----------------------------------------------------------------------'
|
|
||||||
|
|
||||||
" put the recipients in the scratch buffer
|
|
||||||
let recipients=getbufvar(b:corresponding_to, "GPGRecipients")
|
|
||||||
let field=0
|
|
||||||
|
|
||||||
let name=s:GetField(recipients, ":", field)
|
|
||||||
while (strlen(name) > 0)
|
|
||||||
let name=s:GPGIDToName(name)
|
|
||||||
silent put =name
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let name=s:GetField(recipients, ":", field)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" put the unknown recipients in the scratch buffer
|
|
||||||
let unknownRecipients=getbufvar(b:corresponding_to, "GPGUnknownRecipients")
|
|
||||||
let field=0
|
|
||||||
let syntaxPattern="\\(nonexistingwordinthisbuffer"
|
|
||||||
|
|
||||||
let name=s:GetField(unknownRecipients, ":", field)
|
|
||||||
while (strlen(name) > 0)
|
|
||||||
let name="!" . name
|
|
||||||
let syntaxPattern=syntaxPattern . "\\|" . name
|
|
||||||
silent put =name
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let name=s:GetField(unknownRecipients, ":", field)
|
|
||||||
endw
|
|
||||||
|
|
||||||
let syntaxPattern=syntaxPattern . "\\)"
|
|
||||||
|
|
||||||
" define highlight
|
|
||||||
if (has("syntax") && exists("g:syntax_on"))
|
|
||||||
exec('syntax match GPGUnknownRecipient "' . syntaxPattern . '"')
|
|
||||||
highlight clear GPGUnknownRecipient
|
|
||||||
highlight link GPGUnknownRecipient GPGHighlightUnknownRecipient
|
|
||||||
|
|
||||||
syntax match GPGComment "^GPG:.*$"
|
|
||||||
highlight clear GPGComment
|
|
||||||
highlight link GPGComment Comment
|
|
||||||
endi
|
|
||||||
|
|
||||||
" delete the empty first line
|
|
||||||
silent normal! 1Gdd
|
|
||||||
|
|
||||||
" jump to the first recipient
|
|
||||||
silent normal! G
|
|
||||||
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGFinishRecipientsBuffer() {{{2
|
|
||||||
"
|
|
||||||
" create a new recipient list from RecipientsBuffer
|
|
||||||
fun s:GPGFinishRecipientsBuffer()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" go to buffer before doing work
|
|
||||||
if (bufnr("%") != expand("<abuf>"))
|
|
||||||
" switch to scratch buffer window
|
|
||||||
exe 'silent! ' . bufwinnr(expand("<afile>")) . "wincmd w"
|
|
||||||
endi
|
|
||||||
|
|
||||||
" clear GPGRecipients and GPGUnknownRecipients
|
|
||||||
let GPGRecipients=""
|
|
||||||
let GPGUnknownRecipients=""
|
|
||||||
|
|
||||||
" delete the autocommand
|
|
||||||
autocmd! * <buffer>
|
|
||||||
|
|
||||||
let currentline=1
|
|
||||||
let recipient=getline(currentline)
|
|
||||||
|
|
||||||
" get the recipients from the scratch buffer
|
|
||||||
while (currentline <= line("$"))
|
|
||||||
" delete all spaces at beginning and end of the line
|
|
||||||
" also delete a '!' at the beginning of the line
|
|
||||||
let recipient=substitute(recipient, "^[[:space:]!]*\\(.\\{-}\\)[[:space:]]*$", "\\1", "")
|
|
||||||
" delete comment lines
|
|
||||||
let recipient=substitute(recipient, "^GPG:.*$", "", "")
|
|
||||||
|
|
||||||
" only do this if the line is not empty
|
|
||||||
if (strlen(recipient) > 0)
|
|
||||||
let gpgid=s:GPGNameToID(recipient)
|
|
||||||
if (strlen(gpgid) > 0)
|
|
||||||
let GPGRecipients=GPGRecipients . gpgid . ":"
|
|
||||||
else
|
|
||||||
let GPGUnknownRecipients=GPGUnknownRecipients . recipient . ":"
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "The recipient " . recipient . " is not in your public keyring!"
|
|
||||||
echohl None
|
|
||||||
end
|
|
||||||
endi
|
|
||||||
|
|
||||||
let currentline=currentline+1
|
|
||||||
let recipient=getline(currentline)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" write back the new recipient list to the corresponding buffer and mark it
|
|
||||||
" as modified. Buffer is now for sure a encrypted buffer.
|
|
||||||
call setbufvar(b:corresponding_to, "GPGRecipients", GPGRecipients)
|
|
||||||
call setbufvar(b:corresponding_to, "GPGUnknownRecipients", GPGUnknownRecipients)
|
|
||||||
call setbufvar(b:corresponding_to, "&mod", 1)
|
|
||||||
call setbufvar(b:corresponding_to, "GPGEncrypted", 1)
|
|
||||||
|
|
||||||
" check if there is any known recipient
|
|
||||||
if (strlen(s:GetField(GPGRecipients, ":", 0)) == 0)
|
|
||||||
echohl GPGError
|
|
||||||
echo 'There are no known recipients!'
|
|
||||||
echohl None
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGViewOptions() {{{2
|
|
||||||
"
|
|
||||||
" echo the recipients
|
|
||||||
"
|
|
||||||
fun s:GPGViewOptions()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
if (exists("b:GPGOptions"))
|
|
||||||
echo 'This file has following options:'
|
|
||||||
" echo the options
|
|
||||||
let field=0
|
|
||||||
let option=s:GetField(b:GPGOptions, ":", field)
|
|
||||||
while (strlen(option) > 0)
|
|
||||||
echo option
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let option=s:GetField(b:GPGOptions, ":", field)
|
|
||||||
endw
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGEditOptions() {{{2
|
|
||||||
"
|
|
||||||
" create a scratch buffer with all recipients to add/remove recipients
|
|
||||||
"
|
|
||||||
fun s:GPGEditOptions()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" only do this if it isn't already a GPGOptions_* buffer
|
|
||||||
if (match(bufname("%"), "^\\(GPGRecipients_\\|GPGOptions_\\)") != 0 && match(bufname("%"), "\.\\(gpg\\|asc\\|pgp\\)$") >= 0)
|
|
||||||
|
|
||||||
" save buffer name
|
|
||||||
let buffername=bufname("%")
|
|
||||||
let editbuffername="GPGOptions_" . buffername
|
|
||||||
|
|
||||||
" check if this buffer exists
|
|
||||||
if (!bufexists(editbuffername))
|
|
||||||
" create scratch buffer
|
|
||||||
exe 'silent! split ' . escape(editbuffername, ' *?\"'."'")
|
|
||||||
|
|
||||||
" add a autocommand to regenerate the options after a write
|
|
||||||
autocmd BufHidden,BufUnload <buffer> call s:GPGFinishOptionsBuffer()
|
|
||||||
else
|
|
||||||
if (bufwinnr(editbuffername) >= 0)
|
|
||||||
" switch to scratch buffer window
|
|
||||||
exe 'silent! ' . bufwinnr(editbuffername) . "wincmd w"
|
|
||||||
else
|
|
||||||
" split scratch buffer window
|
|
||||||
exe 'silent! sbuffer ' . escape(editbuffername, ' *?\"'."'")
|
|
||||||
|
|
||||||
" add a autocommand to regenerate the options after a write
|
|
||||||
autocmd BufHidden,BufUnload <buffer> call s:GPGFinishOptionsBuffer()
|
|
||||||
endi
|
|
||||||
|
|
||||||
" empty the buffer
|
|
||||||
silent normal! 1GdG
|
|
||||||
endi
|
|
||||||
|
|
||||||
" Mark the buffer as a scratch buffer
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nowrap
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal nonumber
|
|
||||||
|
|
||||||
" so we know for which other buffer this edit buffer is
|
|
||||||
let b:corresponding_to=buffername
|
|
||||||
|
|
||||||
" put some comments to the scratch buffer
|
|
||||||
silent put ='GPG: ----------------------------------------------------------------------'
|
|
||||||
silent put ='GPG: THERE IS NO CHECK OF THE ENTERED OPTIONS!'
|
|
||||||
silent put ='GPG: YOU NEED TO KNOW WHAT YOU ARE DOING!'
|
|
||||||
silent put ='GPG: IF IN DOUBT, QUICKLY EXIT USING :x OR :bd'
|
|
||||||
silent put ='GPG: Please edit the list of options, one option per line'
|
|
||||||
silent put ='GPG: Please refer to the gpg documentation for valid options'
|
|
||||||
silent put ='GPG: Lines beginning with \"GPG:\" are removed automatically'
|
|
||||||
silent put ='GPG: Closing this buffer commits changes'
|
|
||||||
silent put ='GPG: ----------------------------------------------------------------------'
|
|
||||||
|
|
||||||
" put the options in the scratch buffer
|
|
||||||
let options=getbufvar(b:corresponding_to, "GPGOptions")
|
|
||||||
let field=0
|
|
||||||
|
|
||||||
let option=s:GetField(options, ":", field)
|
|
||||||
while (strlen(option) > 0)
|
|
||||||
silent put =option
|
|
||||||
|
|
||||||
let field=field+1
|
|
||||||
let option=s:GetField(options, ":", field)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" delete the empty first line
|
|
||||||
silent normal! 1Gdd
|
|
||||||
|
|
||||||
" jump to the first option
|
|
||||||
silent normal! G
|
|
||||||
|
|
||||||
" define highlight
|
|
||||||
if (has("syntax") && exists("g:syntax_on"))
|
|
||||||
syntax match GPGComment "^GPG:.*$"
|
|
||||||
highlight clear GPGComment
|
|
||||||
highlight link GPGComment Comment
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGFinishOptionsBuffer() {{{2
|
|
||||||
"
|
|
||||||
" create a new option list from OptionsBuffer
|
|
||||||
fun s:GPGFinishOptionsBuffer()
|
|
||||||
" guard for unencrypted files
|
|
||||||
if (exists("b:GPGEncrypted") && b:GPGEncrypted == 0)
|
|
||||||
echohl GPGWarning
|
|
||||||
echo "File is not encrypted, all GPG functions disabled!"
|
|
||||||
echohl None
|
|
||||||
return
|
|
||||||
endi
|
|
||||||
|
|
||||||
" go to buffer before doing work
|
|
||||||
if (bufnr("%") != expand("<abuf>"))
|
|
||||||
" switch to scratch buffer window
|
|
||||||
exe 'silent! ' . bufwinnr(expand("<afile>")) . "wincmd w"
|
|
||||||
endi
|
|
||||||
|
|
||||||
" clear GPGOptions and GPGUnknownOptions
|
|
||||||
let GPGOptions=""
|
|
||||||
let GPGUnknownOptions=""
|
|
||||||
|
|
||||||
" delete the autocommand
|
|
||||||
autocmd! * <buffer>
|
|
||||||
|
|
||||||
let currentline=1
|
|
||||||
let option=getline(currentline)
|
|
||||||
|
|
||||||
" get the options from the scratch buffer
|
|
||||||
while (currentline <= line("$"))
|
|
||||||
" delete all spaces at beginning and end of the line
|
|
||||||
" also delete a '!' at the beginning of the line
|
|
||||||
let option=substitute(option, "^[[:space:]!]*\\(.\\{-}\\)[[:space:]]*$", "\\1", "")
|
|
||||||
" delete comment lines
|
|
||||||
let option=substitute(option, "^GPG:.*$", "", "")
|
|
||||||
|
|
||||||
" only do this if the line is not empty
|
|
||||||
if (strlen(option) > 0)
|
|
||||||
let GPGOptions=GPGOptions . option . ":"
|
|
||||||
endi
|
|
||||||
|
|
||||||
let currentline=currentline+1
|
|
||||||
let option=getline(currentline)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" write back the new option list to the corresponding buffer and mark it
|
|
||||||
" as modified
|
|
||||||
call setbufvar(b:corresponding_to, "GPGOptions", GPGOptions)
|
|
||||||
call setbufvar(b:corresponding_to, "&mod", 1)
|
|
||||||
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGNameToID(name) {{{2
|
|
||||||
"
|
|
||||||
" find GPG key ID corresponding to a name
|
|
||||||
" Returns: ID for the given name
|
|
||||||
fun s:GPGNameToID(name)
|
|
||||||
" ask gpg for the id for a name
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
let output=system(s:GPGCommand . " --quiet --with-colons --fixed-list-mode --list-keys \"" . a:name . "\"")
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
|
|
||||||
" parse the output of gpg
|
|
||||||
let pub_seen=0
|
|
||||||
let uid_seen=0
|
|
||||||
let line=0
|
|
||||||
let counter=0
|
|
||||||
let gpgids=""
|
|
||||||
let choices="The name \"" . a:name . "\" is ambiguous. Please select the correct key:\n"
|
|
||||||
let linecontent=s:GetField(output, "\n", line)
|
|
||||||
while (strlen(linecontent))
|
|
||||||
" search for the next uid
|
|
||||||
if (pub_seen == 1)
|
|
||||||
if (s:GetField(linecontent, ":", 0) == "uid")
|
|
||||||
if (uid_seen == 0)
|
|
||||||
let choices=choices . counter . ": " . s:GetField(linecontent, ":", 9) . "\n"
|
|
||||||
let counter=counter+1
|
|
||||||
let uid_seen=1
|
|
||||||
else
|
|
||||||
let choices=choices . " " . s:GetField(linecontent, ":", 9) . "\n"
|
|
||||||
endi
|
|
||||||
else
|
|
||||||
let uid_seen=0
|
|
||||||
let pub_seen=0
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
|
|
||||||
" search for the next pub
|
|
||||||
if (pub_seen == 0)
|
|
||||||
if (s:GetField(linecontent, ":", 0) == "pub")
|
|
||||||
let gpgids=gpgids . s:GetField(linecontent, ":", 4) . ":"
|
|
||||||
let pub_seen=1
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
|
|
||||||
let line=line+1
|
|
||||||
let linecontent=s:GetField(output, "\n", line)
|
|
||||||
endw
|
|
||||||
|
|
||||||
" counter > 1 means we have more than one results
|
|
||||||
let answer=0
|
|
||||||
if (counter > 1)
|
|
||||||
let choices=choices . "Enter number: "
|
|
||||||
let answer=input(choices, "0")
|
|
||||||
while (answer == "")
|
|
||||||
let answer=input("Enter number: ", "0")
|
|
||||||
endw
|
|
||||||
endi
|
|
||||||
|
|
||||||
return s:GetField(gpgids, ":", answer)
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGIDToName(identity) {{{2
|
|
||||||
"
|
|
||||||
" find name corresponding to a GPG key ID
|
|
||||||
" Returns: Name for the given ID
|
|
||||||
fun s:GPGIDToName(identity)
|
|
||||||
" TODO is the encryption subkey really unique?
|
|
||||||
|
|
||||||
" ask gpg for the id for a name
|
|
||||||
let &shellredir=s:shellredir
|
|
||||||
let &shell=s:shell
|
|
||||||
let output=system(s:GPGCommand . " --quiet --with-colons --fixed-list-mode --list-keys " . a:identity )
|
|
||||||
let &shellredir=s:shellredirsave
|
|
||||||
let &shell=s:shellsave
|
|
||||||
|
|
||||||
" parse the output of gpg
|
|
||||||
let pub_seen=0
|
|
||||||
let finish=0
|
|
||||||
let line=0
|
|
||||||
let linecontent=s:GetField(output, "\n", line)
|
|
||||||
while (strlen(linecontent) && !finish)
|
|
||||||
if (pub_seen == 0) " search for the next pub
|
|
||||||
if (s:GetField(linecontent, ":", 0) == "pub")
|
|
||||||
let pub_seen=1
|
|
||||||
endi
|
|
||||||
else " search for the next uid
|
|
||||||
if (s:GetField(linecontent, ":", 0) == "uid")
|
|
||||||
let pub_seen=0
|
|
||||||
let finish=1
|
|
||||||
let uid=s:GetField(linecontent, ":", 9)
|
|
||||||
endi
|
|
||||||
endi
|
|
||||||
|
|
||||||
let line=line+1
|
|
||||||
let linecontent=s:GetField(output, "\n", line)
|
|
||||||
endw
|
|
||||||
|
|
||||||
return uid
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GetField(line, separator, field) {{{2
|
|
||||||
"
|
|
||||||
" find field of 'separator' separated string, counting starts with 0
|
|
||||||
" Returns: content of the field, if field doesn't exist it returns an empty
|
|
||||||
" string
|
|
||||||
fun s:GetField(line, separator, field)
|
|
||||||
let counter=a:field
|
|
||||||
let separatorLength=strlen(a:separator)
|
|
||||||
let start=0
|
|
||||||
let end=match(a:line, a:separator)
|
|
||||||
if (end < 0)
|
|
||||||
let end=strlen(a:line)
|
|
||||||
endi
|
|
||||||
|
|
||||||
" search for requested field
|
|
||||||
while (start < strlen(a:line) && counter > 0)
|
|
||||||
let counter=counter-separatorLength
|
|
||||||
let start=end+separatorLength
|
|
||||||
let end=match(a:line, a:separator, start)
|
|
||||||
if (end < 0)
|
|
||||||
let end=strlen(a:line)
|
|
||||||
endi
|
|
||||||
endw
|
|
||||||
|
|
||||||
if (start < strlen(a:line))
|
|
||||||
return strpart(a:line, start, end-start)
|
|
||||||
else
|
|
||||||
return ""
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Function: s:GPGDebug(level, text) {{{2
|
|
||||||
"
|
|
||||||
" output debug message, if this message has high enough importance
|
|
||||||
fun s:GPGDebug(level, text)
|
|
||||||
if (g:GPGDebugLevel >= a:level)
|
|
||||||
echom a:text
|
|
||||||
endi
|
|
||||||
endf
|
|
||||||
|
|
||||||
" Section: Command definitions {{{1
|
|
||||||
com! GPGViewRecipients call s:GPGViewRecipients()
|
|
||||||
com! GPGEditRecipients call s:GPGEditRecipients()
|
|
||||||
com! GPGViewOptions call s:GPGViewOptions()
|
|
||||||
com! GPGEditOptions call s:GPGEditOptions()
|
|
||||||
|
|
||||||
" vim600: foldmethod=marker:foldlevel=0
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
"=============================================================================
|
|
||||||
" Copyright (C) 2009-2010 Takeshi NISHIDA
|
|
||||||
"
|
|
||||||
" GetLatestVimScripts: 3252 1 :AutoInstall: L9
|
|
||||||
"=============================================================================
|
|
||||||
" LOAD GUARD {{{1
|
|
||||||
|
|
||||||
if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 0, [])
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" OPTIONS: {{{1
|
|
||||||
|
|
||||||
call l9#defineVariableDefault('g:l9_balloonly', 'balloonly.exe')
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" ASSERTION: {{{1
|
|
||||||
|
|
||||||
" This command has effect only if $L9_DEBUG is non-zero.
|
|
||||||
" Used as follows:
|
|
||||||
" L9Assert a:i > 0
|
|
||||||
" This command can't interpret script-local variables directly.
|
|
||||||
" NG: L9Assert s:a == 1
|
|
||||||
" OK: execute 'L9Assert ' . s:a . ' == 1'
|
|
||||||
"
|
|
||||||
if $L9_DEBUG
|
|
||||||
command -nargs=* L9Assert call eval((<args>) ? 0 : s:handleFailedAssersion(<q-args>))
|
|
||||||
|
|
||||||
function s:handleFailedAssersion(expr)
|
|
||||||
echoerr '[L9Assert] Assersion failure: ' . a:expr
|
|
||||||
if input('[L9Assert] Continue? (Y/N) ', 'Y') !=? 'Y'
|
|
||||||
throw 'L9Assert ' . a:expr
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
else
|
|
||||||
command -nargs=* L9Assert :
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" TIMER: {{{1
|
|
||||||
|
|
||||||
" These commands have effect only if $L9_TIMER is non-zero.
|
|
||||||
" Used as follows:
|
|
||||||
" L9Timer foo
|
|
||||||
" ... (1)
|
|
||||||
" L9Timer bar
|
|
||||||
" ... (2)
|
|
||||||
" L9TimerStop
|
|
||||||
" ...
|
|
||||||
" L9TimerDump <- shows each elapsed time of (1) and (2)
|
|
||||||
"
|
|
||||||
if $L9_TIMER
|
|
||||||
command -nargs=1 L9Timer call s:timerBegin(<q-args>)
|
|
||||||
command -nargs=0 L9TimerStop call s:timerStop()
|
|
||||||
command -nargs=0 L9TimerDump call s:timerDump()
|
|
||||||
|
|
||||||
let s:timerData = []
|
|
||||||
let s:timerTagMaxLen = 0
|
|
||||||
|
|
||||||
function s:timerBegin(tag)
|
|
||||||
L9TimerStop
|
|
||||||
let s:timerCurrent = {'tag': strftime('%c ') . a:tag . ' ', 'time': reltime()}
|
|
||||||
let s:timerTagMaxLen = max([len(s:timerCurrent.tag), s:timerTagMaxLen])
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function s:timerStop()
|
|
||||||
if !exists('s:timerCurrent')
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let s:timerCurrent.time = reltimestr(reltime(s:timerCurrent.time))
|
|
||||||
call add(s:timerData, s:timerCurrent)
|
|
||||||
unlet s:timerCurrent
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function s:timerDump()
|
|
||||||
L9TimerStop
|
|
||||||
let lines = map(s:timerData, 'v:val.tag . repeat(" ", s:timerTagMaxLen - len(v:val.tag)) . v:val.time')
|
|
||||||
call l9#tempbuffer#openReadOnly('[l9-timer]', '', lines, 0, 0, 0, {})
|
|
||||||
let s:timerData = []
|
|
||||||
let s:timerTagMaxLen = 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
else
|
|
||||||
command -nargs=1 L9Timer :
|
|
||||||
command -nargs=0 L9TimerStop :
|
|
||||||
command -nargs=0 L9TimerDump :
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" GREP BUFFER: {{{1
|
|
||||||
|
|
||||||
" Grep for current buffer by l9#grepBuffers()
|
|
||||||
" Used as :L9GrepBuffer/pattern
|
|
||||||
command -nargs=? L9GrepBuffer call l9#grepBuffers(<q-args>, [bufnr('%')])
|
|
||||||
|
|
||||||
" Grep for all buffers by l9#grepBuffers()
|
|
||||||
" Used as :L9GrepBufferAll/pattern
|
|
||||||
command -nargs=? L9GrepBufferAll call l9#grepBuffers(<q-args>, range(1, bufnr('$')))
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
"=============================================================================
|
|
||||||
" vim: set fdm=marker:
|
|
||||||
|
|
@ -1,812 +0,0 @@
|
||||||
" matchit.vim: (global plugin) Extended "%" matching
|
|
||||||
" Last Change: Fri Jan 25 10:00 AM 2008 EST
|
|
||||||
" Maintainer: Benji Fisher PhD <benji@member.AMS.org>
|
|
||||||
" Version: 1.13.2, for Vim 6.3+
|
|
||||||
" URL: http://www.vim.org/script.php?script_id=39
|
|
||||||
|
|
||||||
" Documentation:
|
|
||||||
" The documentation is in a separate file, matchit.txt .
|
|
||||||
|
|
||||||
" Credits:
|
|
||||||
" Vim editor by Bram Moolenaar (Thanks, Bram!)
|
|
||||||
" Original script and design by Raul Segura Acevedo
|
|
||||||
" Support for comments by Douglas Potts
|
|
||||||
" Support for back references and other improvements by Benji Fisher
|
|
||||||
" Support for many languages by Johannes Zellner
|
|
||||||
" Suggestions for improvement, bug reports, and support for additional
|
|
||||||
" languages by Jordi-Albert Batalla, Neil Bird, Servatius Brandt, Mark
|
|
||||||
" Collett, Stephen Wall, Dany St-Amant, Yuheng Xie, and Johannes Zellner.
|
|
||||||
|
|
||||||
" Debugging:
|
|
||||||
" If you'd like to try the built-in debugging commands...
|
|
||||||
" :MatchDebug to activate debugging for the current buffer
|
|
||||||
" This saves the values of several key script variables as buffer-local
|
|
||||||
" variables. See the MatchDebug() function, below, for details.
|
|
||||||
|
|
||||||
" TODO: I should think about multi-line patterns for b:match_words.
|
|
||||||
" This would require an option: how many lines to scan (default 1).
|
|
||||||
" This would be useful for Python, maybe also for *ML.
|
|
||||||
" TODO: Maybe I should add a menu so that people will actually use some of
|
|
||||||
" the features that I have implemented.
|
|
||||||
" TODO: Eliminate the MultiMatch function. Add yet another argument to
|
|
||||||
" Match_wrapper() instead.
|
|
||||||
" TODO: Allow :let b:match_words = '\(\(foo\)\(bar\)\):\3\2:end\1'
|
|
||||||
" TODO: Make backrefs safer by using '\V' (very no-magic).
|
|
||||||
" TODO: Add a level of indirection, so that custom % scripts can use my
|
|
||||||
" work but extend it.
|
|
||||||
|
|
||||||
" allow user to prevent loading
|
|
||||||
" and prevent duplicate loading
|
|
||||||
if exists("loaded_matchit") || &cp
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let loaded_matchit = 1
|
|
||||||
let s:last_mps = ""
|
|
||||||
let s:last_words = ":"
|
|
||||||
|
|
||||||
let s:save_cpo = &cpo
|
|
||||||
set cpo&vim
|
|
||||||
|
|
||||||
nnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'n') <CR>
|
|
||||||
nnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'n') <CR>
|
|
||||||
vnoremap <silent> % :<C-U>call <SID>Match_wrapper('',1,'v') <CR>m'gv``
|
|
||||||
vnoremap <silent> g% :<C-U>call <SID>Match_wrapper('',0,'v') <CR>m'gv``
|
|
||||||
onoremap <silent> % v:<C-U>call <SID>Match_wrapper('',1,'o') <CR>
|
|
||||||
onoremap <silent> g% v:<C-U>call <SID>Match_wrapper('',0,'o') <CR>
|
|
||||||
|
|
||||||
" Analogues of [{ and ]} using matching patterns:
|
|
||||||
nnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "n") <CR>
|
|
||||||
nnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "n") <CR>
|
|
||||||
vmap [% <Esc>[%m'gv``
|
|
||||||
vmap ]% <Esc>]%m'gv``
|
|
||||||
" vnoremap <silent> [% :<C-U>call <SID>MultiMatch("bW", "v") <CR>m'gv``
|
|
||||||
" vnoremap <silent> ]% :<C-U>call <SID>MultiMatch("W", "v") <CR>m'gv``
|
|
||||||
onoremap <silent> [% v:<C-U>call <SID>MultiMatch("bW", "o") <CR>
|
|
||||||
onoremap <silent> ]% v:<C-U>call <SID>MultiMatch("W", "o") <CR>
|
|
||||||
|
|
||||||
" text object:
|
|
||||||
vmap a% <Esc>[%v]%
|
|
||||||
|
|
||||||
" Auto-complete mappings: (not yet "ready for prime time")
|
|
||||||
" TODO Read :help write-plugin for the "right" way to let the user
|
|
||||||
" specify a key binding.
|
|
||||||
" let g:match_auto = '<C-]>'
|
|
||||||
" let g:match_autoCR = '<C-CR>'
|
|
||||||
" if exists("g:match_auto")
|
|
||||||
" execute "inoremap " . g:match_auto . ' x<Esc>"=<SID>Autocomplete()<CR>Pls'
|
|
||||||
" endif
|
|
||||||
" if exists("g:match_autoCR")
|
|
||||||
" execute "inoremap " . g:match_autoCR . ' <CR><C-R>=<SID>Autocomplete()<CR>'
|
|
||||||
" endif
|
|
||||||
" if exists("g:match_gthhoh")
|
|
||||||
" execute "inoremap " . g:match_gthhoh . ' <C-O>:call <SID>Gthhoh()<CR>'
|
|
||||||
" endif " gthhoh = "Get the heck out of here!"
|
|
||||||
|
|
||||||
let s:notslash = '\\\@<!\%(\\\\\)*'
|
|
||||||
|
|
||||||
function! s:Match_wrapper(word, forward, mode) range
|
|
||||||
" In s:CleanUp(), :execute "set" restore_options .
|
|
||||||
let restore_options = (&ic ? " " : " no") . "ignorecase"
|
|
||||||
if exists("b:match_ignorecase")
|
|
||||||
let &ignorecase = b:match_ignorecase
|
|
||||||
endif
|
|
||||||
let restore_options = " ve=" . &ve . restore_options
|
|
||||||
set ve=
|
|
||||||
" If this function was called from Visual mode, make sure that the cursor
|
|
||||||
" is at the correct end of the Visual range:
|
|
||||||
if a:mode == "v"
|
|
||||||
execute "normal! gv\<Esc>"
|
|
||||||
endif
|
|
||||||
" In s:CleanUp(), we may need to check whether the cursor moved forward.
|
|
||||||
let startline = line(".")
|
|
||||||
let startcol = col(".")
|
|
||||||
" Use default behavior if called with a count.
|
|
||||||
if v:count
|
|
||||||
exe "normal! " . v:count . "%"
|
|
||||||
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
|
||||||
end
|
|
||||||
|
|
||||||
" First step: if not already done, set the script variables
|
|
||||||
" s:do_BR flag for whether there are backrefs
|
|
||||||
" s:pat parsed version of b:match_words
|
|
||||||
" s:all regexp based on s:pat and the default groups
|
|
||||||
"
|
|
||||||
if !exists("b:match_words") || b:match_words == ""
|
|
||||||
let match_words = ""
|
|
||||||
" Allow b:match_words = "GetVimMatchWords()" .
|
|
||||||
elseif b:match_words =~ ":"
|
|
||||||
let match_words = b:match_words
|
|
||||||
else
|
|
||||||
execute "let match_words =" b:match_words
|
|
||||||
endif
|
|
||||||
" Thanks to Preben "Peppe" Guldberg and Bram Moolenaar for this suggestion!
|
|
||||||
if (match_words != s:last_words) || (&mps != s:last_mps) ||
|
|
||||||
\ exists("b:match_debug")
|
|
||||||
let s:last_words = match_words
|
|
||||||
let s:last_mps = &mps
|
|
||||||
" The next several lines were here before
|
|
||||||
" BF started messing with this script.
|
|
||||||
" quote the special chars in 'matchpairs', replace [,:] with \| and then
|
|
||||||
" append the builtin pairs (/*, */, #if, #ifdef, #else, #elif, #endif)
|
|
||||||
" let default = substitute(escape(&mps, '[$^.*~\\/?]'), '[,:]\+',
|
|
||||||
" \ '\\|', 'g').'\|\/\*\|\*\/\|#if\>\|#ifdef\>\|#else\>\|#elif\>\|#endif\>'
|
|
||||||
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
|
|
||||||
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
|
|
||||||
" s:all = pattern with all the keywords
|
|
||||||
let match_words = match_words . (strlen(match_words) ? "," : "") . default
|
|
||||||
if match_words !~ s:notslash . '\\\d'
|
|
||||||
let s:do_BR = 0
|
|
||||||
let s:pat = match_words
|
|
||||||
else
|
|
||||||
let s:do_BR = 1
|
|
||||||
let s:pat = s:ParseWords(match_words)
|
|
||||||
endif
|
|
||||||
let s:all = substitute(s:pat, s:notslash . '\zs[,:]\+', '\\|', 'g')
|
|
||||||
let s:all = '\%(' . s:all . '\)'
|
|
||||||
" let s:all = '\%(' . substitute(s:all, '\\\ze[,:]', '', 'g') . '\)'
|
|
||||||
if exists("b:match_debug")
|
|
||||||
let b:match_pat = s:pat
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Second step: set the following local variables:
|
|
||||||
" matchline = line on which the cursor started
|
|
||||||
" curcol = number of characters before match
|
|
||||||
" prefix = regexp for start of line to start of match
|
|
||||||
" suffix = regexp for end of match to end of line
|
|
||||||
" Require match to end on or after the cursor and prefer it to
|
|
||||||
" start on or before the cursor.
|
|
||||||
let matchline = getline(startline)
|
|
||||||
if a:word != ''
|
|
||||||
" word given
|
|
||||||
if a:word !~ s:all
|
|
||||||
echohl WarningMsg|echo 'Missing rule for word:"'.a:word.'"'|echohl NONE
|
|
||||||
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
|
||||||
endif
|
|
||||||
let matchline = a:word
|
|
||||||
let curcol = 0
|
|
||||||
let prefix = '^\%('
|
|
||||||
let suffix = '\)$'
|
|
||||||
" Now the case when "word" is not given
|
|
||||||
else " Find the match that ends on or after the cursor and set curcol.
|
|
||||||
let regexp = s:Wholematch(matchline, s:all, startcol-1)
|
|
||||||
let curcol = match(matchline, regexp)
|
|
||||||
" If there is no match, give up.
|
|
||||||
if curcol == -1
|
|
||||||
return s:CleanUp(restore_options, a:mode, startline, startcol)
|
|
||||||
endif
|
|
||||||
let endcol = matchend(matchline, regexp)
|
|
||||||
let suf = strlen(matchline) - endcol
|
|
||||||
let prefix = (curcol ? '^.*\%' . (curcol + 1) . 'c\%(' : '^\%(')
|
|
||||||
let suffix = (suf ? '\)\%' . (endcol + 1) . 'c.*$' : '\)$')
|
|
||||||
endif
|
|
||||||
if exists("b:match_debug")
|
|
||||||
let b:match_match = matchstr(matchline, regexp)
|
|
||||||
let b:match_col = curcol+1
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Third step: Find the group and single word that match, and the original
|
|
||||||
" (backref) versions of these. Then, resolve the backrefs.
|
|
||||||
" Set the following local variable:
|
|
||||||
" group = colon-separated list of patterns, one of which matches
|
|
||||||
" = ini:mid:fin or ini:fin
|
|
||||||
"
|
|
||||||
" Reconstruct the version with unresolved backrefs.
|
|
||||||
let patBR = substitute(match_words.',',
|
|
||||||
\ s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
|
|
||||||
let patBR = substitute(patBR, s:notslash.'\zs:\{2,}', ':', 'g')
|
|
||||||
" Now, set group and groupBR to the matching group: 'if:endif' or
|
|
||||||
" 'while:endwhile' or whatever. A bit of a kluge: s:Choose() returns
|
|
||||||
" group . "," . groupBR, and we pick it apart.
|
|
||||||
let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
|
|
||||||
let i = matchend(group, s:notslash . ",")
|
|
||||||
let groupBR = strpart(group, i)
|
|
||||||
let group = strpart(group, 0, i-1)
|
|
||||||
" Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
|
|
||||||
if s:do_BR " Do the hard part: resolve those backrefs!
|
|
||||||
let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
|
||||||
endif
|
|
||||||
if exists("b:match_debug")
|
|
||||||
let b:match_wholeBR = groupBR
|
|
||||||
let i = matchend(groupBR, s:notslash . ":")
|
|
||||||
let b:match_iniBR = strpart(groupBR, 0, i-1)
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Fourth step: Set the arguments for searchpair().
|
|
||||||
let i = matchend(group, s:notslash . ":")
|
|
||||||
let j = matchend(group, '.*' . s:notslash . ":")
|
|
||||||
let ini = strpart(group, 0, i-1)
|
|
||||||
let mid = substitute(strpart(group, i,j-i-1), s:notslash.'\zs:', '\\|', 'g')
|
|
||||||
let fin = strpart(group, j)
|
|
||||||
"Un-escape the remaining , and : characters.
|
|
||||||
let ini = substitute(ini, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
|
||||||
let mid = substitute(mid, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
|
||||||
let fin = substitute(fin, s:notslash . '\zs\\\(:\|,\)', '\1', 'g')
|
|
||||||
" searchpair() requires that these patterns avoid \(\) groups.
|
|
||||||
let ini = substitute(ini, s:notslash . '\zs\\(', '\\%(', 'g')
|
|
||||||
let mid = substitute(mid, s:notslash . '\zs\\(', '\\%(', 'g')
|
|
||||||
let fin = substitute(fin, s:notslash . '\zs\\(', '\\%(', 'g')
|
|
||||||
" Set mid. This is optimized for readability, not micro-efficiency!
|
|
||||||
if a:forward && matchline =~ prefix . fin . suffix
|
|
||||||
\ || !a:forward && matchline =~ prefix . ini . suffix
|
|
||||||
let mid = ""
|
|
||||||
endif
|
|
||||||
" Set flag. This is optimized for readability, not micro-efficiency!
|
|
||||||
if a:forward && matchline =~ prefix . fin . suffix
|
|
||||||
\ || !a:forward && matchline !~ prefix . ini . suffix
|
|
||||||
let flag = "bW"
|
|
||||||
else
|
|
||||||
let flag = "W"
|
|
||||||
endif
|
|
||||||
" Set skip.
|
|
||||||
if exists("b:match_skip")
|
|
||||||
let skip = b:match_skip
|
|
||||||
elseif exists("b:match_comment") " backwards compatibility and testing!
|
|
||||||
let skip = "r:" . b:match_comment
|
|
||||||
else
|
|
||||||
let skip = 's:comment\|string'
|
|
||||||
endif
|
|
||||||
let skip = s:ParseSkip(skip)
|
|
||||||
if exists("b:match_debug")
|
|
||||||
let b:match_ini = ini
|
|
||||||
let b:match_tail = (strlen(mid) ? mid.'\|' : '') . fin
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Fifth step: actually start moving the cursor and call searchpair().
|
|
||||||
" Later, :execute restore_cursor to get to the original screen.
|
|
||||||
let restore_cursor = virtcol(".") . "|"
|
|
||||||
normal! g0
|
|
||||||
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
|
|
||||||
normal! H
|
|
||||||
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
|
||||||
execute restore_cursor
|
|
||||||
call cursor(0, curcol + 1)
|
|
||||||
" normal! 0
|
|
||||||
" if curcol
|
|
||||||
" execute "normal!" . curcol . "l"
|
|
||||||
" endif
|
|
||||||
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
|
|
||||||
let skip = "0"
|
|
||||||
else
|
|
||||||
execute "if " . skip . "| let skip = '0' | endif"
|
|
||||||
endif
|
|
||||||
let sp_return = searchpair(ini, mid, fin, flag, skip)
|
|
||||||
let final_position = "call cursor(" . line(".") . "," . col(".") . ")"
|
|
||||||
" Restore cursor position and original screen.
|
|
||||||
execute restore_cursor
|
|
||||||
normal! m'
|
|
||||||
if sp_return > 0
|
|
||||||
execute final_position
|
|
||||||
endif
|
|
||||||
return s:CleanUp(restore_options, a:mode, startline, startcol, mid.'\|'.fin)
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Restore options and do some special handling for Operator-pending mode.
|
|
||||||
" The optional argument is the tail of the matching group.
|
|
||||||
fun! s:CleanUp(options, mode, startline, startcol, ...)
|
|
||||||
execute "set" a:options
|
|
||||||
" Open folds, if appropriate.
|
|
||||||
if a:mode != "o"
|
|
||||||
if &foldopen =~ "percent"
|
|
||||||
normal! zv
|
|
||||||
endif
|
|
||||||
" In Operator-pending mode, we want to include the whole match
|
|
||||||
" (for example, d%).
|
|
||||||
" This is only a problem if we end up moving in the forward direction.
|
|
||||||
elseif (a:startline < line(".")) ||
|
|
||||||
\ (a:startline == line(".") && a:startcol < col("."))
|
|
||||||
if a:0
|
|
||||||
" Check whether the match is a single character. If not, move to the
|
|
||||||
" end of the match.
|
|
||||||
let matchline = getline(".")
|
|
||||||
let currcol = col(".")
|
|
||||||
let regexp = s:Wholematch(matchline, a:1, currcol-1)
|
|
||||||
let endcol = matchend(matchline, regexp)
|
|
||||||
if endcol > currcol " This is NOT off by one!
|
|
||||||
execute "normal!" . (endcol - currcol) . "l"
|
|
||||||
endif
|
|
||||||
endif " a:0
|
|
||||||
endif " a:mode != "o" && etc.
|
|
||||||
return 0
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Example (simplified HTML patterns): if
|
|
||||||
" a:groupBR = '<\(\k\+\)>:</\1>'
|
|
||||||
" a:prefix = '^.\{3}\('
|
|
||||||
" a:group = '<\(\k\+\)>:</\(\k\+\)>'
|
|
||||||
" a:suffix = '\).\{2}$'
|
|
||||||
" a:matchline = "123<tag>12" or "123</tag>12"
|
|
||||||
" then extract "tag" from a:matchline and return "<tag>:</tag>" .
|
|
||||||
fun! s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
|
||||||
if a:matchline !~ a:prefix .
|
|
||||||
\ substitute(a:group, s:notslash . '\zs:', '\\|', 'g') . a:suffix
|
|
||||||
return a:group
|
|
||||||
endif
|
|
||||||
let i = matchend(a:groupBR, s:notslash . ':')
|
|
||||||
let ini = strpart(a:groupBR, 0, i-1)
|
|
||||||
let tailBR = strpart(a:groupBR, i)
|
|
||||||
let word = s:Choose(a:group, a:matchline, ":", "", a:prefix, a:suffix,
|
|
||||||
\ a:groupBR)
|
|
||||||
let i = matchend(word, s:notslash . ":")
|
|
||||||
let wordBR = strpart(word, i)
|
|
||||||
let word = strpart(word, 0, i-1)
|
|
||||||
" Now, a:matchline =~ a:prefix . word . a:suffix
|
|
||||||
if wordBR != ini
|
|
||||||
let table = s:Resolve(ini, wordBR, "table")
|
|
||||||
else
|
|
||||||
" let table = "----------"
|
|
||||||
let table = ""
|
|
||||||
let d = 0
|
|
||||||
while d < 10
|
|
||||||
if tailBR =~ s:notslash . '\\' . d
|
|
||||||
" let table[d] = d
|
|
||||||
let table = table . d
|
|
||||||
else
|
|
||||||
let table = table . "-"
|
|
||||||
endif
|
|
||||||
let d = d + 1
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
let d = 9
|
|
||||||
while d
|
|
||||||
if table[d] != "-"
|
|
||||||
let backref = substitute(a:matchline, a:prefix.word.a:suffix,
|
|
||||||
\ '\'.table[d], "")
|
|
||||||
" Are there any other characters that should be escaped?
|
|
||||||
let backref = escape(backref, '*,:')
|
|
||||||
execute s:Ref(ini, d, "start", "len")
|
|
||||||
let ini = strpart(ini, 0, start) . backref . strpart(ini, start+len)
|
|
||||||
let tailBR = substitute(tailBR, s:notslash . '\zs\\' . d,
|
|
||||||
\ escape(backref, '\\'), 'g')
|
|
||||||
endif
|
|
||||||
let d = d-1
|
|
||||||
endwhile
|
|
||||||
if exists("b:match_debug")
|
|
||||||
if s:do_BR
|
|
||||||
let b:match_table = table
|
|
||||||
let b:match_word = word
|
|
||||||
else
|
|
||||||
let b:match_table = ""
|
|
||||||
let b:match_word = ""
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return ini . ":" . tailBR
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Input a comma-separated list of groups with backrefs, such as
|
|
||||||
" a:groups = '\(foo\):end\1,\(bar\):end\1'
|
|
||||||
" and return a comma-separated list of groups with backrefs replaced:
|
|
||||||
" return '\(foo\):end\(foo\),\(bar\):end\(bar\)'
|
|
||||||
fun! s:ParseWords(groups)
|
|
||||||
let groups = substitute(a:groups.",", s:notslash.'\zs[,:]*,[,:]*', ',', 'g')
|
|
||||||
let groups = substitute(groups, s:notslash . '\zs:\{2,}', ':', 'g')
|
|
||||||
let parsed = ""
|
|
||||||
while groups =~ '[^,:]'
|
|
||||||
let i = matchend(groups, s:notslash . ':')
|
|
||||||
let j = matchend(groups, s:notslash . ',')
|
|
||||||
let ini = strpart(groups, 0, i-1)
|
|
||||||
let tail = strpart(groups, i, j-i-1) . ":"
|
|
||||||
let groups = strpart(groups, j)
|
|
||||||
let parsed = parsed . ini
|
|
||||||
let i = matchend(tail, s:notslash . ':')
|
|
||||||
while i != -1
|
|
||||||
" In 'if:else:endif', ini='if' and word='else' and then word='endif'.
|
|
||||||
let word = strpart(tail, 0, i-1)
|
|
||||||
let tail = strpart(tail, i)
|
|
||||||
let i = matchend(tail, s:notslash . ':')
|
|
||||||
let parsed = parsed . ":" . s:Resolve(ini, word, "word")
|
|
||||||
endwhile " Now, tail has been used up.
|
|
||||||
let parsed = parsed . ","
|
|
||||||
endwhile " groups =~ '[^,:]'
|
|
||||||
let parsed = substitute(parsed, ',$', '', '')
|
|
||||||
return parsed
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" TODO I think this can be simplified and/or made more efficient.
|
|
||||||
" TODO What should I do if a:start is out of range?
|
|
||||||
" Return a regexp that matches all of a:string, such that
|
|
||||||
" matchstr(a:string, regexp) represents the match for a:pat that starts
|
|
||||||
" as close to a:start as possible, before being preferred to after, and
|
|
||||||
" ends after a:start .
|
|
||||||
" Usage:
|
|
||||||
" let regexp = s:Wholematch(getline("."), 'foo\|bar', col(".")-1)
|
|
||||||
" let i = match(getline("."), regexp)
|
|
||||||
" let j = matchend(getline("."), regexp)
|
|
||||||
" let match = matchstr(getline("."), regexp)
|
|
||||||
fun! s:Wholematch(string, pat, start)
|
|
||||||
let group = '\%(' . a:pat . '\)'
|
|
||||||
let prefix = (a:start ? '\(^.*\%<' . (a:start + 2) . 'c\)\zs' : '^')
|
|
||||||
let len = strlen(a:string)
|
|
||||||
let suffix = (a:start+1 < len ? '\(\%>'.(a:start+1).'c.*$\)\@=' : '$')
|
|
||||||
if a:string !~ prefix . group . suffix
|
|
||||||
let prefix = ''
|
|
||||||
endif
|
|
||||||
return prefix . group . suffix
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" No extra arguments: s:Ref(string, d) will
|
|
||||||
" find the d'th occurrence of '\(' and return it, along with everything up
|
|
||||||
" to and including the matching '\)'.
|
|
||||||
" One argument: s:Ref(string, d, "start") returns the index of the start
|
|
||||||
" of the d'th '\(' and any other argument returns the length of the group.
|
|
||||||
" Two arguments: s:Ref(string, d, "foo", "bar") returns a string to be
|
|
||||||
" executed, having the effect of
|
|
||||||
" :let foo = s:Ref(string, d, "start")
|
|
||||||
" :let bar = s:Ref(string, d, "len")
|
|
||||||
fun! s:Ref(string, d, ...)
|
|
||||||
let len = strlen(a:string)
|
|
||||||
if a:d == 0
|
|
||||||
let start = 0
|
|
||||||
else
|
|
||||||
let cnt = a:d
|
|
||||||
let match = a:string
|
|
||||||
while cnt
|
|
||||||
let cnt = cnt - 1
|
|
||||||
let index = matchend(match, s:notslash . '\\(')
|
|
||||||
if index == -1
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
let match = strpart(match, index)
|
|
||||||
endwhile
|
|
||||||
let start = len - strlen(match)
|
|
||||||
if a:0 == 1 && a:1 == "start"
|
|
||||||
return start - 2
|
|
||||||
endif
|
|
||||||
let cnt = 1
|
|
||||||
while cnt
|
|
||||||
let index = matchend(match, s:notslash . '\\(\|\\)') - 1
|
|
||||||
if index == -2
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
" Increment if an open, decrement if a ')':
|
|
||||||
let cnt = cnt + (match[index]=="(" ? 1 : -1) " ')'
|
|
||||||
" let cnt = stridx('0(', match[index]) + cnt
|
|
||||||
let match = strpart(match, index+1)
|
|
||||||
endwhile
|
|
||||||
let start = start - 2
|
|
||||||
let len = len - start - strlen(match)
|
|
||||||
endif
|
|
||||||
if a:0 == 1
|
|
||||||
return len
|
|
||||||
elseif a:0 == 2
|
|
||||||
return "let " . a:1 . "=" . start . "| let " . a:2 . "=" . len
|
|
||||||
else
|
|
||||||
return strpart(a:string, start, len)
|
|
||||||
endif
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Count the number of disjoint copies of pattern in string.
|
|
||||||
" If the pattern is a literal string and contains no '0' or '1' characters
|
|
||||||
" then s:Count(string, pattern, '0', '1') should be faster than
|
|
||||||
" s:Count(string, pattern).
|
|
||||||
fun! s:Count(string, pattern, ...)
|
|
||||||
let pat = escape(a:pattern, '\\')
|
|
||||||
if a:0 > 1
|
|
||||||
let foo = substitute(a:string, '[^'.a:pattern.']', "a:1", "g")
|
|
||||||
let foo = substitute(a:string, pat, a:2, "g")
|
|
||||||
let foo = substitute(foo, '[^' . a:2 . ']', "", "g")
|
|
||||||
return strlen(foo)
|
|
||||||
endif
|
|
||||||
let result = 0
|
|
||||||
let foo = a:string
|
|
||||||
let index = matchend(foo, pat)
|
|
||||||
while index != -1
|
|
||||||
let result = result + 1
|
|
||||||
let foo = strpart(foo, index)
|
|
||||||
let index = matchend(foo, pat)
|
|
||||||
endwhile
|
|
||||||
return result
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" s:Resolve('\(a\)\(b\)', '\(c\)\2\1\1\2') should return table.word, where
|
|
||||||
" word = '\(c\)\(b\)\(a\)\3\2' and table = '-32-------'. That is, the first
|
|
||||||
" '\1' in target is replaced by '\(a\)' in word, table[1] = 3, and this
|
|
||||||
" indicates that all other instances of '\1' in target are to be replaced
|
|
||||||
" by '\3'. The hard part is dealing with nesting...
|
|
||||||
" Note that ":" is an illegal character for source and target,
|
|
||||||
" unless it is preceded by "\".
|
|
||||||
fun! s:Resolve(source, target, output)
|
|
||||||
let word = a:target
|
|
||||||
let i = matchend(word, s:notslash . '\\\d') - 1
|
|
||||||
let table = "----------"
|
|
||||||
while i != -2 " There are back references to be replaced.
|
|
||||||
let d = word[i]
|
|
||||||
let backref = s:Ref(a:source, d)
|
|
||||||
" The idea is to replace '\d' with backref. Before we do this,
|
|
||||||
" replace any \(\) groups in backref with :1, :2, ... if they
|
|
||||||
" correspond to the first, second, ... group already inserted
|
|
||||||
" into backref. Later, replace :1 with \1 and so on. The group
|
|
||||||
" number w+b within backref corresponds to the group number
|
|
||||||
" s within a:source.
|
|
||||||
" w = number of '\(' in word before the current one
|
|
||||||
let w = s:Count(
|
|
||||||
\ substitute(strpart(word, 0, i-1), '\\\\', '', 'g'), '\(', '1')
|
|
||||||
let b = 1 " number of the current '\(' in backref
|
|
||||||
let s = d " number of the current '\(' in a:source
|
|
||||||
while b <= s:Count(substitute(backref, '\\\\', '', 'g'), '\(', '1')
|
|
||||||
\ && s < 10
|
|
||||||
if table[s] == "-"
|
|
||||||
if w + b < 10
|
|
||||||
" let table[s] = w + b
|
|
||||||
let table = strpart(table, 0, s) . (w+b) . strpart(table, s+1)
|
|
||||||
endif
|
|
||||||
let b = b + 1
|
|
||||||
let s = s + 1
|
|
||||||
else
|
|
||||||
execute s:Ref(backref, b, "start", "len")
|
|
||||||
let ref = strpart(backref, start, len)
|
|
||||||
let backref = strpart(backref, 0, start) . ":". table[s]
|
|
||||||
\ . strpart(backref, start+len)
|
|
||||||
let s = s + s:Count(substitute(ref, '\\\\', '', 'g'), '\(', '1')
|
|
||||||
endif
|
|
||||||
endwhile
|
|
||||||
let word = strpart(word, 0, i-1) . backref . strpart(word, i+1)
|
|
||||||
let i = matchend(word, s:notslash . '\\\d') - 1
|
|
||||||
endwhile
|
|
||||||
let word = substitute(word, s:notslash . '\zs:', '\\', 'g')
|
|
||||||
if a:output == "table"
|
|
||||||
return table
|
|
||||||
elseif a:output == "word"
|
|
||||||
return word
|
|
||||||
else
|
|
||||||
return table . word
|
|
||||||
endif
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Assume a:comma = ",". Then the format for a:patterns and a:1 is
|
|
||||||
" a:patterns = "<pat1>,<pat2>,..."
|
|
||||||
" a:1 = "<alt1>,<alt2>,..."
|
|
||||||
" If <patn> is the first pattern that matches a:string then return <patn>
|
|
||||||
" if no optional arguments are given; return <patn>,<altn> if a:1 is given.
|
|
||||||
fun! s:Choose(patterns, string, comma, branch, prefix, suffix, ...)
|
|
||||||
let tail = (a:patterns =~ a:comma."$" ? a:patterns : a:patterns . a:comma)
|
|
||||||
let i = matchend(tail, s:notslash . a:comma)
|
|
||||||
if a:0
|
|
||||||
let alttail = (a:1 =~ a:comma."$" ? a:1 : a:1 . a:comma)
|
|
||||||
let j = matchend(alttail, s:notslash . a:comma)
|
|
||||||
endif
|
|
||||||
let current = strpart(tail, 0, i-1)
|
|
||||||
if a:branch == ""
|
|
||||||
let currpat = current
|
|
||||||
else
|
|
||||||
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
|
|
||||||
endif
|
|
||||||
while a:string !~ a:prefix . currpat . a:suffix
|
|
||||||
let tail = strpart(tail, i)
|
|
||||||
let i = matchend(tail, s:notslash . a:comma)
|
|
||||||
if i == -1
|
|
||||||
return -1
|
|
||||||
endif
|
|
||||||
let current = strpart(tail, 0, i-1)
|
|
||||||
if a:branch == ""
|
|
||||||
let currpat = current
|
|
||||||
else
|
|
||||||
let currpat = substitute(current, s:notslash . a:branch, '\\|', 'g')
|
|
||||||
endif
|
|
||||||
if a:0
|
|
||||||
let alttail = strpart(alttail, j)
|
|
||||||
let j = matchend(alttail, s:notslash . a:comma)
|
|
||||||
endif
|
|
||||||
endwhile
|
|
||||||
if a:0
|
|
||||||
let current = current . a:comma . strpart(alttail, 0, j-1)
|
|
||||||
endif
|
|
||||||
return current
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Call this function to turn on debugging information. Every time the main
|
|
||||||
" script is run, buffer variables will be saved. These can be used directly
|
|
||||||
" or viewed using the menu items below.
|
|
||||||
if !exists(":MatchDebug")
|
|
||||||
command! -nargs=0 MatchDebug call s:Match_debug()
|
|
||||||
endif
|
|
||||||
|
|
||||||
fun! s:Match_debug()
|
|
||||||
let b:match_debug = 1 " Save debugging information.
|
|
||||||
" pat = all of b:match_words with backrefs parsed
|
|
||||||
amenu &Matchit.&pat :echo b:match_pat<CR>
|
|
||||||
" match = bit of text that is recognized as a match
|
|
||||||
amenu &Matchit.&match :echo b:match_match<CR>
|
|
||||||
" curcol = cursor column of the start of the matching text
|
|
||||||
amenu &Matchit.&curcol :echo b:match_col<CR>
|
|
||||||
" wholeBR = matching group, original version
|
|
||||||
amenu &Matchit.wh&oleBR :echo b:match_wholeBR<CR>
|
|
||||||
" iniBR = 'if' piece, original version
|
|
||||||
amenu &Matchit.ini&BR :echo b:match_iniBR<CR>
|
|
||||||
" ini = 'if' piece, with all backrefs resolved from match
|
|
||||||
amenu &Matchit.&ini :echo b:match_ini<CR>
|
|
||||||
" tail = 'else\|endif' piece, with all backrefs resolved from match
|
|
||||||
amenu &Matchit.&tail :echo b:match_tail<CR>
|
|
||||||
" fin = 'endif' piece, with all backrefs resolved from match
|
|
||||||
amenu &Matchit.&word :echo b:match_word<CR>
|
|
||||||
" '\'.d in ini refers to the same thing as '\'.table[d] in word.
|
|
||||||
amenu &Matchit.t&able :echo '0:' . b:match_table . ':9'<CR>
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Jump to the nearest unmatched "(" or "if" or "<tag>" if a:spflag == "bW"
|
|
||||||
" or the nearest unmatched "</tag>" or "endif" or ")" if a:spflag == "W".
|
|
||||||
" Return a "mark" for the original position, so that
|
|
||||||
" let m = MultiMatch("bW", "n") ... execute m
|
|
||||||
" will return to the original position. If there is a problem, do not
|
|
||||||
" move the cursor and return "", unless a count is given, in which case
|
|
||||||
" go up or down as many levels as possible and again return "".
|
|
||||||
" TODO This relies on the same patterns as % matching. It might be a good
|
|
||||||
" idea to give it its own matching patterns.
|
|
||||||
fun! s:MultiMatch(spflag, mode)
|
|
||||||
if !exists("b:match_words") || b:match_words == ""
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
let restore_options = (&ic ? "" : "no") . "ignorecase"
|
|
||||||
if exists("b:match_ignorecase")
|
|
||||||
let &ignorecase = b:match_ignorecase
|
|
||||||
endif
|
|
||||||
let startline = line(".")
|
|
||||||
let startcol = col(".")
|
|
||||||
|
|
||||||
" First step: if not already done, set the script variables
|
|
||||||
" s:do_BR flag for whether there are backrefs
|
|
||||||
" s:pat parsed version of b:match_words
|
|
||||||
" s:all regexp based on s:pat and the default groups
|
|
||||||
" This part is copied and slightly modified from s:Match_wrapper().
|
|
||||||
let default = escape(&mps, '[$^.*~\\/?]') . (strlen(&mps) ? "," : "") .
|
|
||||||
\ '\/\*:\*\/,#if\%(def\)\=:#else\>:#elif\>:#endif\>'
|
|
||||||
" Allow b:match_words = "GetVimMatchWords()" .
|
|
||||||
if b:match_words =~ ":"
|
|
||||||
let match_words = b:match_words
|
|
||||||
else
|
|
||||||
execute "let match_words =" b:match_words
|
|
||||||
endif
|
|
||||||
if (match_words != s:last_words) || (&mps != s:last_mps) ||
|
|
||||||
\ exists("b:match_debug")
|
|
||||||
let s:last_words = match_words
|
|
||||||
let s:last_mps = &mps
|
|
||||||
if match_words !~ s:notslash . '\\\d'
|
|
||||||
let s:do_BR = 0
|
|
||||||
let s:pat = match_words
|
|
||||||
else
|
|
||||||
let s:do_BR = 1
|
|
||||||
let s:pat = s:ParseWords(match_words)
|
|
||||||
endif
|
|
||||||
let s:all = '\%(' . substitute(s:pat . (strlen(s:pat)?",":"") . default,
|
|
||||||
\ '[,:]\+','\\|','g') . '\)'
|
|
||||||
if exists("b:match_debug")
|
|
||||||
let b:match_pat = s:pat
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Second step: figure out the patterns for searchpair()
|
|
||||||
" and save the screen, cursor position, and 'ignorecase'.
|
|
||||||
" - TODO: A lot of this is copied from s:Match_wrapper().
|
|
||||||
" - maybe even more functionality should be split off
|
|
||||||
" - into separate functions!
|
|
||||||
let cdefault = (s:pat =~ '[^,]$' ? "," : "") . default
|
|
||||||
let open = substitute(s:pat . cdefault,
|
|
||||||
\ s:notslash . '\zs:.\{-}' . s:notslash . ',', '\\),\\(', 'g')
|
|
||||||
let open = '\(' . substitute(open, s:notslash . '\zs:.*$', '\\)', '')
|
|
||||||
let close = substitute(s:pat . cdefault,
|
|
||||||
\ s:notslash . '\zs,.\{-}' . s:notslash . ':', '\\),\\(', 'g')
|
|
||||||
let close = substitute(close, '^.\{-}' . s:notslash . ':', '\\(', '') . '\)'
|
|
||||||
if exists("b:match_skip")
|
|
||||||
let skip = b:match_skip
|
|
||||||
elseif exists("b:match_comment") " backwards compatibility and testing!
|
|
||||||
let skip = "r:" . b:match_comment
|
|
||||||
else
|
|
||||||
let skip = 's:comment\|string'
|
|
||||||
endif
|
|
||||||
let skip = s:ParseSkip(skip)
|
|
||||||
" let restore_cursor = line(".") . "G" . virtcol(".") . "|"
|
|
||||||
" normal! H
|
|
||||||
" let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
|
||||||
let restore_cursor = virtcol(".") . "|"
|
|
||||||
normal! g0
|
|
||||||
let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor
|
|
||||||
normal! H
|
|
||||||
let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor
|
|
||||||
execute restore_cursor
|
|
||||||
|
|
||||||
" Third step: call searchpair().
|
|
||||||
" Replace '\('--but not '\\('--with '\%(' and ',' with '\|'.
|
|
||||||
let openpat = substitute(open, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
|
|
||||||
let openpat = substitute(openpat, ',', '\\|', 'g')
|
|
||||||
let closepat = substitute(close, '\(\\\@<!\(\\\\\)*\)\@<=\\(', '\\%(', 'g')
|
|
||||||
let closepat = substitute(closepat, ',', '\\|', 'g')
|
|
||||||
if skip =~ 'synID' && !(has("syntax") && exists("g:syntax_on"))
|
|
||||||
let skip = '0'
|
|
||||||
else
|
|
||||||
execute "if " . skip . "| let skip = '0' | endif"
|
|
||||||
endif
|
|
||||||
mark '
|
|
||||||
let level = v:count1
|
|
||||||
while level
|
|
||||||
if searchpair(openpat, '', closepat, a:spflag, skip) < 1
|
|
||||||
call s:CleanUp(restore_options, a:mode, startline, startcol)
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
let level = level - 1
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
" Restore options and return a string to restore the original position.
|
|
||||||
call s:CleanUp(restore_options, a:mode, startline, startcol)
|
|
||||||
return restore_cursor
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" Search backwards for "if" or "while" or "<tag>" or ...
|
|
||||||
" and return "endif" or "endwhile" or "</tag>" or ... .
|
|
||||||
" For now, this uses b:match_words and the same script variables
|
|
||||||
" as s:Match_wrapper() . Later, it may get its own patterns,
|
|
||||||
" either from a buffer variable or passed as arguments.
|
|
||||||
" fun! s:Autocomplete()
|
|
||||||
" echo "autocomplete not yet implemented :-("
|
|
||||||
" if !exists("b:match_words") || b:match_words == ""
|
|
||||||
" return ""
|
|
||||||
" end
|
|
||||||
" let startpos = s:MultiMatch("bW")
|
|
||||||
"
|
|
||||||
" if startpos == ""
|
|
||||||
" return ""
|
|
||||||
" endif
|
|
||||||
" " - TODO: figure out whether 'if' or '<tag>' matched, and construct
|
|
||||||
" " - the appropriate closing.
|
|
||||||
" let matchline = getline(".")
|
|
||||||
" let curcol = col(".") - 1
|
|
||||||
" " - TODO: Change the s:all argument if there is a new set of match pats.
|
|
||||||
" let regexp = s:Wholematch(matchline, s:all, curcol)
|
|
||||||
" let suf = strlen(matchline) - matchend(matchline, regexp)
|
|
||||||
" let prefix = (curcol ? '^.\{' . curcol . '}\%(' : '^\%(')
|
|
||||||
" let suffix = (suf ? '\).\{' . suf . '}$' : '\)$')
|
|
||||||
" " Reconstruct the version with unresolved backrefs.
|
|
||||||
" let patBR = substitute(b:match_words.',', '[,:]*,[,:]*', ',', 'g')
|
|
||||||
" let patBR = substitute(patBR, ':\{2,}', ':', "g")
|
|
||||||
" " Now, set group and groupBR to the matching group: 'if:endif' or
|
|
||||||
" " 'while:endwhile' or whatever.
|
|
||||||
" let group = s:Choose(s:pat, matchline, ",", ":", prefix, suffix, patBR)
|
|
||||||
" let i = matchend(group, s:notslash . ",")
|
|
||||||
" let groupBR = strpart(group, i)
|
|
||||||
" let group = strpart(group, 0, i-1)
|
|
||||||
" " Now, matchline =~ prefix . substitute(group,':','\|','g') . suffix
|
|
||||||
" if s:do_BR
|
|
||||||
" let group = s:InsertRefs(groupBR, prefix, group, suffix, matchline)
|
|
||||||
" endif
|
|
||||||
" " let g:group = group
|
|
||||||
"
|
|
||||||
" " - TODO: Construct the closing from group.
|
|
||||||
" let fake = "end" . expand("<cword>")
|
|
||||||
" execute startpos
|
|
||||||
" return fake
|
|
||||||
" endfun
|
|
||||||
|
|
||||||
" Close all open structures. "Get the heck out of here!"
|
|
||||||
" fun! s:Gthhoh()
|
|
||||||
" let close = s:Autocomplete()
|
|
||||||
" while strlen(close)
|
|
||||||
" put=close
|
|
||||||
" let close = s:Autocomplete()
|
|
||||||
" endwhile
|
|
||||||
" endfun
|
|
||||||
|
|
||||||
" Parse special strings as typical skip arguments for searchpair():
|
|
||||||
" s:foo becomes (current syntax item) =~ foo
|
|
||||||
" S:foo becomes (current syntax item) !~ foo
|
|
||||||
" r:foo becomes (line before cursor) =~ foo
|
|
||||||
" R:foo becomes (line before cursor) !~ foo
|
|
||||||
fun! s:ParseSkip(str)
|
|
||||||
let skip = a:str
|
|
||||||
if skip[1] == ":"
|
|
||||||
if skip[0] == "s"
|
|
||||||
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') =~? '" .
|
|
||||||
\ strpart(skip,2) . "'"
|
|
||||||
elseif skip[0] == "S"
|
|
||||||
let skip = "synIDattr(synID(line('.'),col('.'),1),'name') !~? '" .
|
|
||||||
\ strpart(skip,2) . "'"
|
|
||||||
elseif skip[0] == "r"
|
|
||||||
let skip = "strpart(getline('.'),0,col('.'))=~'" . strpart(skip,2). "'"
|
|
||||||
elseif skip[0] == "R"
|
|
||||||
let skip = "strpart(getline('.'),0,col('.'))!~'" . strpart(skip,2). "'"
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return skip
|
|
||||||
endfun
|
|
||||||
|
|
||||||
let &cpo = s:save_cpo
|
|
||||||
|
|
||||||
" vim:sts=2:sw=2:
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,323 +0,0 @@
|
||||||
" rails.vim - Detect a rails application
|
|
||||||
" Author: Tim Pope <vimNOSPAM@tpope.info>
|
|
||||||
" GetLatestVimScripts: 1567 1 :AutoInstall: rails.vim
|
|
||||||
" URL: http://rails.vim.tpope.net/
|
|
||||||
|
|
||||||
" Install this file as plugin/rails.vim. See doc/rails.txt for details. (Grab
|
|
||||||
" it from the URL above if you don't have it.) To access it from Vim, see
|
|
||||||
" :help add-local-help (hint: :helptags ~/.vim/doc) Afterwards, you should be
|
|
||||||
" able to do :help rails
|
|
||||||
|
|
||||||
" ============================================================================
|
|
||||||
|
|
||||||
" Exit quickly when:
|
|
||||||
" - this plugin was already loaded (or disabled)
|
|
||||||
" - when 'compatible' is set
|
|
||||||
if &cp || (exists("g:loaded_rails") && g:loaded_rails) && !(exists("g:rails_debug") && g:rails_debug)
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_rails = 1
|
|
||||||
|
|
||||||
" Apparently, the nesting level within Vim when the Ruby interface is
|
|
||||||
" initialized determines how much stack space Ruby gets. In previous
|
|
||||||
" versions of rails.vim, sporadic stack overflows occured when omnicomplete
|
|
||||||
" was used. This was apparently due to rails.vim having first initialized
|
|
||||||
" ruby deep in a nested function call.
|
|
||||||
if has("ruby")
|
|
||||||
silent! ruby nil
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Utility Functions {{{1
|
|
||||||
|
|
||||||
function! s:error(str)
|
|
||||||
echohl ErrorMsg
|
|
||||||
echomsg a:str
|
|
||||||
echohl None
|
|
||||||
let v:errmsg = a:str
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:autoload(...)
|
|
||||||
if !exists("g:autoloaded_rails") && v:version >= 700
|
|
||||||
runtime! autoload/rails.vim
|
|
||||||
endif
|
|
||||||
if exists("g:autoloaded_rails")
|
|
||||||
if a:0
|
|
||||||
exe a:1
|
|
||||||
endif
|
|
||||||
return 1
|
|
||||||
endif
|
|
||||||
if !exists("g:rails_no_autoload_warning")
|
|
||||||
let g:rails_no_autoload_warning = 1
|
|
||||||
if v:version >= 700
|
|
||||||
call s:error("Disabling rails.vim: autoload/rails.vim is missing")
|
|
||||||
else
|
|
||||||
call s:error("Disabling rails.vim: Vim version 7 or higher required")
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
return ""
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
" Configuration {{{
|
|
||||||
|
|
||||||
function! s:SetOptDefault(opt,val)
|
|
||||||
if !exists("g:".a:opt)
|
|
||||||
let g:{a:opt} = a:val
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
call s:SetOptDefault("rails_statusline",1)
|
|
||||||
call s:SetOptDefault("rails_syntax",1)
|
|
||||||
call s:SetOptDefault("rails_mappings",1)
|
|
||||||
call s:SetOptDefault("rails_abbreviations",1)
|
|
||||||
call s:SetOptDefault("rails_ctags_arguments","--exclude=\"*.js\"")
|
|
||||||
call s:SetOptDefault("rails_expensive",1)
|
|
||||||
call s:SetOptDefault("rails_dbext",g:rails_expensive)
|
|
||||||
call s:SetOptDefault("rails_default_file","README")
|
|
||||||
call s:SetOptDefault("rails_default_database","")
|
|
||||||
call s:SetOptDefault("rails_root_url",'http://localhost:3000/')
|
|
||||||
call s:SetOptDefault("rails_modelines",0)
|
|
||||||
call s:SetOptDefault("rails_menu",1)
|
|
||||||
call s:SetOptDefault("rails_gnu_screen",1)
|
|
||||||
call s:SetOptDefault("rails_history_size",5)
|
|
||||||
call s:SetOptDefault("rails_generators","controller\nintegration_test\nmailer\nmigration\nmodel\nobserver\nplugin\nresource\nscaffold\nsession_migration")
|
|
||||||
if g:rails_dbext
|
|
||||||
if exists("g:loaded_dbext") && executable("sqlite3") && ! executable("sqlite")
|
|
||||||
" Since dbext can't find it by itself
|
|
||||||
call s:SetOptDefault("dbext_default_SQLITE_bin","sqlite3")
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
" Detection {{{1
|
|
||||||
|
|
||||||
function! s:escvar(r)
|
|
||||||
let r = fnamemodify(a:r,':~')
|
|
||||||
let r = substitute(r,'\W','\="_".char2nr(submatch(0))."_"','g')
|
|
||||||
let r = substitute(r,'^\d','_&','')
|
|
||||||
return r
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:Detect(filename)
|
|
||||||
let fn = substitute(fnamemodify(a:filename,":p"),'\c^file://','','')
|
|
||||||
let sep = matchstr(fn,'^[^\\/]\{3,\}\zs[\\/]')
|
|
||||||
if sep != ""
|
|
||||||
let fn = getcwd().sep.fn
|
|
||||||
endif
|
|
||||||
if fn =~ '[\/]config[\/]environment\.rb$'
|
|
||||||
return s:BufInit(strpart(fn,0,strlen(fn)-22))
|
|
||||||
endif
|
|
||||||
if isdirectory(fn)
|
|
||||||
let fn = fnamemodify(fn,':s?[\/]$??')
|
|
||||||
else
|
|
||||||
let fn = fnamemodify(fn,':s?\(.*\)[\/][^\/]*$?\1?')
|
|
||||||
endif
|
|
||||||
let ofn = ""
|
|
||||||
let nfn = fn
|
|
||||||
while nfn != ofn && nfn != ""
|
|
||||||
if exists("s:_".s:escvar(nfn))
|
|
||||||
return s:BufInit(nfn)
|
|
||||||
endif
|
|
||||||
let ofn = nfn
|
|
||||||
let nfn = fnamemodify(nfn,':h')
|
|
||||||
endwhile
|
|
||||||
let ofn = ""
|
|
||||||
while fn != ofn
|
|
||||||
if filereadable(fn . "/config/environment.rb")
|
|
||||||
return s:BufInit(fn)
|
|
||||||
endif
|
|
||||||
let ofn = fn
|
|
||||||
let fn = fnamemodify(ofn,':s?\(.*\)[\/]\(app\|config\|db\|doc\|features\|lib\|log\|public\|script\|spec\|stories\|test\|tmp\|vendor\)\($\|[\/].*$\)?\1?')
|
|
||||||
endwhile
|
|
||||||
return 0
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:BufInit(path)
|
|
||||||
let s:_{s:escvar(a:path)} = 1
|
|
||||||
if s:autoload()
|
|
||||||
return RailsBufInit(a:path)
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
" Initialization {{{1
|
|
||||||
|
|
||||||
augroup railsPluginDetect
|
|
||||||
autocmd!
|
|
||||||
autocmd BufNewFile,BufRead * call s:Detect(expand("<afile>:p"))
|
|
||||||
autocmd VimEnter * if expand("<amatch>") == "" && !exists("b:rails_root") | call s:Detect(getcwd()) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
|
|
||||||
autocmd FileType netrw if !exists("b:rails_root") | call s:Detect(expand("<afile>:p")) | endif | if exists("b:rails_root") | silent doau User BufEnterRails | endif
|
|
||||||
autocmd BufEnter * if exists("b:rails_root")|silent doau User BufEnterRails|endif
|
|
||||||
autocmd BufLeave * if exists("b:rails_root")|silent doau User BufLeaveRails|endif
|
|
||||||
autocmd Syntax railslog if s:autoload()|call rails#log_syntax()|endif
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
command! -bar -bang -nargs=* -complete=dir Rails :if s:autoload()|call rails#new_app_command(<bang>0,<f-args>)|endif
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
" Menus {{{1
|
|
||||||
|
|
||||||
if !(g:rails_menu && has("menu"))
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
|
|
||||||
function! s:sub(str,pat,rep)
|
|
||||||
return substitute(a:str,'\v\C'.a:pat,a:rep,'')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:gsub(str,pat,rep)
|
|
||||||
return substitute(a:str,'\v\C'.a:pat,a:rep,'g')
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:menucmd(priority)
|
|
||||||
return 'anoremenu <script> '.(exists("$CREAM") ? 87 : '').s:gsub(g:rails_installed_menu,'[^.]','').'.'.a:priority.' '
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:CreateMenus() abort
|
|
||||||
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
|
|
||||||
exe "aunmenu ".s:gsub(g:rails_installed_menu,'\&','')
|
|
||||||
unlet g:rails_installed_menu
|
|
||||||
endif
|
|
||||||
if has("menu") && (exists("g:did_install_default_menus") || exists("$CREAM")) && g:rails_menu
|
|
||||||
if g:rails_menu > 1
|
|
||||||
let g:rails_installed_menu = '&Rails'
|
|
||||||
else
|
|
||||||
let g:rails_installed_menu = '&Plugin.&Rails'
|
|
||||||
endif
|
|
||||||
let dots = s:gsub(g:rails_installed_menu,'[^.]','')
|
|
||||||
let menucmd = s:menucmd(200)
|
|
||||||
if exists("$CREAM")
|
|
||||||
exe menucmd.g:rails_installed_menu.'.-PSep- :'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ Alt+] :R<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ Alt+[ :A<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ Ctrl+Enter :Rfind<CR>'
|
|
||||||
else
|
|
||||||
exe menucmd.g:rails_installed_menu.'.-PSep- :'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Related\ file\ :R\ /\ ]f :R<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Alternate\ file\ :A\ /\ [f :A<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&File\ under\ cursor\ gf :Rfind<CR>'
|
|
||||||
endif
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Controller :find app/controllers/application.rb<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Helper :find app/helpers/application_helper.rb<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Javascript :find public/javascripts/application.js<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &Layout :Rlayout application<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Application\ &README :find doc/README_FOR_APP<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Environment :find config/environment.rb<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Database\ Configuration :find config/database.yml<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.Database\ &Schema :Rmigration 0<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.R&outes :find config/routes.rb<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Other\ files.&Test\ Helper :find test/test_helper.rb<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.-FSep- :'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.Ra&ke\ :Rake :Rake<CR>'
|
|
||||||
let menucmd = substitute(menucmd,'200 $','500 ','')
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Start\ :Rserver :Rserver<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Force\ start\ :Rserver! :Rserver!<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Server\ :Rserver.&Kill\ :Rserver!\ - :Rserver! -<CR>'
|
|
||||||
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.&Evaluate\ Ruby\.\.\.\ :Rp :call <SID>menuprompt("Rp","Code to execute and output: ")<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Console\ :Rscript :Rscript console<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Preview\ :Rpreview :Rpreview<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Log\ file\ :Rlog :Rlog<CR>'
|
|
||||||
exe substitute(s:sub(menucmd,'anoremenu','vnoremenu'),'<script>','<script> <silent>','').g:rails_installed_menu.'.E&xtract\ as\ partial\ :Rextract :call <SID>menuprompt("'."'".'<,'."'".'>Rextract","Partial name (e.g., template or /controller/template): ")<CR>'
|
|
||||||
exe menucmd.g:rails_installed_menu.'.&Migration\ writer\ :Rinvert :Rinvert<CR>'
|
|
||||||
exe menucmd.' '.g:rails_installed_menu.'.-HSep- :'
|
|
||||||
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.&Help\ :help\ rails :if <SID>autoload()<Bar>exe RailsHelpCommand("")<Bar>endif<CR>'
|
|
||||||
exe substitute(menucmd,'<script>','<script> <silent>','').g:rails_installed_menu.'.Abo&ut\ :if <SID>autoload()<Bar>exe RailsHelpCommand("about")<Bar>endif<CR>'
|
|
||||||
let g:rails_did_menus = 1
|
|
||||||
call s:ProjectMenu()
|
|
||||||
call s:menuBufLeave()
|
|
||||||
if exists("b:rails_root")
|
|
||||||
call s:menuBufEnter()
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:ProjectMenu()
|
|
||||||
if exists("g:rails_did_menus") && g:rails_history_size > 0
|
|
||||||
if !exists("g:RAILS_HISTORY")
|
|
||||||
let g:RAILS_HISTORY = ""
|
|
||||||
endif
|
|
||||||
let history = g:RAILS_HISTORY
|
|
||||||
let menu = s:gsub(g:rails_installed_menu,'\&','')
|
|
||||||
silent! exe "aunmenu <script> ".menu.".Projects"
|
|
||||||
let dots = s:gsub(menu,'[^.]','')
|
|
||||||
exe 'anoremenu <script> <silent> '.(exists("$CREAM") ? '87' : '').dots.'.100 '.menu.'.Pro&jects.&New\.\.\.\ :Rails :call <SID>menuprompt("Rails","New application path and additional arguments: ")<CR>'
|
|
||||||
exe 'anoremenu <script> '.menu.'.Pro&jects.-FSep- :'
|
|
||||||
while history =~ '\n'
|
|
||||||
let proj = matchstr(history,'^.\{-\}\ze\n')
|
|
||||||
let history = s:sub(history,'^.{-}\n','')
|
|
||||||
exe 'anoremenu <script> '.menu.'.Pro&jects.'.s:gsub(proj,'[.\\ ]','\\&').' :e '.s:gsub(proj."/".g:rails_default_file,'[ !%#]','\\&')."<CR>"
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:menuBufEnter()
|
|
||||||
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
|
|
||||||
let menu = s:gsub(g:rails_installed_menu,'\&','')
|
|
||||||
exe 'amenu enable '.menu.'.*'
|
|
||||||
if RailsFileType() !~ '^view\>'
|
|
||||||
exe 'vmenu disable '.menu.'.Extract\ as\ partial'
|
|
||||||
endif
|
|
||||||
if RailsFileType() !~ '^\%(db-\)\=migration$' || RailsFilePath() =~ '\<db/schema\.rb$'
|
|
||||||
exe 'amenu disable '.menu.'.Migration\ writer'
|
|
||||||
endif
|
|
||||||
call s:ProjectMenu()
|
|
||||||
silent! exe 'aunmenu '.menu.'.Rake\ tasks'
|
|
||||||
silent! exe 'aunmenu '.menu.'.Generate'
|
|
||||||
silent! exe 'aunmenu '.menu.'.Destroy'
|
|
||||||
if rails#app().cache.needs('rake_tasks') || empty(rails#app().rake_tasks())
|
|
||||||
exe substitute(s:menucmd(300),'<script>','<script> <silent>','').g:rails_installed_menu.'.Rake\ &tasks\ :Rake.Fill\ this\ menu :call rails#app().rake_tasks()<Bar>call <SID>menuBufLeave()<Bar>call <SID>menuBufEnter()<CR>'
|
|
||||||
else
|
|
||||||
let i = 0
|
|
||||||
while i < len(rails#app().rake_tasks())
|
|
||||||
let task = rails#app().rake_tasks()[i]
|
|
||||||
exe s:menucmd(300).g:rails_installed_menu.'.Rake\ &tasks\ :Rake.'.s:sub(task,':',':.').' :Rake '.task.'<CR>'
|
|
||||||
let i += 1
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
let i = 0
|
|
||||||
let menucmd = substitute(s:menucmd(400),'<script>','<script> <silent>','').g:rails_installed_menu
|
|
||||||
while i < len(rails#app().generators())
|
|
||||||
let generator = rails#app().generators()[i]
|
|
||||||
exe menucmd.'.&Generate\ :Rgen.'.s:gsub(generator,'_','\\ ').' :call <SID>menuprompt("Rgenerate '.generator.'","Arguments for script/generate '.generator.': ")<CR>'
|
|
||||||
exe menucmd.'.&Destroy\ :Rdestroy.'.s:gsub(generator,'_','\\ ').' :call <SID>menuprompt("Rdestroy '.generator.'","Arguments for script/destroy '.generator.': ")<CR>'
|
|
||||||
let i += 1
|
|
||||||
endwhile
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:menuBufLeave()
|
|
||||||
if exists("g:rails_installed_menu") && g:rails_installed_menu != ""
|
|
||||||
let menu = s:gsub(g:rails_installed_menu,'\&','')
|
|
||||||
exe 'amenu disable '.menu.'.*'
|
|
||||||
exe 'amenu enable '.menu.'.Help\ '
|
|
||||||
exe 'amenu enable '.menu.'.About\ '
|
|
||||||
exe 'amenu enable '.menu.'.Projects'
|
|
||||||
silent! exe 'aunmenu '.menu.'.Rake\ tasks'
|
|
||||||
silent! exe 'aunmenu '.menu.'.Generate'
|
|
||||||
silent! exe 'aunmenu '.menu.'.Destroy'
|
|
||||||
exe s:menucmd(300).g:rails_installed_menu.'.Rake\ tasks\ :Rake.-TSep- :'
|
|
||||||
exe s:menucmd(400).g:rails_installed_menu.'.&Generate\ :Rgen.-GSep- :'
|
|
||||||
exe s:menucmd(400).g:rails_installed_menu.'.&Destroy\ :Rdestroy.-DSep- :'
|
|
||||||
endif
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
function! s:menuprompt(vimcmd,prompt)
|
|
||||||
let res = inputdialog(a:prompt,'','!!!')
|
|
||||||
if res == '!!!'
|
|
||||||
return ""
|
|
||||||
endif
|
|
||||||
exe a:vimcmd." ".res
|
|
||||||
endfunction
|
|
||||||
|
|
||||||
call s:CreateMenus()
|
|
||||||
|
|
||||||
augroup railsPluginMenu
|
|
||||||
autocmd!
|
|
||||||
autocmd User BufEnterRails call s:menuBufEnter()
|
|
||||||
autocmd User BufLeaveRails call s:menuBufLeave()
|
|
||||||
" g:RAILS_HISTORY hasn't been set when s:InitPlugin() is called.
|
|
||||||
autocmd VimEnter * call s:ProjectMenu()
|
|
||||||
augroup END
|
|
||||||
|
|
||||||
" }}}1
|
|
||||||
" vim:set sw=2 sts=2:
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue