Add fuzzyfinder
diff --git a/autoload/fuf.vim b/autoload/fuf.vim
new file mode 100644
index 0000000..198d1a9
--- /dev/null
+++ b/autoload/fuf.vim
@@ -0,0 +1,1032 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ finish
+endif
+
+" }}}1
+"=============================================================================
+" GLOBAL FUNCTIONS {{{1
+
+
+"
+function fuf#countModifiedFiles(files, time)
+ return len(filter(copy(a:files), 'getftime(v:val) > a:time'))
+endfunction
+
+"
+function fuf#getCurrentTagFiles()
+ return sort(filter(map(tagfiles(), 'fnamemodify(v:val, '':p'')'), 'filereadable(v:val)'))
+endfunction
+
+"
+function fuf#mapToSetSerialIndex(in, offset)
+ for i in range(len(a:in))
+ let a:in[i].index = i + a:offset
+ endfor
+ return a:in
+endfunction
+
+"
+function fuf#updateMruList(mrulist, newItem, maxItem, exclude)
+ let result = copy(a:mrulist)
+ let result = filter(result,'v:val.word !=# a:newItem.word')
+ let result = insert(result, a:newItem)
+ if len(a:exclude)
+ let result = filter(result, 'v:val.word !~ a:exclude')
+ endif
+ return result[0 : a:maxItem - 1]
+endfunction
+
+" takes suffix number. if no digits, returns -1
+function fuf#suffixNumber(str)
+ let s = matchstr(a:str, '\d\+$')
+ return (len(s) ? str2nr(s) : -1)
+endfunction
+
+" "foo/bar/buz/hoge" -> { head: "foo/bar/buz/", tail: "hoge" }
+function fuf#splitPath(path)
+ let head = matchstr(a:path, '^.*[/\\]')
+ return {
+ \ 'head' : head,
+ \ 'tail' : a:path[strlen(head):]
+ \ }
+endfunction
+
+" "foo/.../bar/...hoge" -> "foo/.../bar/../../hoge"
+function fuf#expandTailDotSequenceToParentDir(pattern)
+ return substitute(a:pattern, '^\(.*[/\\]\)\?\zs\.\(\.\+\)\ze[^/\\]*$',
+ \ '\=repeat(".." . l9#getPathSeparator(), len(submatch(2)))', '')
+endfunction
+
+"
+function fuf#formatPrompt(prompt, partialMatching, otherString)
+ let indicator = escape((a:partialMatching ? '!' : '') . a:otherString, '\')
+ return substitute(a:prompt, '[]', indicator, 'g')
+endfunction
+
+"
+function fuf#getFileLines(file)
+ let bufnr = (type(a:file) ==# type(0) ? a:file : bufnr('^' . a:file . '$'))
+ let lines = getbufline(bufnr, 1, '$')
+ if !empty(lines)
+ return lines
+ endif
+ return l9#readFile(a:file)
+endfunction
+
+"
+function fuf#makePreviewLinesAround(lines, indices, page, maxHeight)
+ let index = ((empty(a:indices) ? 0 : a:indices[0])
+ \ + a:page * a:maxHeight) % len(a:lines)
+ if empty(a:lines) || a:maxHeight <= 0
+ return []
+ endif
+ let beg = max([0, index - a:maxHeight / 2])
+ let end = min([beg + a:maxHeight, len(a:lines)])
+ let beg = max([0, end - a:maxHeight])
+ let lines = []
+ for i in range(beg, end - 1)
+ let mark = (count(a:indices, i) ? '>' : ' ')
+ call add(lines, printf('%s%4d ', mark, i + 1) . a:lines[i])
+ endfor
+ return lines
+endfunction
+
+" a:file: a path string or a buffer number
+function fuf#makePreviewLinesForFile(file, count, maxHeight)
+ let lines = fuf#getFileLines(a:file)
+ if empty(lines)
+ return []
+ endif
+ let bufnr = (type(a:file) ==# type(0) ? a:file : bufnr('^' . a:file . '$'))
+ if exists('s:bufferCursorPosMap[bufnr]')
+ let indices = [s:bufferCursorPosMap[bufnr][1] - 1]
+ else
+ let indices = []
+ endif
+ return fuf#makePreviewLinesAround(
+ \ lines, indices, a:count, a:maxHeight)
+endfunction
+
+"
+function fuf#echoWarning(msg)
+ call l9#echoHl('WarningMsg', a:msg, '[fuf] ', 1)
+endfunction
+
+"
+function fuf#echoError(msg)
+ call l9#echoHl('ErrorMsg', a:msg, '[fuf] ', 1)
+endfunction
+
+"
+function fuf#openBuffer(bufNr, mode, reuse)
+ if a:reuse && ((a:mode ==# s:OPEN_TYPE_SPLIT &&
+ \ l9#moveToBufferWindowInCurrentTabpage(a:bufNr)) ||
+ \ (a:mode ==# s:OPEN_TYPE_VSPLIT &&
+ \ l9#moveToBufferWindowInCurrentTabpage(a:bufNr)) ||
+ \ (a:mode ==# s:OPEN_TYPE_TAB &&
+ \ l9#moveToBufferWindowInOtherTabpage(a:bufNr)))
+ return
+ endif
+ execute printf({
+ \ s:OPEN_TYPE_CURRENT : '%sbuffer' ,
+ \ s:OPEN_TYPE_SPLIT : '%ssbuffer' ,
+ \ s:OPEN_TYPE_VSPLIT : 'vertical %ssbuffer',
+ \ s:OPEN_TYPE_TAB : 'tab %ssbuffer' ,
+ \ }[a:mode], a:bufNr)
+endfunction
+
+"
+function fuf#openFile(path, mode, reuse)
+ let bufNr = bufnr('^' . a:path . '$')
+ if bufNr > -1
+ call fuf#openBuffer(bufNr, a:mode, a:reuse)
+ else
+ execute {
+ \ s:OPEN_TYPE_CURRENT : 'edit ' ,
+ \ s:OPEN_TYPE_SPLIT : 'split ' ,
+ \ s:OPEN_TYPE_VSPLIT : 'vsplit ' ,
+ \ s:OPEN_TYPE_TAB : 'tabedit ',
+ \ }[a:mode] . fnameescape(fnamemodify(a:path, ':~:.'))
+ endif
+endfunction
+
+"
+function fuf#openTag(tag, mode)
+ execute {
+ \ s:OPEN_TYPE_CURRENT : 'tjump ' ,
+ \ s:OPEN_TYPE_SPLIT : 'stjump ' ,
+ \ s:OPEN_TYPE_VSPLIT : 'vertical stjump ',
+ \ s:OPEN_TYPE_TAB : 'tab stjump ' ,
+ \ }[a:mode] . a:tag
+endfunction
+
+"
+function fuf#openHelp(tag, mode)
+ execute {
+ \ s:OPEN_TYPE_CURRENT : 'help ' ,
+ \ s:OPEN_TYPE_SPLIT : 'help ' ,
+ \ s:OPEN_TYPE_VSPLIT : 'vertical help ',
+ \ s:OPEN_TYPE_TAB : 'tab help ' ,
+ \ }[a:mode] . a:tag
+endfunction
+
+"
+function fuf#prejump(mode)
+ execute {
+ \ s:OPEN_TYPE_CURRENT : '' ,
+ \ s:OPEN_TYPE_SPLIT : 'split' ,
+ \ s:OPEN_TYPE_VSPLIT : 'vsplit' ,
+ \ s:OPEN_TYPE_TAB : 'tab split',
+ \ }[a:mode]
+endfunction
+
+"
+function fuf#compareRanks(i1, i2)
+ if exists('a:i1.ranks') && exists('a:i2.ranks')
+ for i in range(min([len(a:i1.ranks), len(a:i2.ranks)]))
+ if a:i1.ranks[i] > a:i2.ranks[i]
+ return +1
+ elseif a:i1.ranks[i] < a:i2.ranks[i]
+ return -1
+ endif
+ endfor
+ endif
+ return 0
+endfunction
+
+"
+function fuf#makePathItem(fname, menu, appendsDirSuffix)
+ let pathPair = fuf#splitPath(a:fname)
+ let dirSuffix = (a:appendsDirSuffix && isdirectory(expand(a:fname))
+ \ ? l9#getPathSeparator()
+ \ : '')
+ return {
+ \ 'word' : a:fname . dirSuffix,
+ \ 'wordForPrimaryHead': s:toLowerForIgnoringCase(pathPair.head),
+ \ 'wordForPrimaryTail': s:toLowerForIgnoringCase(pathPair.tail),
+ \ 'wordForBoundary' : s:toLowerForIgnoringCase(s:getWordBoundaries(pathPair.tail)),
+ \ 'wordForRefining' : s:toLowerForIgnoringCase(a:fname . dirSuffix),
+ \ 'wordForRank' : s:toLowerForIgnoringCase(pathPair.tail),
+ \ 'menu' : a:menu,
+ \ }
+endfunction
+
+"
+function fuf#makeNonPathItem(word, menu)
+ let wordL = s:toLowerForIgnoringCase(a:word)
+ return {
+ \ 'word' : a:word,
+ \ 'wordForPrimary' : wordL,
+ \ 'wordForBoundary': s:toLowerForIgnoringCase(s:getWordBoundaries(a:word)),
+ \ 'wordForRefining': wordL,
+ \ 'wordForRank' : wordL,
+ \ 'menu' : a:menu,
+ \ }
+endfunction
+
+"
+function fuf#makePatternSet(patternBase, interpreter, partialMatching)
+ let MakeMatchingExpr = function(a:partialMatching
+ \ ? 's:makePartialMatchingExpr'
+ \ : 's:makeFuzzyMatchingExpr')
+ let [primary; refinings] = split(a:patternBase, g:fuf_patternSeparator, 1)
+ let elements = call(a:interpreter, [primary])
+ let primaryExprs = map(elements.matchingPairs, 'MakeMatchingExpr(v:val[0], v:val[1])')
+ let refiningExprs = map(refinings, 's:makeRefiningExpr(v:val)')
+ return {
+ \ 'primary' : elements.primary,
+ \ 'primaryForRank': elements.primaryForRank,
+ \ 'filteringExpr' : join(primaryExprs + refiningExprs, ' && '),
+ \ }
+endfunction
+
+"
+function fuf#enumExpandedDirsEntries(dir, exclude)
+ " Substitutes "\" because on Windows, "**\" doesn't include ".\",
+ " but "**/" include "./". I don't know why.
+ let dirNormalized = substitute(a:dir, '\', '/', 'g')
+ let entries = split(glob(dirNormalized . "*" ), "\n") +
+ \ split(glob(dirNormalized . ".*"), "\n")
+ " removes "*/." and "*/.."
+ call filter(entries, 'v:val !~ ''\v(^|[/\\])\.\.?$''')
+ call map(entries, 'fuf#makePathItem(v:val, "", 1)')
+ if len(a:exclude)
+ call filter(entries, 'v:val.word !~ a:exclude')
+ endif
+ return entries
+endfunction
+
+"
+function fuf#mapToSetAbbrWithSnippedWordAsPath(items)
+ let maxLenStats = {}
+ call map(a:items, 's:makeFileAbbrInfo(v:val, maxLenStats)')
+ let snippedHeads =
+ \ map(maxLenStats, 's:getSnippedHead(v:key[: -2], v:val)')
+ return map(a:items, 's:setAbbrWithFileAbbrData(v:val, snippedHeads)')
+endfunction
+
+"
+function fuf#setAbbrWithFormattedWord(item, abbrIndex)
+ let lenMenu = (exists('a:item.menu') ? len(a:item.menu) + 2 : 0)
+ let abbrPrefix = (exists('a:item.abbrPrefix') ? a:item.abbrPrefix : '')
+ let a:item.abbr = abbrPrefix . a:item.word
+ if a:abbrIndex
+ let a:item.abbr = printf('%4d: ', a:item.index) . a:item.abbr
+ endif
+ let a:item.abbr = l9#snipTail(a:item.abbr, g:fuf_maxMenuWidth - lenMenu, s:ABBR_SNIP_MASK)
+ return a:item
+endfunction
+
+"
+function s:onCommandPre()
+ for m in filter(copy(fuf#getModeNames()), 'fuf#{v:val}#requiresOnCommandPre()')
+ call fuf#{m}#onCommandPre(getcmdtype() . getcmdline())
+ endfor
+ " lets last entry become the newest in the history
+ call histadd(getcmdtype(), getcmdline())
+ " this is not mapped again (:help recursive_mapping)
+ return "\<CR>"
+endfunction
+
+"
+let s:modeNames = []
+
+"
+function fuf#addMode(modeName)
+ if count(g:fuf_modesDisable, a:modeName) > 0
+ return
+ endif
+ call add(s:modeNames, a:modeName)
+ call fuf#{a:modeName}#renewCache()
+ call fuf#{a:modeName}#onInit()
+ if fuf#{a:modeName}#requiresOnCommandPre()
+ " cnoremap has a problem, which doesn't expand cabbrev.
+ cmap <silent> <expr> <CR> <SID>onCommandPre()
+ endif
+endfunction
+
+"
+function fuf#getModeNames()
+ return s:modeNames
+endfunction
+
+"
+function fuf#defineLaunchCommand(CmdName, modeName, prefixInitialPattern)
+ execute printf('command! -bang -narg=? %s call fuf#launch(%s, %s . <q-args>, len(<q-bang>))',
+ \ a:CmdName, string(a:modeName), a:prefixInitialPattern)
+endfunction
+
+"
+function fuf#defineKeyMappingInHandler(key, func)
+ " hacks to be able to use feedkeys().
+ execute printf(
+ \ 'inoremap <buffer> <silent> %s <C-r>=fuf#getRunningHandler().%s ? "" : ""<CR>',
+ \ a:key, a:func)
+endfunction
+
+"
+let s:oneTimeVariables = []
+
+"
+function fuf#setOneTimeVariables(...)
+ let s:oneTimeVariables += a:000
+endfunction
+
+"
+function fuf#launch(modeName, initialPattern, partialMatching)
+ if exists('s:runningHandler')
+ call fuf#echoWarning('FuzzyFinder is running.')
+ endif
+ if count(fuf#getModeNames(), a:modeName) == 0
+ echoerr 'This mode is not available: ' . a:modeName
+ return
+ endif
+ let s:runningHandler = fuf#{a:modeName}#createHandler(copy(s:handlerBase))
+ let s:runningHandler.stats = fuf#loadDataFile(s:runningHandler.getModeName(), 'stats')
+ let s:runningHandler.partialMatching = a:partialMatching
+ let s:runningHandler.bufNrPrev = bufnr('%')
+ let s:runningHandler.lastCol = -1
+ let s:runningHandler.windowRestoringCommand = winrestcmd()
+ call s:runningHandler.onModeEnterPre()
+ call fuf#setOneTimeVariables(
+ \ ['&completeopt', 'menuone'],
+ \ ['&ignorecase', 0],)
+ if s:runningHandler.getPreviewHeight() > 0
+ call fuf#setOneTimeVariables(
+ \ ['&cmdheight', s:runningHandler.getPreviewHeight() + 1])
+ endif
+ call l9#tempvariables#setList(s:TEMP_VARIABLES_GROUP, s:oneTimeVariables)
+ let s:oneTimeVariables = []
+ call s:activateFufBuffer()
+ augroup FufLocal
+ autocmd!
+ autocmd CursorMovedI <buffer> call s:runningHandler.onCursorMovedI()
+ autocmd InsertLeave <buffer> nested call s:runningHandler.onInsertLeave()
+ augroup END
+ for [key, func] in [
+ \ [ g:fuf_keyOpen , 'onCr(' . s:OPEN_TYPE_CURRENT . ')' ],
+ \ [ g:fuf_keyOpenSplit , 'onCr(' . s:OPEN_TYPE_SPLIT . ')' ],
+ \ [ g:fuf_keyOpenVsplit , 'onCr(' . s:OPEN_TYPE_VSPLIT . ')' ],
+ \ [ g:fuf_keyOpenTabpage , 'onCr(' . s:OPEN_TYPE_TAB . ')' ],
+ \ [ '<BS>' , 'onBs()' ],
+ \ [ '<C-h>' , 'onBs()' ],
+ \ [ '<C-w>' , 'onDeleteWord()' ],
+ \ [ g:fuf_keyPreview , 'onPreviewBase(1)' ],
+ \ [ g:fuf_keyNextMode , 'onSwitchMode(+1)' ],
+ \ [ g:fuf_keyPrevMode , 'onSwitchMode(-1)' ],
+ \ [ g:fuf_keySwitchMatching, 'onSwitchMatching()' ],
+ \ [ g:fuf_keyPrevPattern , 'onRecallPattern(+1)' ],
+ \ [ g:fuf_keyNextPattern , 'onRecallPattern(-1)' ],
+ \ ]
+ call fuf#defineKeyMappingInHandler(key, func)
+ endfor
+ " Starts Insert mode and makes CursorMovedI event now. Command prompt is
+ " needed to forces a completion menu to update every typing.
+ call setline(1, s:runningHandler.getPrompt() . a:initialPattern)
+ call s:runningHandler.onModeEnterPost()
+ call feedkeys("A", 'n') " startinsert! does not work in InsertLeave event handler
+ redraw
+endfunction
+
+"
+function fuf#loadDataFile(modeName, dataName)
+ if !s:dataFileAvailable
+ return []
+ endif
+ let lines = l9#readFile(l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName]))
+ return map(lines, 'eval(v:val)')
+endfunction
+
+"
+function fuf#saveDataFile(modeName, dataName, items)
+ if !s:dataFileAvailable
+ return -1
+ endif
+ let lines = map(copy(a:items), 'string(v:val)')
+ return l9#writeFile(lines, l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName]))
+endfunction
+
+"
+function fuf#getDataFileTime(modeName, dataName)
+ if !s:dataFileAvailable
+ return -1
+ endif
+ return getftime(expand(l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName])))
+endfunction
+
+"
+function s:createDataBufferListener(dataFile)
+ let listener = { 'dataFile': a:dataFile }
+
+ function listener.onWrite(lines)
+ let [modeName, dataName] = split(self.dataFile, l9#getPathSeparator())
+ let items = map(filter(a:lines, '!empty(v:val)'), 'eval(v:val)')
+ call fuf#saveDataFile(modeName, dataName, items)
+ echo "Data files updated"
+ return 1
+ endfunction
+
+ return listener
+endfunction
+
+"
+function s:createEditDataListener()
+ let listener = {}
+
+ function listener.onComplete(dataFile, method)
+ let bufName = '[fuf-info]'
+ let lines = l9#readFile(l9#concatPaths([g:fuf_dataDir, a:dataFile]))
+ call l9#tempbuffer#openWritable(bufName, 'vim', lines, 0, 0, 0,
+ \ s:createDataBufferListener(a:dataFile))
+ endfunction
+
+ return listener
+endfunction
+
+"
+function s:getEditableDataFiles(modeName)
+ let dataFiles = fuf#{a:modeName}#getEditableDataNames()
+ call filter(dataFiles, 'fuf#getDataFileTime(a:modeName, v:val) != -1')
+ return map(dataFiles, 'l9#concatPaths([a:modeName, v:val])')
+endfunction
+
+"
+function fuf#editDataFile()
+ let dataFiles = map(copy(fuf#getModeNames()), 's:getEditableDataFiles(v:val)')
+ let dataFiles = l9#concat(dataFiles)
+ call fuf#callbackitem#launch('', 0, '>Mode>', s:createEditDataListener(), dataFiles, 0)
+endfunction
+
+"
+function fuf#getRunningHandler()
+ return s:runningHandler
+endfunction
+
+"
+function fuf#onComplete(findstart, base)
+ return s:runningHandler.onComplete(a:findstart, a:base)
+endfunction
+
+" }}}1
+"=============================================================================
+" LOCAL FUNCTIONS/VARIABLES {{{1
+
+let s:TEMP_VARIABLES_GROUP = "FuzzyFinder"
+let s:ABBR_SNIP_MASK = '...'
+let s:OPEN_TYPE_CURRENT = 1
+let s:OPEN_TYPE_SPLIT = 2
+let s:OPEN_TYPE_VSPLIT = 3
+let s:OPEN_TYPE_TAB = 4
+
+" a:pattern: 'str' -> '\V\.\*s\.\*t\.\*r\.\*'
+function s:makeFuzzyMatchingExpr(target, pattern)
+ let wi = ''
+ for c in split(a:pattern, '\zs')
+ if wi =~# '[^*?]$' && c !~ '[*?]'
+ let wi .= '*'
+ endif
+ let wi .= c
+ endfor
+ return s:makePartialMatchingExpr(a:target, wi)
+endfunction
+
+" a:pattern: 'str' -> '\Vstr'
+" 'st*r' -> '\Vst\.\*r'
+function s:makePartialMatchingExpr(target, pattern)
+ let patternMigemo = s:makeAdditionalMigemoPattern(a:pattern)
+ if a:pattern !~ '[*?]' && empty(patternMigemo)
+ " NOTE: stridx is faster than regexp matching
+ return 'stridx(' . a:target . ', ' . string(a:pattern) . ') >= 0'
+ endif
+ return a:target . ' =~# ' .
+ \ string(l9#convertWildcardToRegexp(a:pattern)) . patternMigemo
+endfunction
+
+"
+function s:makeRefiningExpr(pattern)
+ if g:fuf_fuzzyRefining
+ let expr = s:makeFuzzyMatchingExpr('v:val.wordForRefining', a:pattern)
+ else
+ let expr = s:makePartialMatchingExpr('v:val.wordForRefining', a:pattern)
+ endif
+ if a:pattern =~# '\D'
+ return expr
+ else
+ return '(' . expr . ' || v:val.index == ' . string(a:pattern) . ')'
+ endif
+endfunction
+
+"
+function s:makeAdditionalMigemoPattern(pattern)
+ if !g:fuf_useMigemo || a:pattern =~# '[^\x01-\x7e]'
+ return ''
+ endif
+ return '\|\m' . substitute(migemo(a:pattern), '\\_s\*', '.*', 'g')
+endfunction
+
+"
+function s:interpretPrimaryPatternForPathTail(pattern)
+ let pattern = fuf#expandTailDotSequenceToParentDir(a:pattern)
+ let pairL = fuf#splitPath(s:toLowerForIgnoringCase(pattern))
+ return {
+ \ 'primary' : pattern,
+ \ 'primaryForRank': pairL.tail,
+ \ 'matchingPairs' : [['v:val.wordForPrimaryTail', pairL.tail],],
+ \ }
+endfunction
+
+"
+function s:interpretPrimaryPatternForPath(pattern)
+ let pattern = fuf#expandTailDotSequenceToParentDir(a:pattern)
+ let patternL = s:toLowerForIgnoringCase(pattern)
+ let pairL = fuf#splitPath(patternL)
+ if g:fuf_splitPathMatching
+ let matches = [
+ \ ['v:val.wordForPrimaryHead', pairL.head],
+ \ ['v:val.wordForPrimaryTail', pairL.tail],
+ \ ]
+ else
+ let matches = [
+ \ ['v:val.wordForPrimaryHead . v:val.wordForPrimaryTail', patternL],
+ \ ]
+ endif
+ return {
+ \ 'primary' : pattern,
+ \ 'primaryForRank': pairL.tail,
+ \ 'matchingPairs' : matches,
+ \ }
+endfunction
+
+"
+function s:interpretPrimaryPatternForNonPath(pattern)
+ let patternL = s:toLowerForIgnoringCase(a:pattern)
+ return {
+ \ 'primary' : a:pattern,
+ \ 'primaryForRank': patternL,
+ \ 'matchingPairs' : [['v:val.wordForPrimary', patternL],],
+ \ }
+endfunction
+
+"
+function s:getWordBoundaries(word)
+ return substitute(a:word, '\a\zs\l\+\|\zs\A', '', 'g')
+endfunction
+
+"
+function s:toLowerForIgnoringCase(str)
+ return (g:fuf_ignoreCase ? tolower(a:str) : a:str)
+endfunction
+
+"
+function s:setRanks(item, pattern, exprBoundary, stats)
+ "let word2 = substitute(a:eval_word, '\a\zs\l\+\|\zs\A', '', 'g')
+ let a:item.ranks = [
+ \ s:evaluateLearningRank(a:item.word, a:stats),
+ \ -s:scoreSequentialMatching(a:item.wordForRank, a:pattern),
+ \ -s:scoreBoundaryMatching(a:item.wordForBoundary,
+ \ a:pattern, a:exprBoundary),
+ \ a:item.index,
+ \ ]
+ return a:item
+endfunction
+
+"
+function s:evaluateLearningRank(word, stats)
+ for i in range(len(a:stats))
+ if a:stats[i].word ==# a:word
+ return i
+ endif
+ endfor
+ return len(a:stats)
+endfunction
+
+" range of return value is [0.0, 1.0]
+function s:scoreSequentialMatching(word, pattern)
+ if empty(a:pattern)
+ return str2float('0.0')
+ endif
+ let pos = stridx(a:word, a:pattern)
+ if pos < 0
+ return str2float('0.0')
+ endif
+ let lenRest = len(a:word) - len(a:pattern) - pos
+ return str2float(pos == 0 ? '0.5' : '0.0') + str2float('0.5') / (lenRest + 1)
+endfunction
+
+" range of return value is [0.0, 1.0]
+function s:scoreBoundaryMatching(wordForBoundary, pattern, exprBoundary)
+ if empty(a:pattern)
+ return str2float('0.0')
+ endif
+ if !eval(a:exprBoundary)
+ return 0
+ endif
+ return (s:scoreSequentialMatching(a:wordForBoundary, a:pattern) + 1) / 2
+endfunction
+
+"
+function s:highlightPrompt(prompt)
+ syntax clear
+ execute printf('syntax match %s /^\V%s/', g:fuf_promptHighlight, escape(a:prompt, '\/'))
+endfunction
+
+"
+function s:highlightError()
+ syntax clear
+ syntax match Error /^.*$/
+endfunction
+
+"
+function s:expandAbbrevMap(pattern, abbrevMap)
+ let result = [a:pattern]
+ for [pattern, subs] in items(a:abbrevMap)
+ let exprs = result
+ let result = []
+ for expr in exprs
+ let result += map(copy(subs), 'substitute(expr, pattern, escape(v:val, ''\''), "g")')
+ endfor
+ endfor
+ return l9#unique(result)
+endfunction
+
+"
+function s:makeFileAbbrInfo(item, maxLenStats)
+ let head = matchstr(a:item.word, '^.*[/\\]\ze.')
+ let a:item.abbr = { 'head' : head,
+ \ 'tail' : a:item.word[strlen(head):],
+ \ 'key' : head . '.',
+ \ 'prefix' : printf('%4d: ', a:item.index), }
+ if exists('a:item.abbrPrefix')
+ let a:item.abbr.prefix .= a:item.abbrPrefix
+ endif
+ let len = len(a:item.abbr.prefix) + len(a:item.word) +
+ \ (exists('a:item.menu') ? len(a:item.menu) + 2 : 0)
+ if !exists('a:maxLenStats[a:item.abbr.key]') || len > a:maxLenStats[a:item.abbr.key]
+ let a:maxLenStats[a:item.abbr.key] = len
+ endif
+ return a:item
+endfunction
+
+"
+function s:getSnippedHead(head, baseLen)
+ return l9#snipMid(a:head, len(a:head) + g:fuf_maxMenuWidth - a:baseLen, s:ABBR_SNIP_MASK)
+endfunction
+
+"
+function s:setAbbrWithFileAbbrData(item, snippedHeads)
+ let lenMenu = (exists('a:item.menu') ? len(a:item.menu) + 2 : 0)
+ let abbr = a:item.abbr.prefix . a:snippedHeads[a:item.abbr.key] . a:item.abbr.tail
+ let a:item.abbr = l9#snipTail(abbr, g:fuf_maxMenuWidth - lenMenu, s:ABBR_SNIP_MASK)
+ return a:item
+endfunction
+
+"
+let s:FUF_BUF_NAME = '[fuf]'
+
+"
+function s:activateFufBuffer()
+ " lcd . : To avoid the strange behavior that unnamed buffer changes its cwd
+ " if 'autochdir' was set on.
+ lcd .
+ let cwd = getcwd()
+ call l9#tempbuffer#openScratch(s:FUF_BUF_NAME, 'fuf', [], 1, 0, 1, {})
+ resize 1 " for issue #21
+ " lcd ... : countermeasure against auto-cd script
+ lcd `=cwd`
+ setlocal nocursorline " for highlighting
+ setlocal nocursorcolumn " for highlighting
+ setlocal omnifunc=fuf#onComplete
+ redraw " for 'lazyredraw'
+ if exists(':AcpLock')
+ AcpLock
+ elseif exists(':AutoComplPopLock')
+ AutoComplPopLock
+ endif
+endfunction
+
+"
+function s:deactivateFufBuffer()
+ if exists(':AcpUnlock')
+ AcpUnlock
+ elseif exists(':AutoComplPopUnlock')
+ AutoComplPopUnlock
+ endif
+ call l9#tempbuffer#close(s:FUF_BUF_NAME)
+endfunction
+
+" }}}1
+"=============================================================================
+" s:handlerBase {{{1
+
+let s:handlerBase = {}
+
+"-----------------------------------------------------------------------------
+" PURE VIRTUAL FUNCTIONS {{{2
+"
+" "
+" s:handler.getModeName()
+"
+" "
+" s:handler.getPrompt()
+"
+" "
+" s:handler.getCompleteItems(patternSet)
+"
+" "
+" s:handler.onOpen(word, mode)
+"
+" " Before entering FuzzyFinder buffer. This function should return in a short time.
+" s:handler.onModeEnterPre()
+"
+" " After entering FuzzyFinder buffer.
+" s:handler.onModeEnterPost()
+"
+" " After leaving FuzzyFinder buffer.
+" s:handler.onModeLeavePost(opened)
+"
+" }}}2
+"-----------------------------------------------------------------------------
+
+"
+function s:handlerBase.concretize(deriv)
+ call extend(self, a:deriv, 'error')
+ return self
+endfunction
+
+"
+function s:handlerBase.addStat(pattern, word)
+ let stat = { 'pattern' : a:pattern, 'word' : a:word }
+ call filter(self.stats, 'v:val !=# stat')
+ call insert(self.stats, stat)
+ let self.stats = self.stats[0 : g:fuf_learningLimit - 1]
+endfunction
+
+"
+function s:handlerBase.getMatchingCompleteItems(patternBase)
+ let MakeMatchingExpr = function(self.partialMatching
+ \ ? 's:makePartialMatchingExpr'
+ \ : 's:makeFuzzyMatchingExpr')
+ let patternSet = self.makePatternSet(a:patternBase)
+ let exprBoundary = s:makeFuzzyMatchingExpr('a:wordForBoundary', patternSet.primaryForRank)
+ let stats = filter(
+ \ copy(self.stats), 'v:val.pattern ==# patternSet.primaryForRank')
+ let items = self.getCompleteItems(patternSet.primary)
+ " NOTE: In order to know an excess, plus 1 to limit number
+ let items = l9#filterWithLimit(
+ \ items, patternSet.filteringExpr, g:fuf_enumeratingLimit + 1)
+ return map(items,
+ \ 's:setRanks(v:val, patternSet.primaryForRank, exprBoundary, stats)')
+endfunction
+
+"
+function s:handlerBase.onComplete(findstart, base)
+ if a:findstart
+ return 0
+ elseif !self.existsPrompt(a:base)
+ return []
+ endif
+ call s:highlightPrompt(self.getPrompt())
+ let items = []
+ for patternBase in s:expandAbbrevMap(self.removePrompt(a:base), g:fuf_abbrevMap)
+ let items += self.getMatchingCompleteItems(patternBase)
+ if len(items) > g:fuf_enumeratingLimit
+ let items = items[ : g:fuf_enumeratingLimit - 1]
+ call s:highlightError()
+ break
+ endif
+ endfor
+ if empty(items)
+ call s:highlightError()
+ else
+ call sort(items, 'fuf#compareRanks')
+ if g:fuf_autoPreview
+ call feedkeys("\<C-p>\<Down>\<C-r>=fuf#getRunningHandler().onPreviewBase(0) ? '' : ''\<CR>", 'n')
+ else
+ call feedkeys("\<C-p>\<Down>", 'n')
+ endif
+ let self.lastFirstWord = items[0].word
+ endif
+ return items
+endfunction
+
+"
+function s:handlerBase.existsPrompt(line)
+ return strlen(a:line) >= strlen(self.getPrompt()) &&
+ \ a:line[:strlen(self.getPrompt()) -1] ==# self.getPrompt()
+endfunction
+
+"
+function s:handlerBase.removePrompt(line)
+ return a:line[(self.existsPrompt(a:line) ? strlen(self.getPrompt()) : 0):]
+endfunction
+
+"
+function s:handlerBase.restorePrompt(line)
+ let i = 0
+ while i < len(self.getPrompt()) && i < len(a:line) && self.getPrompt()[i] ==# a:line[i]
+ let i += 1
+ endwhile
+ return self.getPrompt() . a:line[i : ]
+endfunction
+
+"
+function s:handlerBase.onCursorMovedI()
+ if !self.existsPrompt(getline('.'))
+ call setline('.', self.restorePrompt(getline('.')))
+ call feedkeys("\<End>", 'n')
+ elseif col('.') <= len(self.getPrompt())
+ " if the cursor is moved before command prompt
+ call feedkeys(repeat("\<Right>", len(self.getPrompt()) - col('.') + 1), 'n')
+ elseif col('.') > strlen(getline('.')) && col('.') != self.lastCol
+ " if the cursor is placed on the end of the line and has been actually moved.
+ let self.lastCol = col('.')
+ let self.lastPattern = self.removePrompt(getline('.'))
+ call feedkeys("\<C-x>\<C-o>", 'n')
+ endif
+endfunction
+
+"
+function s:handlerBase.onInsertLeave()
+ unlet s:runningHandler
+ call l9#tempvariables#swap(s:TEMP_VARIABLES_GROUP)
+ call s:deactivateFufBuffer()
+ call fuf#saveDataFile(self.getModeName(), 'stats', self.stats)
+ execute self.windowRestoringCommand
+ let fOpen = exists('s:reservedCommand')
+ if fOpen
+ call self.onOpen(s:reservedCommand[0], s:reservedCommand[1])
+ unlet s:reservedCommand
+ endif
+ call self.onModeLeavePost(fOpen)
+ if exists('self.reservedMode')
+ call l9#tempvariables#swap(s:TEMP_VARIABLES_GROUP)
+ call fuf#launch(self.reservedMode, self.lastPattern, self.partialMatching)
+ else
+ call l9#tempvariables#end(s:TEMP_VARIABLES_GROUP)
+ endif
+endfunction
+
+"
+function s:handlerBase.onCr(openType)
+ if pumvisible()
+ call feedkeys(printf("\<C-y>\<C-r>=fuf#getRunningHandler().onCr(%d) ? '' : ''\<CR>",
+ \ a:openType), 'n')
+ return
+ endif
+ if !empty(self.lastPattern)
+ call self.addStat(self.lastPattern, self.removePrompt(getline('.')))
+ endif
+ if !self.isOpenable(getline('.'))
+ " To clear i_<C-r> expression (fuf#getRunningHandler().onCr...)
+ echo ''
+ return
+ endif
+ let s:reservedCommand = [self.removePrompt(getline('.')), a:openType]
+ call feedkeys("\<Esc>", 'n') " stopinsert behavior is strange...
+endfunction
+
+"
+function s:handlerBase.onBs()
+ call feedkeys((pumvisible() ? "\<C-e>\<BS>" : "\<BS>"), 'n')
+endfunction
+
+"
+function s:getLastBlockLength(pattern, patternIsPath)
+ let separatorPos = strridx(a:pattern, g:fuf_patternSeparator)
+ if separatorPos >= 0
+ return len(a:pattern) - separatorPos
+ endif
+ if a:patternIsPath && a:pattern =~# '[/\\].'
+ return len(matchstr(a:pattern, '[^/\\]*.$'))
+ endif
+ return len(a:pattern)
+endfunction
+
+"
+function s:handlerBase.onDeleteWord()
+ let pattern = self.removePrompt(getline('.')[ : col('.') - 2])
+ let numBs = s:getLastBlockLength(pattern, 1)
+ call feedkeys((pumvisible() ? "\<C-e>" : "") . repeat("\<BS>", numBs), 'n')
+endfunction
+
+"
+function s:handlerBase.onPreviewBase(repeatable)
+ if self.getPreviewHeight() <= 0
+ return
+ elseif !pumvisible()
+ return
+ elseif !self.existsPrompt(getline('.'))
+ let word = self.removePrompt(getline('.'))
+ elseif !exists('self.lastFirstWord')
+ return
+ else
+ let word = self.lastFirstWord
+ endif
+ redraw
+ if a:repeatable && exists('self.lastPreviewInfo') && self.lastPreviewInfo.word ==# word
+ let self.lastPreviewInfo.count += 1
+ else
+ let self.lastPreviewInfo = {'word': word, 'count': 0}
+ endif
+ let lines = self.makePreviewLines(word, self.lastPreviewInfo.count)
+ let lines = lines[: self.getPreviewHeight() - 1]
+ call map(lines, 'substitute(v:val, "\t", repeat(" ", &tabstop), "g")')
+ call map(lines, 'strtrans(v:val)')
+ call map(lines, 'l9#snipTail(v:val, &columns - 1, s:ABBR_SNIP_MASK)')
+ echo join(lines, "\n")
+endfunction
+
+"
+function s:handlerBase.onSwitchMode(shift)
+ let modes = copy(fuf#getModeNames())
+ call map(modes, '{ "ranks": [ fuf#{v:val}#getSwitchOrder(), v:val ] }')
+ call filter(modes, 'v:val.ranks[0] >= 0')
+ call sort(modes, 'fuf#compareRanks')
+ let self.reservedMode = self.getModeName()
+ for i in range(len(modes))
+ if modes[i].ranks[1] ==# self.getModeName()
+ let self.reservedMode = modes[(i + a:shift) % len(modes)].ranks[1]
+ break
+ endif
+ endfor
+ call feedkeys("\<Esc>", 'n') " stopinsert doesn't work.
+endfunction
+
+"
+function s:handlerBase.onSwitchMatching()
+ let self.partialMatching = !self.partialMatching
+ let self.lastCol = -1
+ call setline('.', self.restorePrompt(self.lastPattern))
+ call feedkeys("\<End>", 'n')
+ "call self.onCursorMovedI()
+endfunction
+
+"
+function s:handlerBase.onRecallPattern(shift)
+ let patterns = map(copy(self.stats), 'v:val.pattern')
+ if !exists('self.indexRecall')
+ let self.indexRecall = -1
+ endif
+ let self.indexRecall += a:shift
+ if self.indexRecall < 0
+ let self.indexRecall = -1
+ elseif self.indexRecall >= len(patterns)
+ let self.indexRecall = len(patterns) - 1
+ else
+ call setline('.', self.getPrompt() . patterns[self.indexRecall])
+ call feedkeys("\<End>", 'n')
+ endif
+endfunction
+
+" }}}1
+"=============================================================================
+" INITIALIZATION {{{1
+
+augroup FufGlobal
+ autocmd!
+ autocmd BufLeave * let s:bufferCursorPosMap[bufnr('')] = getpos('.')
+augroup END
+
+let s:bufferCursorPosMap = {}
+
+"
+let s:DATA_FILE_VERSION = 400
+
+"
+function s:checkDataFileCompatibility()
+ if empty(g:fuf_dataDir)
+ let s:dataFileAvailable = 0
+ return
+ endif
+ let versionPath = l9#concatPaths([g:fuf_dataDir, 'VERSION'])
+ let lines = l9#readFile(versionPath)
+ if empty(lines)
+ call l9#writeFile([s:DATA_FILE_VERSION], versionPath)
+ let s:dataFileAvailable = 1
+ elseif str2nr(lines[0]) == s:DATA_FILE_VERSION
+ let s:dataFileAvailable = 1
+ else
+ call fuf#echoWarning(printf(
+ \ "=======================================================\n" .
+ \ " Existing data files for FuzzyFinder is no longer \n" .
+ \ " compatible with this version of FuzzyFinder. Remove \n" .
+ \ " %-53s\n" .
+ \ "=======================================================\n" ,
+ \ string(g:fuf_dataDir)))
+ call l9#inputHl('Question', 'Press Enter')
+ let s:dataFileAvailable = 0
+ endif
+endfunction
+
+call s:checkDataFileCompatibility()
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+
diff --git a/autoload/fuf/bookmarkdir.vim b/autoload/fuf/bookmarkdir.vim
new file mode 100644
index 0000000..20d10a8
--- /dev/null
+++ b/autoload/fuf/bookmarkdir.vim
@@ -0,0 +1,163 @@
+"=============================================================================
+" Copyright (c) 2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/bookmarkfile.vim b/autoload/fuf/bookmarkfile.vim
new file mode 100644
index 0000000..41d1493
--- /dev/null
+++ b/autoload/fuf/bookmarkfile.vim
@@ -0,0 +1,199 @@
+"=============================================================================
+" Copyright (c) 2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/buffer.vim b/autoload/fuf/buffer.vim
new file mode 100644
index 0000000..1a302ca
--- /dev/null
+++ b/autoload/fuf/buffer.vim
@@ -0,0 +1,189 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/buffertag.vim b/autoload/fuf/buffertag.vim
new file mode 100644
index 0000000..392b996
--- /dev/null
+++ b/autoload/fuf/buffertag.vim
@@ -0,0 +1,300 @@
+"=============================================================================
+" 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:
diff --git a/autoload/fuf/callbackfile.vim b/autoload/fuf/callbackfile.vim
new file mode 100644
index 0000000..4d2d269
--- /dev/null
+++ b/autoload/fuf/callbackfile.vim
@@ -0,0 +1,137 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/callbackitem.vim b/autoload/fuf/callbackitem.vim
new file mode 100644
index 0000000..f74747f
--- /dev/null
+++ b/autoload/fuf/callbackitem.vim
@@ -0,0 +1,139 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/changelist.vim b/autoload/fuf/changelist.vim
new file mode 100644
index 0000000..8caf7ba
--- /dev/null
+++ b/autoload/fuf/changelist.vim
@@ -0,0 +1,172 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
+
diff --git a/autoload/fuf/coveragefile.vim b/autoload/fuf/coveragefile.vim
new file mode 100644
index 0000000..f7e3068
--- /dev/null
+++ b/autoload/fuf/coveragefile.vim
@@ -0,0 +1,194 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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, '""')
+ 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),
+ \ 'split(glob(v:val), "\n")'))
+ call filter(s:cache[key], 'filereadable(v:val)')
+ 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])
+ call feedkeys(":FufCoverageFile\<CR>", 'n')
+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_coveragefile_prompt, self.partialMatching,
+ \ string(g:fuf_coveragefile_globPatterns))
+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 = s:enumItems()
+ call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')
+endfunction
+
+"
+function s:handler.onModeLeavePost(opened)
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
diff --git a/autoload/fuf/dir.vim b/autoload/fuf/dir.vim
new file mode 100644
index 0000000..1cade37
--- /dev/null
+++ b/autoload/fuf/dir.vim
@@ -0,0 +1,132 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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(
+ \ split(glob(fnamemodify(a:word, ':p') . '*'), "\n"),
+ \ [], 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:
diff --git a/autoload/fuf/file.vim b/autoload/fuf/file.vim
new file mode 100644
index 0000000..c2a6ee7
--- /dev/null
+++ b/autoload/fuf/file.vim
@@ -0,0 +1,139 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/givencmd.vim b/autoload/fuf/givencmd.vim
new file mode 100644
index 0000000..ca24639
--- /dev/null
+++ b/autoload/fuf/givencmd.vim
@@ -0,0 +1,123 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/givendir.vim b/autoload/fuf/givendir.vim
new file mode 100644
index 0000000..f4401ba
--- /dev/null
+++ b/autoload/fuf/givendir.vim
@@ -0,0 +1,123 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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(
+ \ split(glob(fnamemodify(a:word, ':p') . '*'), "\n"),
+ \ [], 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:
diff --git a/autoload/fuf/givenfile.vim b/autoload/fuf/givenfile.vim
new file mode 100644
index 0000000..0e69b8d
--- /dev/null
+++ b/autoload/fuf/givenfile.vim
@@ -0,0 +1,121 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/help.vim b/autoload/fuf/help.vim
new file mode 100644
index 0000000..9f807cd
--- /dev/null
+++ b/autoload/fuf/help.vim
@@ -0,0 +1,198 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/jumplist.vim b/autoload/fuf/jumplist.vim
new file mode 100644
index 0000000..959d93d
--- /dev/null
+++ b/autoload/fuf/jumplist.vim
@@ -0,0 +1,182 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
+
diff --git a/autoload/fuf/line.vim b/autoload/fuf/line.vim
new file mode 100644
index 0000000..efe78bf
--- /dev/null
+++ b/autoload/fuf/line.vim
@@ -0,0 +1,135 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/mrucmd.vim b/autoload/fuf/mrucmd.vim
new file mode 100644
index 0000000..fe4d1ed
--- /dev/null
+++ b/autoload/fuf/mrucmd.vim
@@ -0,0 +1,134 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/mrufile.vim b/autoload/fuf/mrufile.vim
new file mode 100644
index 0000000..cd8acbe
--- /dev/null
+++ b/autoload/fuf/mrufile.vim
@@ -0,0 +1,225 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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, '""')
+ 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:listAroundFilesUsingCache(dir)
+ if !exists('s:aroundCache[a:dir]')
+ let s:aroundCache[a:dir] = [a:dir] +
+ \ split(glob(a:dir . l9#getPathSeparator() . "*" ), "\n") +
+ \ split(glob(a:dir . l9#getPathSeparator() . ".*"), "\n")
+ 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 levelString = (g:fuf_mrufile_searchAroundLevel < 0 ? ''
+ \ : '[Around:' . g:fuf_mrufile_searchAroundLevel . ']')
+ return fuf#formatPrompt(g:fuf_mrufile_prompt, self.partialMatching, 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 . ')')
+ " NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
+ let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~')
+ 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:listAroundFilesUsingCache(v:val)')
+ let self.items = l9#concat(self.items)
+ endif
+ call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')
+ call fuf#mapToSetSerialIndex(self.items, 1)
+ call fuf#mapToSetAbbrWithSnippedWordAsPath(self.items)
+endfunction
+
+"
+function s:handler.onModeLeavePost(opened)
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
diff --git a/autoload/fuf/quickfix.vim b/autoload/fuf/quickfix.vim
new file mode 100644
index 0000000..926a717
--- /dev/null
+++ b/autoload/fuf/quickfix.vim
@@ -0,0 +1,154 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
+
diff --git a/autoload/fuf/tag.vim b/autoload/fuf/tag.vim
new file mode 100644
index 0000000..814f79e
--- /dev/null
+++ b/autoload/fuf/tag.vim
@@ -0,0 +1,178 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/fuf/taggedfile.vim b/autoload/fuf/taggedfile.vim
new file mode 100644
index 0000000..e4313cf
--- /dev/null
+++ b/autoload/fuf/taggedfile.vim
@@ -0,0 +1,159 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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:
diff --git a/autoload/l9.vim b/autoload/l9.vim
new file mode 100644
index 0000000..4ae3ce2
--- /dev/null
+++ b/autoload/l9.vim
@@ -0,0 +1,552 @@
+"=============================================================================
+" 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 = 100
+let s:L9_VERSION_COMPATIBLE = 0
+
+" returns true if given version is compatible.
+function l9#isCompatible(ver)
+ return (s:L9_VERSION_COMPATIBLE <= a:ver && a:ver <= s:L9_VERSION_CURRENT)
+endfunction
+
+let s:VERSION_FACTOR = str2float('0.01')
+
+" returns false if the caller script should finish.
+" l9Version: same rule as v:version
+function l9#guardScriptLoading(path, vimVersion, l9Version)
+ let loadedVarName = 'g:loaded_' . substitute(a:path, '\W', '_', 'g')
+ if exists(loadedVarName)
+ return 0
+ elseif v:version < a:vimVersion
+ echoerr a:path . ' requires Vim version ' . string(a:vimVersion * s:VERSION_FACTOR)
+ return 0
+ elseif !exists('*l9#isCompatible') || !l9#isCompatible(a:l9Version)
+ echoerr a:path . ' requires L9 library version ' . string(a:l9Version * s:VERSION_FACTOR)
+ return 0
+ endif
+ 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
+
+" 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:
diff --git a/autoload/l9/async.py b/autoload/l9/async.py
new file mode 100644
index 0000000..eeb0cc3
--- /dev/null
+++ b/autoload/l9/async.py
@@ -0,0 +1,92 @@
+#!/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()
+
+
diff --git a/autoload/l9/async.vim b/autoload/l9/async.vim
new file mode 100644
index 0000000..1053d97
--- /dev/null
+++ b/autoload/l9/async.vim
@@ -0,0 +1,67 @@
+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100) || !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:
+
+
diff --git a/autoload/l9/quickfix.vim b/autoload/l9/quickfix.vim
new file mode 100644
index 0000000..5dcded3
--- /dev/null
+++ b/autoload/l9/quickfix.vim
@@ -0,0 +1,107 @@
+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion())
+ 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:
+
diff --git a/autoload/l9/tempbuffer.vim b/autoload/l9/tempbuffer.vim
new file mode 100644
index 0000000..f5c3beb
--- /dev/null
+++ b/autoload/l9/tempbuffer.vim
@@ -0,0 +1,112 @@
+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion())
+ 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:
+
diff --git a/autoload/l9/tempvariables.vim b/autoload/l9/tempvariables.vim
new file mode 100644
index 0000000..9ea51c2
--- /dev/null
+++ b/autoload/l9/tempvariables.vim
@@ -0,0 +1,68 @@
+"=============================================================================
+" Copyright (C) 2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion())
+ finish
+endif
+
+" }}}1
+"=============================================================================
+" TEMPORARY VARIABLES {{{1
+
+"
+let s:varsMap = {}
+
+" set temporary variables
+function l9#tempvariables#set(group, name, value)
+ if !exists('s:varsMap[a:group]')
+ let s:varsMap[a:group] = {'vars': {}, 'active': 1}
+ endif
+ if !exists('s:varsMap[a:group].vars[a:name]')
+ let s:varsMap[a:group].vars[a:name] = {'original': eval(a:name)}
+ endif
+ let s:varsMap[a:group].vars[a:name].temp = a:value
+ if s:varsMap[a:group].active
+ execute 'let ' . a:name . ' = a:value'
+ endif
+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
+
+" swap temporary variables and original variables
+function l9#tempvariables#swap(group)
+ if s:varsMap[a:group].active
+ let variables = map(copy(s:varsMap[a:group].vars), 'v:val.original')
+ else
+ let variables = map(copy(s:varsMap[a:group].vars), 'v:val.temp')
+ endif
+ for [name, value] in items(variables)
+ execute 'let ' . name . ' = value'
+ unlet value " to avoid E706
+ endfor
+ let s:varsMap[a:group].active = !s:varsMap[a:group].active
+endfunction
+
+" restore original variables and clean up.
+function l9#tempvariables#end(group)
+ if !exists('s:varsMap[a:group]')
+ return
+ endif
+ if s:varsMap[a:group].active
+ call l9#tempvariables#swap(a:group)
+ endif
+ unlet s:varsMap[a:group]
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+
diff --git a/autoload/sample_vimrc_for_new_users.vim b/autoload/sample_vimrc_for_new_users.vim
new file mode 100644
index 0000000..b458cab
--- /dev/null
+++ b/autoload/sample_vimrc_for_new_users.vim
@@ -0,0 +1,219 @@
+" kept recoding the same things over and over again.
+" So I write what I think is useful to you here.
+"
+" How to use?
+" Either copy paste contents into your .vimrc (omitting the Load function)
+" or call the load function
+
+
+" these markers { { { enable folding. see modeline at the bottom
+" You don't have to close them if you append the folding level.
+
+" set nocompatible should be default. This should be the first line:
+set nocompatible
+
+
+" You should have this in your .vimrc:
+" (The {{ { starts a fold.
+" type zR to open all or za to open one fold only
+" zM folds everything again
+
+" enable filetype, plugin and syntax support {{{1
+" This means
+filetype indent plugin on | syn on
+
+" allow buffers to go in background without saving etc.
+set hidden
+
+" useful mappings: {{{1
+
+" open this file fast so that you can take notes below the line "finish" and
+" add more mappings:
+noremap \c :e ~/.vimrc<cr>
+
+" :w! is always bad to type. So create your own mapping for it. Example:
+noremap \w :w!<cr>
+
+" you may want to remove the <c-d> if you have many files opened
+" This switches buffers
+" Note: :b foo will also select some-foo-text.txt file if it was opened :)
+noremap \b :b<space><c-d>
+
+" being able to open the help fast is always fine.
+" note that you can use tab / shift -tab to select next / previous match
+" also glob patterns are allowed. Eg :h com*func<tab>
+noremap \h :h<space>
+
+" open one file, use tab and shift-tab again if there are multiple files
+" after using this mapping the command line should have started showing
+" :e **/* . Eg use :e **/*fil*txt to match file.txt in any subdir
+noremap \e :e<space>**/*
+
+" open multiple files at once. Eg add .txt to open all .txt files
+" Using :bn @: you can cycle them all
+" :bn = :bnext @: repeats last command
+noremap \n :n<space>**/*
+
+" foreign plugin vim-addon-manager {{{1
+
+" commenting this code because I assume you already have it in your ~/.vimrc:
+
+ " tell Vim where to find the autoload function:
+" set runtimepath+=~/vim-plugins/vim-addon-manager
+
+" Activate the addons called 'JSON', 'name1', 'name2'
+" This adds them to runtimepath and ensures that plugin/* and after/plugin/*
+" files are sourced. JSON is not that important. It highlights the
+" NAME-addon-info.txt files. Probably you want to substitude nameN by plugins
+" such as snipMate, tlib etc.
+
+" call scriptmanager#Activate(['JSON',"name1","name2"])
+
+" foreign plugins tlib {{{1
+
+" this is from tlib. I highly recommend having a look at that library.
+noremap \r :TRecentlyUsedFiles<cr>
+" disable some plugins. Maybe you don't want all..
+let loaded_cmdlinehelp=1
+let loaded_concordance=1
+let loaded_evalselection=1
+let loaded_glark=1
+let loaded_hookcursormoved=1
+let loaded_linglang=1
+let loaded_livetimestamp=1
+let loaded_localvariables=1
+let loaded_loremipsum=1
+let loaded_my_tinymode=1
+let loaded_netrwPlugin=1
+let loaded_pim=1
+let loaded_quickfixsigns=1
+let loaded_scalefont=1
+let loaded_setsyntax=1
+let loaded_shymenu=1
+let loaded_spec=1
+let loaded_tassert=1
+let loaded_tbak=1
+let loaded_tbibtools=1
+let loaded_tcalc=1
+let loaded_tcomment=1
+let loaded_techopair=1
+let loaded_tgpg=1
+let loaded_tlog=1
+let loaded_tmarks=1
+let loaded_tmboxbrowser=1
+let loaded_tmru=1
+let loaded_tortoisesvn=1
+let loaded_tregisters=1
+let loaded_tselectbuffer=1
+let loaded_tselectfile=1
+let loaded_tsession=1
+let loaded_tskeleton=1
+let loaded_tstatus=1
+let loaded_ttagcomplete=1
+let loaded_ttagecho=1
+let loaded_ttags=1
+"let loaded_ttoc=1
+let loaded_viki=1
+let loaded_vikitasks=1
+
+
+
+" dummy func to enabling you to load this file after adding the top level {{{1
+" dir to runtimepath using :set runtimpeth+=ROOT
+fun! sample_vimrc_for_new_users#Load()
+ " no code. If this function is called this file is sourced
+endf
+
+finish
+
+MY COMMENTS ABOUT VIM AND ITS USAGE {{{1
+========================================
+Vim is ignoring this text after finish.
+
+
+I like Vim cause its that fast and easy to extend.
+I also learned that VimL is a nice language. It was ahead of time when it
+was invented. However today it can be considered limiting in various ways.
+Eg you don't want to write parsers in it. Its too slow for those use cases.
+Yet its powerful enough to make everyday easier - even competitive to bloated
+IDEs. Example plugins you should know about:
+
+- tlib library
+
+- snipmate (or xptemplate): Insert text snippets. Its not only about speed.
+ Snippets are a nice way to organize your memos.
+
+- matchit: match everything, eg matching xml tags, fun -> return -> endfun
+ statements (same for for, while etc)
+
+- The_NERD_tree: directory tree in Vim. You can easily hit the limits of
+ Vim/VimL here whene opening large directories it takes a way too long :-(
+ Yet you may find it useful.
+
+- commenting plugins
+
+- ... (You want a plugin added here?)
+
+What you should know about:
+- :h motion.txt (skim it once)
+- Vim keeps history as tree.
+- :h quickfix (load compiler output into an error list)
+- how to use tags - because this (sometimes fuzzzy) thing
+ is still fast to setup and works very well for many use cases.
+- Vim can assist you in spelling
+
+
+most important mappings / commands:
+g; = jump back in list of last edited locations
+<c-o> <c-i> = jump back and forth in location list
+<c-^> = toggle buffers
+
+q:, ?:, /: : Open mini buffer to browse or edit command or search history
+ You can open this from command line using <c-f>!
+... I could keep writing for 2 hours now at least.
+
+
+I'm also aware of Emacs emulating most important editing features of Vim.
+Eg there is the vimpulse plugin for Emacs. So I know that I should use the
+tool which is best for a given task. This can be Vim for coding. But for debugging
+you may prefer Emacs or a bloated IDE such as Eclipse, Netbeans, IDEA (which all have
+vim like keybindgs!).
+
+What are the limitations causing greatest impact to software developers using Vim?
+- no async communication support unless you depend on client-server feature
+ which requires X. This means Vim will hang until an operation has finished
+ when interfacing with external tools.
+ Impact: People tried writing debugger features. But all solutions are kind
+ of doomed unless Vim gets a nice async communication interface.
+- Many coding helpers should not have been written in VimL. They should have
+ been written in a proper language so that all open source editors can
+ benefit from their features. An Example is the broken PHP completion which
+ doesn't even complete static member functions like A::foo();
+
+ Examples how this can be done better:
+ * vim-addon-scion (Haskell development helper app is written in Haskell. Vim
+ is only a coding editor backend)
+ * codefellow (same for Scala).
+
+Vim can be one of the fastest editors you'll start to love (and hate)
+
+
+" additional resources - how to continue learning about Vim? {{{1
+The way to start learning Vim:
+vimtutor
+
+additional advanced info:
+http://github.com/dahu/LearnVim
+
+Vim Wiki:
+http://vim.wikia.com
+
+join #vim (irc.freenode.net)
+
+join the mailinglist (www.vim.org -> community)
+
+Tell me to add additional resources here
+
+
+" this modeline tells vim to enable folding {{{1
+" vim: fdm=marker
diff --git a/autoload/scriptmanager.vim b/autoload/scriptmanager.vim
new file mode 100644
index 0000000..a057b82
--- /dev/null
+++ b/autoload/scriptmanager.vim
@@ -0,0 +1,244 @@
+" see README
+
+" this file contains code which is always used
+" code which is used for installing / updating etc should go into scriptmanager2.vim
+
+
+" don't need a plugin. If you want to use this plugin you call Activate once
+" anyway
+augroup SCRIPT_MANAGER
+ autocmd!
+ autocmd BufRead,BufNewFile *-addon-info.txt
+ \ setlocal ft=addon-info
+ \ | setlocal syntax=json
+ \ | syn match Error "^\s*'"
+ autocmd BufWritePost *-addon-info.txt call scriptmanager#ReadAddonInfo(expand('%'))
+augroup end
+
+fun! scriptmanager#DefineAndBind(local,global,default)
+ return 'if !exists('.string(a:global).') | let '.a:global.' = '.a:default.' | endif | let '.a:local.' = '.a:global
+endf
+
+
+" assign g:os
+for os in split('amiga beos dos32 dos16 mac macunix os2 qnx unix vms win16 win32 win64 win32unix', ' ')
+ if has(os) | let g:os = os | break | endif
+endfor
+let g:is_win = g:os[:2] == 'win'
+
+exec scriptmanager#DefineAndBind('s:c','g:vim_script_manager','{}')
+let s:c['config'] = get(s:c,'config',expand('$HOME').'/.vim-script-manager')
+let s:c['auto_install'] = get(s:c,'auto_install', 0)
+" repository locations:
+let s:c['plugin_sources'] = get(s:c,'plugin_sources', {})
+" if a plugin has an item here the dict value contents will be written as plugin info file
+let s:c['missing_addon_infos'] = get(s:c,'missing_addon_infos', {})
+" addon_infos cache, {} if file dosen't exist
+let s:c['addon_infos'] = get(s:c,'addon_infos', {})
+let s:c['activated_plugins'] = get(s:c,'activaded_plugins', {})
+" If file is writeable, then this plugin was likely installed by user according
+" to the instruction. If it is not, then it is likely a system-wide
+" installation
+let s:c['plugin_root_dir'] = get(s:c, 'plugin_root_dir', ((filewritable(expand('<sfile>')))?
+ \ (fnamemodify(expand('<sfile>'),':h:h:h')):
+ \ ('~/vim-addons')))
+" ensure we have absolute paths (windows doesn't like ~/.. ) :
+let s:c['plugin_root_dir'] = expand(s:c['plugin_root_dir'])
+let s:c['known'] = get(s:c,'known','vim-addon-manager-known-repositories')
+
+if g:is_win
+ " if binary-utils path exists then add it to PATH
+ let s:c['binary_utils'] = get(s:c,'binary_utils',s:c['plugin_root_dir'].'\binary-utils')
+ let s:c['binary_utils_bin'] = s:c['binary_utils'].'\dist\bin'
+ if isdirectory(s:c['binary_utils'])
+ let $PATH=$PATH.';'.s:c['binary_utils_bin']
+ endif
+endif
+
+" additional plugin sources should go into your .vimrc or into the repository
+" called "vim-addon-manager-known-repositories" referenced here:
+let s:c['plugin_sources']["vim-addon-manager-known-repositories"] = { 'type' : 'git', 'url': 'git://github.com/MarcWeber/vim-addon-manager-known-repositories.git' }
+
+fun! scriptmanager#VerifyIsJSON(s)
+ let stringless_body = substitute(a:s,'"\%(\\.\|[^"\\]\)*"','','g')
+ return stringless_body !~# "[^,:{}\\[\\]0-9.\\-+Eaeflnr-u \t]"
+endf
+
+" use join so that you can break the dict into multiple lines. This makes
+" reading it much easier
+fun! scriptmanager#ReadAddonInfo(path)
+ if a:path =~ 'tlib/plugin-info.txt$'
+ " I'll ask Tom Link to change this when vim-addon-manager is more stable
+ return eval(join(readfile(a:path, "b"),""))
+ endif
+
+ " using eval is evil!
+ let body = join(readfile(a:path, "b"),"")
+
+ if scriptmanager#VerifyIsJSON(body)
+ " using eval is now safe!
+ return eval(body)
+ else
+ echoe "Invalid JSON in ".a:path."!"
+ return {}
+ endif
+
+endf
+
+fun! scriptmanager#PluginDirByName(name)
+ return s:c['plugin_root_dir'].'/'.a:name
+endf
+fun! scriptmanager#PluginRuntimePath(name)
+ let info = scriptmanager#AddonInfo(a:name)
+ return s:c['plugin_root_dir'].'/'.a:name.(has_key(info, 'runtimepath') ? '/'.info['runtimepath'] : '')
+endf
+
+" doesn't check dependencies!
+fun! scriptmanager#IsPluginInstalled(name)
+ return isdirectory(scriptmanager#PluginDirByName(a:name))
+endf
+
+" {} if file doesn't exist
+fun! scriptmanager#AddonInfo(name)
+ let infoFile = scriptmanager#AddonInfoFile(a:name)
+ let s:c['addon_infos'][a:name] = filereadable(infoFile)
+ \ ? scriptmanager#ReadAddonInfo(infoFile)
+ \ : {}
+ return get(s:c['addon_infos'],a:name, {})
+endf
+
+
+" opts: {
+" 'plugin_sources': additional sources (used when installing dependencies)
+" 'auto_install': when 1 overrides global setting, so you can autoinstall
+" trusted repositories only
+" }
+fun! scriptmanager#ActivateRecursively(list_of_names, ...)
+ let opts = a:0 == 0 ? {} : a:1
+
+ for name in a:list_of_names
+ if !has_key(s:c['activated_plugins'], name)
+ " break circular dependencies..
+ let s:c['activated_plugins'][name] = 0
+
+ let infoFile = scriptmanager#AddonInfoFile(name)
+ if !filereadable(infoFile) && !scriptmanager#IsPluginInstalled(name)
+ call scriptmanager2#Install([name], opts)
+ endif
+ let info = scriptmanager#AddonInfo(name)
+ let dependencies = get(info,'dependencies', {})
+
+ " activate dependencies merging opts with given repository sources
+ " sources given in opts will win
+ call scriptmanager#Activate(keys(dependencies),
+ \ extend(copy(opts), { 'plugin_sources' : extend(copy(dependencies), get(opts, 'plugin_sources',{}))}))
+ endif
+ " source plugin/* files ?
+ let rtp = scriptmanager#PluginRuntimePath(name)
+ call add(s:new_runtime_paths, rtp)
+
+ let s:c['activated_plugins'][name] = 1
+ endfor
+endf
+
+" see also ActivateRecursively
+" Activate activates the plugins and their dependencies recursively.
+" I sources both: plugin/*.vim and after/plugin/*.vim files when called after
+" .vimrc has been sourced which happens when you activate plugins manually.
+fun! scriptmanager#Activate(...) abort
+ let args = copy(a:000)
+
+ if type(args[0])==type("")
+ " way of usage 1: pass addon names as function arguments
+ " Example: Activate("name1","name2")
+
+ let args=[args, {}]
+ else
+ " way of usage 2: pass addon names as list optionally passing options
+ " Example: Activate(["name1","name2"], { options })
+
+ let args=[args[0], get(args,1,{})]
+ endif
+
+ " now opts should be defined
+ " args[0] = plugin names
+ " args[1] = options
+
+ let opts = args[1]
+ let topLevel = get(opts,'topLevel',1)
+ let opts['topLevel'] = 0
+ let active = copy(s:c['activated_plugins'])
+ if topLevel | let s:new_runtime_paths = [] | endif
+ call call('scriptmanager#ActivateRecursively', args)
+
+ if topLevel
+ " deferred tasks:
+ " - add addons to runtimepath
+ " - add source plugin/**/*.vim files in case Activate was called long
+ " after .vimrc has been sourced
+
+ " add paths after ~/.vim but before $VIMRUNTIME
+ " don't miss the after directories if they exist and
+ " put them last! (Thanks to Oliver Teuliere)
+ let rtp = split(&runtimepath,'\(\\\@<!\(\\.\)*\\\)\@<!,')
+ let &runtimepath=join(rtp[:0] + s:new_runtime_paths + rtp[1:]
+ \ + filter(map(copy(s:new_runtime_paths),'v:val."/after"'), 'isdirectory(v:val)') ,",")
+ unlet rtp
+
+ if has_key(s:c, 'started_up')
+ for rtp in s:new_runtime_paths
+ call scriptmanager#GlobThenSource(rtp.'/plugin/**/*.vim')
+ call scriptmanager#GlobThenSource(rtp.'/after/plugin/**/*.vim')
+ endfor
+ endif
+ endif
+
+ if has_key(s:c, 'started_up')
+ " now source after/plugin/**/*.vim files explicitely. Vim doesn't do it (hack!)
+ for k in keys(s:c['activated_plugins'])
+ if !has_key(active, k)
+ let rtp = scriptmanager#PluginRuntimePath(k)
+ call scriptmanager#GlobThenSource(rtp.'/plugin/**/*.vim')
+ call scriptmanager#GlobThenSource(rtp.'/after/plugin/**/*.vim')
+ endif
+ endfor
+ endif
+endfun
+
+fun! scriptmanager#GlobThenSource(glob)
+ for file in split(glob(a:glob),"\n")
+ exec 'source '.fnameescape(file)
+ endfor
+endf
+
+augroup VIM_PLUGIN_MANAGER
+ autocmd VimEnter * call scriptmanager#Hack()
+augroup end
+
+" hack: Vim sources plugin files after sourcing .vimrc
+" Vim doesn't source the after/plugin/*.vim files in other runtime
+" paths. So do this *after* plugin/* files have been sourced
+fun! scriptmanager#Hack()
+ let s:c['started_up'] = 1
+
+ " now source after/plugin/**/*.vim files explicitly. Vim doesn't do it (hack!)
+ for p in keys(s:c['activated_plugins'])
+ call scriptmanager#GlobThenSource(scriptmanager#PluginDirByName(p).'/after/plugin/**/*.vim')
+ endfor
+endf
+
+fun! scriptmanager#AddonInfoFile(name)
+ " this name is deprecated
+ let f = scriptmanager#PluginDirByName(a:name).'/plugin-info.txt'
+ if filereadable(f)
+ return f
+ else
+ return scriptmanager#PluginDirByName(a:name).'/'.a:name.'-addon-info.txt'
+ endif
+endf
+
+command! -nargs=* -complete=customlist,scriptmanager2#AddonCompletion ActivateAddons :call scriptmanager#Activate([<f-args>])
+command! -nargs=* -complete=customlist,scriptmanager2#InstalledAddonCompletion ActivateInstalledAddons :call scriptmanager#Activate([<f-args>])
+command! -nargs=* -complete=customlist,scriptmanager2#AddonCompletion UpdateAddons :call scriptmanager2#Update([<f-args>])
+command! -nargs=* -complete=customlist,scriptmanager2#UninstallCompletion UninstallNotLoadedAddons :call scriptmanager2#UninstallAddons([<f-args>])
+
diff --git a/autoload/scriptmanager2.vim b/autoload/scriptmanager2.vim
new file mode 100644
index 0000000..9042e62
--- /dev/null
+++ b/autoload/scriptmanager2.vim
@@ -0,0 +1,495 @@
+" scriptmanager2 contains code which is used when install plugins only
+
+let s:curl = exists('g:netrw_http_cmd') ? g:netrw_http_cmd : 'curl -o'
+exec scriptmanager#DefineAndBind('s:c','g:vim_script_manager','{}')
+
+
+let s:system_wide = !filewritable(expand('<sfile>'))
+
+" Install let's you install plugins by passing the url of a addon-info file
+" This preprocessor replaces the urls by the plugin-names putting the
+" repository information into the global dict
+fun! scriptmanager2#ReplaceAndFetchUrls(list)
+ let l = a:list
+ let idx = 0
+ for idx in range(0, len(l)-1)
+ silent! unlet t
+ let n = l[idx]
+ " assume n is either an url or a path
+ if n =~ '^http://' && 'y' == input('Fetch plugin info from url '.n.' [y/n]')
+ let t = tempfile()
+ exec '!'.s:curl.' '.t.' > '.s:shellescape(t)
+ elseif n =~ '[/\\]' && filereadable(n)
+ let t = n
+ endif
+ if exists('t')
+ let dic = scriptmanager#ReadAddonInfo(t)
+ if !has_key(dic,'name') || !has_key(dic, 'repository')
+ echoe n." is no valid addon-info file. It must contain both keys: name and repository"
+ continue
+ endif
+ let s:c['plugin_sources'][dic['name']] = dic['repository']
+ let l[idx] = dic['name']
+ endif
+ endfor
+ return l
+endfun
+
+
+" opts: same as Activate
+fun! scriptmanager2#Install(toBeInstalledList, ...)
+ let toBeInstalledList = scriptmanager2#ReplaceAndFetchUrls(a:toBeInstalledList)
+ let opts = a:0 == 0 ? {} : a:1
+ for name in toBeInstalledList
+ if scriptmanager#IsPluginInstalled(name)
+ continue
+ endif
+
+ " ask user for to confirm installation unless he set auto_install
+ if s:c['auto_install'] || get(opts,'auto_install',0) || input('Install plugin '.name.'? [y/n]:','') == 'y'
+
+ if name != s:c['known'] | call scriptmanager2#LoadKnownRepos() | endif
+
+ let repository = get(s:c['plugin_sources'], name, get(opts, name,0))
+
+ if type(repository) == type(0) && repository == 0
+ echoe "No repository location info known for plugin ".name."!"
+ return
+ endif
+
+ let d = get(repository, 'deprecated', '')
+ if type(d) == type('') && d != ''
+ echom "Deprecation warning package ".name. ":"
+ echom d
+ if 'y' != input('Plugin '.name.' is deprecated. See warning above. Install it? [y/n]','n')
+ continue
+ endif
+ endif
+
+ let pluginDir = scriptmanager#PluginDirByName(name)
+ let infoFile = scriptmanager#AddonInfoFile(name)
+ call scriptmanager2#Checkout(pluginDir, repository)
+
+ if !filereadable(infoFile) && has_key(s:c['missing_addon_infos'], name)
+ call writefile([s:c['missing_addon_infos'][name]], infoFile)
+ endif
+
+ " install dependencies
+
+ let infoFile = scriptmanager#AddonInfoFile(name)
+ let info = scriptmanager#AddonInfo(name)
+
+ let dependencies = get(info,'dependencies', {})
+
+ " install dependencies merging opts with given repository sources
+ " sources given in opts will win
+ call scriptmanager2#Install(keys(dependencies),
+ \ extend(copy(opts), { 'plugin_sources' : extend(copy(dependencies), get(opts, 'plugin_sources',{}))}))
+ endif
+ call scriptmanager2#HelpTags(name)
+ endfor
+endf
+
+" this function will be refactored slightly soon by either me or Zyx.
+fun! scriptmanager2#UpdateAddon(name)
+ let pluginDir = scriptmanager#PluginDirByName(a:name)
+ if !vcs_checkouts#Update(pluginDir)
+ " try updating plugin by archive
+
+ " dose the user have made any changes? :
+ let pluginDir = scriptmanager#PluginDirByName(a:name)
+ let backup = scriptmanager#PluginDirByName(a:name).'.backup'
+ let container = fnamemodify(backup,':h')
+ let diff_file = containing.'/'.a:name.'.diff-orig'
+
+ if executable('diff') && isdirectory(backup)
+ call s:exec_in_dir([{'c':'diff -r '.s:shellescape(r.'/plugin').' '.s:shellescape(r.'/plugin-merged')}])
+ endif
+
+ if filereadable(pluginDir.'/version')
+ let pluginversion = get(readfile(pluginDir.'/version'), 0, "?")
+ let repository = get(s:c['plugin_sources'], a:name, {})
+ if empty(repository)
+ echoe "Cannot update plugin ".a:name.": no repository locations known."
+ return
+ endif
+ let newpluginversion = get(repository, 'version', '?')
+ if newpluginversion==#'?'
+ echoe "Cannot update plugin ".a:name.": no version information is available."
+ elseif pluginversion==#newpluginversion
+ " Though we are not updating plugin, this is not an error
+ return 1
+ endif
+ if scriptmanager2#Checkout(pluginDir, repository)
+ return
+ endif
+ return 1
+ endif
+ return
+ endif
+ return 1
+endf
+
+fun! scriptmanager2#Update(list)
+ let list = a:list
+ if empty(list) && input('Update all loaded plugins? [y/n] ','y') == 'y'
+ call scriptmanager2#LoadKnownRepos(' so that its updated as well')
+ " include vim-addon-manager in list
+ if !s:system_wide
+ call scriptmanager#Activate(['vim-addon-manager'])
+ endif
+ let list = keys(s:c['activated_plugins'])
+ endif
+ let failed = []
+ for p in list
+ if scriptmanager2#UpdateAddon(p)
+ call scriptmanager2#HelpTags(p)
+ else
+ call add(failed,p)
+ endif
+ endfor
+ if !empty(failed)
+ echoe "Failed updating plugins: ".string(failed)."."
+ endif
+endf
+
+" completion {{{
+
+" optional arg = 0: only installed
+" arg = 1: installed and names from known-repositories
+fun! scriptmanager2#KnownAddons(...)
+ let installable = a:0 > 0 ? a:1 : 0
+ let list = map(split(glob(scriptmanager#PluginDirByName('*')),"\n"),"fnamemodify(v:val,':t')")
+ let list = filter(list, 'isdirectory(v:val)')
+ if installable == "installable"
+ call scriptmanager2#LoadKnownRepos()
+ call extend(list, keys(s:c['plugin_sources']))
+ endif
+ " uniq items:
+ let dict = {}
+ for name in list
+ let dict[name] = 1
+ endfor
+ return keys(dict)
+endf
+
+fun! scriptmanager2#DoCompletion(A,L,P,...)
+ let config = a:0 > 0 ? a:1 : 0
+ let names = scriptmanager2#KnownAddons(config)
+
+ let beforeC= a:L[:a:P-1]
+ let word = matchstr(beforeC, '\zs\S*$')
+ " ollow glob patterns
+ let word = substitute('\*','.*',word,'g')
+
+ let not_loaded = config == "uninstall"
+ \ ? " && index(keys(s:c['activated_plugins']), v:val) == -1"
+ \ : ''
+
+ return filter(names,'v:val =~ '.string(word) . not_loaded)
+endf
+
+fun! scriptmanager2#AddonCompletion(...)
+ return call('scriptmanager2#DoCompletion',a:000+["installable"])
+endf
+
+fun! scriptmanager2#InstalledAddonCompletion(...)
+ return call('scriptmanager2#DoCompletion',a:000)
+endf
+
+fun! scriptmanager2#UninstallCompletion(...)
+ return call('scriptmanager2#DoCompletion',a:000+["uninstall"])
+endf
+"}}}
+
+
+fun! scriptmanager2#UninstallAddons(list)
+ let list = a:list
+ if list == []
+ echo "No plugins selected. If you ran UninstallNotLoadedAddons use <tab> or <c-d> to get a list of not loaded plugins."
+ return
+ endif
+ call map(list, 'scriptmanager#PluginDirByName(v:val)')
+ if input('Confirm running rm -fr on directories: '.join(list,", ").'? [y/n]') == 'y'
+ for path in list
+ exec '!rm -fr '.s:shellescape(path)
+ endfor
+ endif
+endf
+
+fun! scriptmanager2#HelpTags(name)
+ let d=scriptmanager#PluginDirByName(a:name).'/doc'
+ if isdirectory(d) | exec 'helptags '.d | endif
+endf
+
+" " if --strip-components fails finish this workaround:
+" " emulate it in VimL
+" fun! s:StripComponents(targetDir, num)
+" let dostrip = 1*a:num
+" while x in range(1, 1*a:num)
+" let dirs = split(glob(a:targetDir.'/*'),"\n")
+" if len(dirs) > 1
+" throw "can't strip, multiple dirs found!"
+" endif
+" for f in split(glob(dirs[0].'/*'),"\n")
+" call rename(file_or_dir, fnamemodify(f,':h:h').'/'.fnamemodify(f,':t'))
+" endfor
+" call remove_dir_or_file(fnamemodify(f,':h'))
+" endwhile
+" endfun
+
+
+" may throw EXCEPTION_UNPACK
+fun! scriptmanager2#Checkout(targetDir, repository) abort
+ if a:repository['type'] =~ 'git\|hg\|svn'
+ call vcs_checkouts#Checkout(a:targetDir, a:repository)
+ else
+ " archive based repositories - no VCS
+ " must have a:repository['archive_name']
+
+ if !isdirectory(a:targetDir) | call mkdir(a:targetDir.'/archive','p') | endif
+
+ " basename VIM -> vim
+ let archiveName = fnamemodify(substitute(get(a:repository,'archive_name',''), '\.\zsVIM$', 'vim', ''),':t')
+
+ " archive will be downloaded to this location
+ let archiveFile = a:targetDir.'/archive/'.archiveName
+
+ call scriptmanager_util#Download(a:repository['url'], archiveFile)
+
+ call scriptmanager_util#Unpack(archiveFile, a:targetDir, get(a:repository,'strip-components',1))
+
+ call writefile([get(a:repository,"version","?")], a:targetDir."/version")
+
+ " hook for plugin / syntax files: Move into the correct direcotry:
+ if a:repository['archive_name'] =~? '\.vim$'
+ let type = tolower(get(a:repository,'script-type',''))
+ if type =~# '^syntax\|indent\|ftplugin$'
+ let dir = a:targetDir.'/'.type
+ call mkdir(dir)
+ call rename(a:targetDir.'/'.archiveName, dir.'/'.archiveName)
+ endif
+ endif
+ endif
+endfun
+
+fun! s:shellescape(s)
+ return shellescape(a:s,1)
+endf
+
+" cmds = list of {'d': dir to run command in, 'c': the command line to be run }
+fun! s:exec_in_dir(cmds)
+ call vcs_checkouts#ExecIndir(a:cmds)
+endf
+
+" is there a library providing an OS abstraction? This breaks Winndows
+" xcopy or copy should be used there..
+fun! scriptmanager2#Copy(f,t)
+ if g:is_win
+ exec '!xcopy /e /i '.s:shellescape(a:f).' '.s:shellescape(a:t)
+ else
+ exec '!cp -r '.s:shellescape(a:f).' '.s:shellescape(a:t)
+ endif
+endfun
+
+
+fun! scriptmanager2#LoadKnownRepos(...)
+ let known = s:c['known']
+ let reason = a:0 > 0 ? a:1 : 'get more plugin sources'
+ if 0 == get(s:c['activated_plugins'], known, 0) && input('Activate plugin '.known.' to '.reason.'? [y/n]:','') == 'y'
+ call scriptmanager#Activate([known])
+ " this should be done by Activate!
+ exec 'source '.scriptmanager#PluginDirByName(known).'/plugin/vim-addon-manager-known-repositories.vim'
+ endif
+endf
+
+
+fun! scriptmanager2#MergeTarget()
+ return split(&runtimepath,",")[0].'/after/plugin/vim-addon-manager-merged.vim'
+endf
+
+" if you machine is under IO load starting up Vim can take some time
+" This function tries to optimize this by reading all the plugin/*.vim
+" files joining them to one vim file.
+"
+" 1) rename plugin to plugin-merged (so that they are no longer sourced by Vim)
+" 2) read plugin/*.vim_merged files
+" 3) replace clashing s:name vars by uniq names
+" 4) rewrite the guards (everything containing finish)
+" 5) write final merged file to ~/.vim/after/plugin/vim-addon-manager-merged.vim
+" so that its sourced automatically
+"
+" TODO: take after plugins int account?
+fun! scriptmanager2#MergePluginFiles(plugins, skip_pattern)
+ if !filereadable('/bin/sh')
+ throw "you should be using Linux.. This code is likely to break on other operating systems!"
+ endif
+
+ let target = scriptmanager2#MergeTarget()
+
+ for r in a:plugins
+ if !has_key(s:c['activated_plugins'], r)
+ throw "JoinPluginFiles: all plugins must be activated (which ensures that they have been installed). This plugin is not active: ".r
+ endif
+ endfor
+
+ let runtimepaths = map(copy(a:plugins), 'scriptmanager#PluginRuntimePath(v:val)')
+
+ " 1)
+ for r in runtimepaths
+ if (isdirectory(r.'/plugin'))
+ call s:exec_in_dir([{'c':'mv '.s:shellescape(r.'/plugin').' '.s:shellescape(r.'/plugin-merged')}])
+ endif
+ endfor
+
+ " 2)
+ let file_local_vars = {}
+ let uniq = 1
+ let all_contents = ""
+ for r in runtimepaths
+ for file in split(glob(r.'/plugin-merged/*.vim'),"\n")
+
+ if file =~ a:skip_pattern
+ let all_contents .= "\" ignoring ".file."\n"
+ continue
+ endif
+
+ let names_this_file = {}
+ let contents =join(readfile(file, 'b'),"\n")
+ for l in split("s:abc s:foobar",'\ze\<s:')[1:]
+ let names_this_file[matchstr(l,'^s:\zs[^ [(=)\]]*')] = 1
+ endfor
+ " handle duplicate local vars: 3)
+ for k in keys(names_this_file)
+ if has_key(file_local_vars, k)
+ let new = 'uniq_'.uniq
+ let uniq += 1
+ let file_local_vars[new] = 1
+ let contents = "\" replaced: ".k." by ".new."\n".substitute(contents, 's:'.k,'s:'.new,'g')
+ else
+ let file_local_vars[k] = 1
+ endif
+ endfor
+
+ " find finish which start at the end of a line.
+ " They are often used to separated Vim code from additional info such as
+ " history (eg tlib is using it). Comment remaining lines
+ let lines = split(contents,"\n")
+ let comment = 0
+ for i in range(0,len(lines)-1)
+ if lines[i] =~ '^finish'
+ let comment = 1
+ endif
+ if comment
+ let lines[i] = "\" ".lines[i]
+ endif
+ endfor
+ let contents = join(lines,"\n")
+
+ " guards 4)
+ " find guards replace them by if .. endif blocks
+ let lines = split(contents,"\n")
+ for i in range(2,len(lines)-1)
+ if lines[i] =~ '^\s*finish' && lines[i-1] =~ '^\s*if\s'
+ " found a guard
+
+ " negate if, remove {{{ if present (I don't care)
+ let lines[i-1] = 'if !('.matchstr(substitute(lines[i-1],'"[^"]*{{{.*','',''),'if\s*\zs.*').')'
+ let j = i+1
+ while j < len(lines) && lines[j] !~ '^\s*endif'
+ let lines[j] = ''
+ let j = j+1
+ endwhile
+ let lines[j] = ''
+ " guards are never longer than 10 lines
+ if j - i > 10
+ throw "something probably has gone wrong while removing guard for file".file." start at line: ".i
+ endif
+ call add(lines,'endif')
+ let contents = join(lines,"\n")
+ break
+ endif
+ endfor
+
+
+ " comment remaining finish lines. This does not catch if .. | finish | endif and such
+ " :-(
+ " adding additional \n because not all scripts have a final \n..
+ let contents = substitute(contents, '\<finish\>','" finish','g')
+ let all_contents .= "\n"
+ \ ."\"merged: ".file."\n"
+ \ .contents
+ \ ."\n"
+ \ ."\"merged: ".file." end\n"
+ endfor
+ endfor
+
+ let d =fnamemodify(target,':h')
+ if !isdirectory(d) | call mkdir(d,'p') | endif
+ call writefile(split(all_contents,"\n"), target)
+
+endf
+
+fun! scriptmanager2#UnmergePluginFiles()
+ let path = fnamemodify(scriptmanager#PluginRuntimePath('vim-addon-manager'),':h')
+ for merged in split(glob(path.'/*/plugin-merged'),"\n")
+ \ +split(glob(path.'/*/*/plugin-merged'),"\n")
+ echo "unmerging ".merged
+ call rename(merged, substitute(merged,'-merged$','',''))
+ endfor
+ call delete(scriptmanager2#MergeTarget())
+endfun
+
+
+if g:is_win
+ fun! scriptmanager2#FetchAdditionalWindowsTools() abort
+ if !executable("curl") && s:curl == "curl -o"
+ throw "No curl found. Either set g:netrw_http_cmd='path/curl -o' or put it in PATH"
+ endif
+ if !isdirectory(s:c['binary_utils'].'\dist')
+ call mkdir(s:c['binary_utils'].'\dist','p')
+ endif
+ " we have curl, so we can fetch remaingin deps using Download and Unpack
+ let tools = {
+ \ 'gzip': ['mirror://sourceforge/gnuwin32/gzip/1.3.12-1/', "gzip-1.3.12-1-bin.zip", "gzip"],
+ \ 'bzip2':['mirror://sourceforge/gnuwin32/bzip2/1.0.5/', "bzip2-1.0.5-bin.zip", "bzip2" ],
+ \ 'tar': ['mirror://sourceforge/gnuwin32/tar/1.13-1/',"tar-1.13-1-bin.zip", "tar"],
+ \ 'zip': ['mirror://sourceforge/gnuwin32/unzip/5.51-1/', "unzip-5.51-1-bin.zip", "unzip"],
+ \ 'diffutils': ['mirror://sourceforge/gnuwin32/diffutils/2.8.7-1/',"diffutils-2.8.7-1-bin.zip", "diff"],
+ \ 'patch': [ 'mirror://sourceforge/gnuwin32/patch/2.5.9-7/',"patch-2.5.9-7-bin.zip", "patch"]
+ \ }
+ for v in values(tools)
+ echo "downloading ".v[1]
+ if !executable(v[2]) && !filereadable(s:c['binary_utils'].'\'.v[1])
+ " call scriptmanager_util#DownloadFromMirrors(v[0].v[1], s:c['binary_utils'])
+ endif
+ endfor
+
+ if !executable('unzip')
+ " colorize this?
+ echo "__ its your turn: __"
+ echom "__ move all files of the zip directory into ".s:c['binary_utils'].'/dist . Close the Explorer window and the shell window to continue. Press any key'
+ call getchar()
+ exec "!".expand(s:c['binary_utils'].'/'. tools.zip[1])
+ let $PATH=$PATH.';'.s:c['binary_utils_bin']
+ if !executable('unzip')
+ throw "can't execute unzip. Something failed!"
+ endif
+ endif
+
+ " now we have unzip and can do rest
+ for k in ["gzip","bzip2","tar","diffutils","patch"]
+ if !executable(tools[k][2])
+ call scriptmanager_util#Unpack(s:c['binary_utils'].'\'.tools[k][1], s:c['binary_utils'].'\dist', 0)
+ endif
+ endfor
+
+ "if executable("7z")
+ "echo "you already have 7z in PATH. Nothing to be done"
+ "return
+ "endif
+ "let _7zurl = 'mirror://sourceforge/sevenzip/7-Zip/4.65/7z465.exe'
+ "call scriptmanager_util#DownloadFromMirrors(_7zurl, s:c['binary_utils'].'/7z.exe')
+
+ endf
+endif
diff --git a/autoload/scriptmanager_test.vim b/autoload/scriptmanager_test.vim
new file mode 100644
index 0000000..4ec8e75
--- /dev/null
+++ b/autoload/scriptmanager_test.vim
@@ -0,0 +1,71 @@
+
+let s:plugin_root_dir = fnamemodify(expand('<sfile>'),':h:h:h')
+
+" called by vim-addon-manager-test.sh
+fun! scriptmanager_test#Test()
+ let test_dir = '/tmp/vim-addon-manager-test'
+
+ exec '!rm -fr ' test_dir
+ exec '!mkdir -p ' test_dir
+ exec '!cp -r' s:plugin_root_dir test_dir
+
+ " keep it simple:
+ let g:vim_script_manager['activated_plugins']['vim-addon-manager-known-repositories'] = 1
+ let plugin_sources = g:vim_script_manager['plugin_sources']
+
+ " test mercurial
+ call feedkeys("y")
+ let plugin_sources['vimstuff'] = { 'type': 'hg', 'url': 'http://vimstuff.hg.sourceforge.net:8000/hgroot/vimstuff/vimstuff' }
+ call scriptmanager#Activate(["vimstuff"])
+
+ " test git
+ call feedkeys("y")
+ let plugin_sources['vim-addon-views'] = { 'type' : 'git', 'url' : 'git://github.com/MarcWeber/vim-addon-views.git' }
+ call scriptmanager#Activate(["vim-addon-views"])
+
+ " test subversion
+ call feedkeys("y")
+ let plugin_sources['vim-latex'] = { 'type': 'svn', 'url': 'https://vim-latex.svn.sourceforge.net/svnroot/vim-latex/trunk/vimfiles'}
+ call scriptmanager#Activate(["vim-latex"])
+
+endf
+
+" scriptmanager_util#Unpack tests
+
+" test: . = all tests
+" tar$ = onnly the tar test
+fun! scriptmanager_test#TestUnpack(test) abort
+ let tests = {
+ \ 'tar': ['autocorrect', ['README', 'archive', 'archive/autocorrect.tar', 'autocorrect.dat', 'autocorrect.vim', 'generator.rb', 'version'] ],
+ \ 'tar.gz': ['ack', ['archive', 'doc', 'doc/ack.txt', 'plugin', 'plugin/ack.vim', 'version']],
+ \ 'tgz': ['VIlisp', ['README', 'VIlisp-hyperspec.pl', 'VIlisp.vim', 'changelog', 'funnel.pl', 'lisp-thesaurus', 'make-lisp-thes.pl', 'archive', 'version']],
+ \ 'tar.bz2': ['DetectIndent', ['archive', 'doc', 'doc/detectindent.txt', 'plugin', 'plugin/detectindent.vim', 'version']],
+ \ 'tbz2': ['xterm16', ['ChangeLog', 'archive', 'cpalette.pl', 'version', 'xterm16.ct', 'xterm16.schema', 'xterm16.txt', 'xterm16.vim']],
+ \ 'vim_ftplugin': ['srec1008', ['archive', 'archive/srec.vim', 'ftplugin', 'ftplugin/srec.vim', 'version']],
+ \ 'vba': ['Templates_for_Files_and_Function_Groups', ['archive', 'archive/file_templates.vba', 'plugin', 'plugin/file_templates.vim', 'templates', 'templates/example.c', 'version', 'templates/example.h']],
+ \ 'vba.gz': ['gitolite', ['archive', 'ftdetect', 'ftdetect/gitolite.vim', 'syntax', 'syntax/gitolite.vim', 'version']],
+ \ 'vba.bz2': ['winmanager1440',['archive', 'doc', 'doc/tags', 'doc/winmanager.txt', 'plugin', 'plugin/start.gnome', 'plugin/start.kde', 'plugin/winfileexplorer.vim', 'plugin/winmanager.vim', 'plugin/wintagexplorer.vim', 'version']]
+ \ }
+
+ let tmpDir = scriptmanager_util#TempDir("vim-addon-manager-test")
+
+ call scriptmanager2#LoadKnownRepos()
+
+ for [k,v] in items(tests)
+ if k !~ a:test | continue | endif
+ call scriptmanager_util#RmFR(tmpDir)
+ let dict = g:vim_script_manager['plugin_sources'][v[0]]
+ call scriptmanager2#Checkout(tmpDir, dict)
+ let files = split(glob(tmpDir.'/**'),"\n")
+ " replace \ by / on win and remove tmpDir prefix
+ call map(files, 'substitute(v:val,'.string('\').',"/","g")['.(len(tmpDir)+1).':]')
+ call sort(files)
+ call sort(v[1])
+ if v[1] != files
+ echoe "test failure :".k
+ echoe 'expected :'.string(v[1])
+ echoe 'got : '.string(files)
+ debug echoe 'continue'
+ endif
+ endfor
+endf
diff --git a/autoload/scriptmanager_util.vim b/autoload/scriptmanager_util.vim
new file mode 100644
index 0000000..e1b7dbd
--- /dev/null
+++ b/autoload/scriptmanager_util.vim
@@ -0,0 +1,181 @@
+" let users override curl command. Reuse netrw setting
+let s:curl = exists('g:netrw_http_cmd') ? g:netrw_http_cmd : 'curl -o'
+
+" cmds = list of {'d': dir to run command in, 'c': the command line to be run }
+fun! s:exec_in_dir(cmds)
+ call vcs_checkouts#ExecIndir(a:cmds)
+endf
+
+" insert arguments at placeholders $ shell escaping the value
+" usage: s:shellescape("rm --arg $ -fr $p $p $p", [string, file1, file2, file3])
+"
+" the / \ annoyance of Windows is fixed by calling expand which replaces / by
+" \ on Windows. This only happens by the $p substitution
+fun! s:shellescape(cmd, ...)
+ let list = copy(a:000)
+ let r = ''
+ let l = split(a:cmd, '\$', 1)
+ let r = l[0]
+ for x in l[1:]
+ let i = remove(list, 0)
+ if x[0] == 'p'
+ let x = x[1:]
+ let i = expand(i)
+ endif
+ let r .= shellescape(i,1).x
+ endfor
+ return r
+endf
+
+" TODO improve this and move somewhere else?
+fun! scriptmanager_util#ShellDSL(...)
+ return call('s:shellescape', a:000)
+endf
+
+
+fun! s:EndsWith(name, ...)
+ return a:name =~? '\%('.substitute(join(a:000,'\|'),'\.','\\.','g').'\)$'
+endf
+
+
+
+" may throw EXCEPTION_UNPACK.*
+" most packages are shipped in a directory. Eg ADDON/plugin/*
+" strip_components=1 strips of this ADDON directory (implemented for tar.* " archives only)
+
+" !! If you change this run the test, please: call vim_addon_manager_tests#Tests('.')
+fun! scriptmanager_util#Unpack(archive, targetdir, strip_components)
+
+ let esc_archive = s:shellescape('$', a:archive)
+ let tgt = [{'d': a:targetdir}]
+
+ let gzbzip2 = {
+ \ '.gz': [-4, '','gzip -d'],
+ \ '.tgz': [-3,'ar','gzip -d'],
+ \ '.bz2': [-5, '', 'bzip2 -d'],
+ \ '.tbz2': [-4,'ar','bzip2 -d'],
+ \ }
+
+ " .vim file and type syntax?
+ if a:archive =~? '\.vim$'
+ call writefile(readfile(a:archive,'b'), a:targetdir.'/'.fnamemodify(a:archive, ':t'),'b')
+
+ " .gz .bzip2 (or .vba.* or .tar.*)
+ elseif s:EndsWith(a:archive, keys(gzbzip2) )
+ " I was told tar on Windows is buggy and can't handle xj or xz correctly
+ " so unpack in two phases:
+
+ for [k,z] in items(gzbzip2)
+ if s:EndsWith(a:archive, k)
+ let unpacked = a:archive[:z[0]]
+ let renameTo = unpacked.z[1]
+ call s:exec_in_dir([{'c': z[2].' '.esc_archive }])
+ if !filereadable(renameTo)
+ " windows tar does not rename .tgz to .tar ?
+ call rename(unpacked, renameTo)
+ endif
+ " now unpack .tar or .vba file and tidy up temp file:
+ call scriptmanager_util#Unpack(renameTo, a:targetdir, a:strip_components)
+ call delete(renameTo)
+ endif
+ unlet k z
+ endfor
+
+ " execute in target dir:
+
+ " .tar
+ elseif s:EndsWith(a:archive, '.tar')
+ call s:exec_in_dir(tgt + [{'c': 'tar '.'--strip-components='.a:strip_components.' -xf '.esc_archive }])
+
+ " .zip
+ elseif s:EndsWith(a:archive, '.zip')
+ call s:exec_in_dir(tgt + [{'c': 'unzip '.esc_archive }])
+
+ " .7z, .cab, .rar, .arj, .jar
+ " (I have actually seen only .7z and .rar, but 7z supports other formats
+ " too)
+ elseif s:EndsWith(a:archive, '.7z','.cab','.arj','.rar','.jar')
+ call s:exec_in_dir(tgt + [{'c': '7z x '.esc_archive }])
+
+
+ elseif s:EndsWith(a:archive, '.vba')
+ " .vba reuse vimball#Vimball() function
+ exec 'sp '.fnameescape(a:archive)
+ call vimball#Vimball(1,a:targetdir)
+ else
+ throw "EXCEPTION_UNPACK: don't know how to unpack ". a:archive
+ endif
+
+endf
+
+fun! scriptmanager_util#Download(url, targetFile)
+ " allow redirection because of sourceforge mirrors:
+ let c = substitute(s:curl, 'curl','curl --location --max-redirs 40','')
+ call s:exec_in_dir([{'c': s:shellescape(c.' $p $', a:targetFile, a:url)}])
+endf
+
+fun! scriptmanager_util#RmFR(dir_or_file)
+ let cmd = ""
+ if has('win32') || has('win64')
+ if getftype(a:dir_or_file) == 'dir'
+ let cmd = 'rmdir /S /Q'
+ else
+ let cmd = 'erase /F'
+ endif
+ elseif has('win16') || has('win95')
+ " Dos-style COMMAND.COM. These are _UNTESTED_
+ if getftype(a:dir_or_file) == 'dir'
+ let cmd = 'deltree /Y'
+ else
+ let cmd = 'erase /F'
+ endif
+ else
+ let cmd = "rm -fr"
+ endif
+ if cmd == ""
+ throw "don't know how to RmFR on this system: ".g:os
+ else
+ exec '!'.s:shellescape(cmd.' $', a:dir_or_file)
+ endif
+endf
+
+
+" a "direct link" (found on the downrload page)
+" such as "http://downloads.sourceforge.net/project/gnuwin32/gzip/1.3.12-1/gzip-1.3.12-1-bin.zip"
+" can be downloaded this way:
+" call scriptmanager_util#DownloadFromMirrors("mirror://sourceforge/gnuwin32/gzip/1.3.12-1/gzip-1.3.12-1-bin.zip","/tmp")
+fun! scriptmanager_util#DownloadFromMirrors(url, targetDir)
+ let mirrors_sourceforge = [
+ \ 'http://heanet.dl.sourceforge.net/sourceforge/',
+ \ 'http://surfnet.dl.sourceforge.net/sourceforge/',
+ \ ]
+
+ let m = matchlist(a:url, '^mirror:\/\/\([^/\\]\+\)\/\(.*\)')
+
+ if len(m) > 3
+ let url = mirrors_{m[1]}[0].m[2]
+ endif
+ " if target is a directory append basename of url
+ let t = a:targetDir
+ if isdirectory(t)
+ let t = t .'/'.fnamemodify(url,':t')
+ endif
+ call scriptmanager_util#Download(url, t)
+endf
+
+
+let s:tmpDir = ""
+" this is not cleaned up on shutdown yet !
+" tmpname():
+" on windows C:\Users\NAME\AppData\Local\Temp\VIG3DB6.tmp
+" on linux /tmp/v106312/111
+"
+" on linux this returns /tmp/a:name
+" on windows it returns C:\Users\NAME\AppData\Local\Temp/a:name
+fun! scriptmanager_util#TempDir(name)
+ if s:tmpDir == ""
+ let s:tmpDir = fnamemodify(tempname(), ":h".(g:is_win ? '': ':h'))
+ endif
+ " expand make \ out of / on Windows
+ return expand(s:tmpDir.'/'.a:name)
+endf
diff --git a/autoload/vcs_checkouts.vim b/autoload/vcs_checkouts.vim
new file mode 100644
index 0000000..461476c
--- /dev/null
+++ b/autoload/vcs_checkouts.vim
@@ -0,0 +1,89 @@
+" this may be useful for other projects.
+" Thus move checking .hg .svn etc into a different file
+
+fun! vcs_checkouts#Update(dir)
+ let directory = a:dir
+ if isdirectory(directory.'/.git')
+ call s:exec_in_dir([{'d': directory, 'c': 'git pull'}])
+ return !v:shell_error
+ elseif isdirectory(directory.'/.svn')
+ call s:exec_in_dir([{'d': directory, 'c': 'svn update'}])
+ return !v:shell_error
+ elseif isdirectory(directory.'/.hg')
+ call s:exec_in_dir([
+ \ {'d': directory, 'c': 'hg pull'},
+ \ {'d': directory, 'c': 'hg update'},
+ \ {'d': directory, 'c': 'hg merge'}
+ \ ])
+ return !v:shell_error
+ else
+ echoe "Plugin ".fnamemodify(directory, ':t')." is not controlled by any known SCM system."
+ return 0
+ endif
+endf
+
+" repository = {'type': svn|hg|git, 'url': .. }
+fun! vcs_checkouts#Checkout(targetDir, repository)
+ if a:repository['type'] == 'git'
+ let parent = fnamemodify(a:targetDir,':h')
+ exec '!git clone '.s:shellescape(a:repository['url']).' '.s:shellescape(a:targetDir)
+ if !isdirectory(a:targetDir)
+ throw "Failed checking out ".a:targetDir."!"
+ endif
+ elseif a:repository['type'] == 'hg'
+ let parent = fnamemodify(a:targetDir,':h')
+ exec '!hg clone '.s:shellescape(a:repository['url']).' '.s:shellescape(a:targetDir)
+ if !isdirectory(a:targetDir)
+ throw "Failed checking out ".a:targetDir."!"
+ endif
+ elseif a:repository['type'] == 'svn'
+ let parent = fnamemodify(a:targetDir,':h')
+ call s:exec_in_dir([{'d': parent, 'c': 'svn checkout '.s:shellescape(a:repository['url']).' '.s:shellescape(a:targetDir)}])
+ if !isdirectory(a:targetDir)
+ throw "Failed checking out ".a:targetDir."!"
+ endif
+ endif
+endf
+
+fun! s:exec_in_dir(cmds)
+ call vcs_checkouts#ExecIndir(a:cmds)
+endf
+
+fun! vcs_checkouts#ExecIndir(cmds) abort
+ if g:is_win
+ " set different lcd in extra buffer:
+ new
+ let lcd=""
+ for c in a:cmds
+ if has_key(c, "d")
+ " TODO quoting
+ exec "lcd ".c.d
+ endif
+ if has_key(c, "c")
+ exec '!'.c.c
+ endif
+ " break if one of the pased commands failes:
+ if v:shell_error != 0
+ break
+ endif
+ endfor
+ " should lcd withou args be used instead?
+ bw!
+ else
+ " execute command sequences on linux
+ let cmds_str = []
+ for c in a:cmds
+ if has_key(c,"d")
+ call add(cmds_str, "cd ".s:shellescape(c.d))
+ endif
+ if has_key(c,"c")
+ call add(cmds_str, c.c)
+ endif
+ endfor
+ exec '!'.join(cmds_str," && ")
+ endif
+endf
+
+fun! s:shellescape(s)
+ return shellescape(a:s,1)
+endf
diff --git a/doc/fuf.jax b/doc/fuf.jax
new file mode 100644
index 0000000..7150c80
--- /dev/null
+++ b/doc/fuf.jax
@@ -0,0 +1,1313 @@
+*fuf.jax* バッファ/ファイル/その他を、あいまい検索
+
+ Copyright (c) 2007-2010 Takeshi NISHIDA
+
+FuzzyFinder *fuzzyfinder* *fuf*
+
+概要 |fuf-introduction|
+インストール |fuf-installation|
+使い方 |fuf-usage|
+モード |fuf-modes|
+詳細なトピック |fuf-detailed-topics|
+コマンド |fuf-commands|
+オプション |fuf-options|
+VIMRC の例 |fuf-vimrc-example|
+SPECIAL THANKS |fuf-thanks|
+CHANGELOG |fuf-changelog|
+あばうと |fuf-about|
+
+==============================================================================
+概要 *fuf-introduction*
+
+FuzzyFinder はバッファ/ファイル/コマンド/ブックマーク/タグに素早くアクセスする
+ための手段を提供します。入力されたパターンから変換されたあいまいパターンまたは
+部分一致パターンで検索を行います。
+
+ 入力パターン あいまいパターン 部分一致パターン ~
+>
+ abc *a*b*c* *abc*
+ dir/file dir/*f*i*l*e* dir/*file*
+ d*r/file d*r/*f*i*l*e* d*r/*file*
+ ../**/s ../**/*s* ../**/*s*
+ (** : 再帰検索)
+<
+次のような場面で有用です:
+
+ "./AhLongLongLongLongLongFile.txt"
+ "./AhLongLongLongLongLongName.txt"
+ "./OhLongLongLongLongLongFile.txt"
+ "./OhLongLongLongLongLongName.txt" <- 欲しいファイル :-O
+
+"ON" と入力すれば "OhLongLongLongLongLongName.txt" が選択できます. :-D
+
+FuzzyFinder が検索できる対象は次の通りです:
+ - バッファ
+ - ファイル
+ - ディレクトリ
+ - 最近使ったファイル
+ - 最近使ったファイルの近くのファイル
+ - 最近使ったコマンドライン
+ - ブックマークされたファイル
+ - ブックマークされたディレクトリ
+ - タグ
+ - タグファイルに含まれるファイル
+ - ジャンプリスト
+ - チェンジリスト
+ - バッファの行
+ - quickfix
+ - ヘルプ
+
+FuzzyFinder は ファイルを検索したりアイテムを選択するシステムを利用するための
+API も提供します。
+
+FuzzyFinder はマルチバイト文字をサポートしています。
+
+
+==============================================================================
+インストール *fuf-installation*
+
+ZIPファイルをランタイムディレクトリに展開します。
+
+以下のようにファイルが配置されるはずです。
+>
+ <ランタイムディレクトリ>/plugin/fuf.vim
+ <ランタイムディレクトリ>/doc/fuf.txt
+ ...
+<
+もしランタイムディレクトリが多数のプラグインでごちゃごちゃになるのが嫌なら、各
+プラグインを個別のディレクトリに配置し、そのディレクトリのパスを 'runtimepath'
+に追加してください。アンインストールも楽になります。
+
+その後、ヘルプを有効にするためにタグファイルを更新してください。詳しくは
+|add-local-help|を参照してください。
+
+必要なもの: ~
+
+- L9 library (vimscript #3252)
+
+
+==============================================================================
+使い方 *fuf-usage*
+
+次のコマンドで FuzzyFinder を起動します:
+
+ コマンド モード ~
+ |:FufBuffer| - Buffer モード (|fuf-buffer-mode|)
+ |:FufFile| - File モード (|fuf-file-mode|)
+ |:FufCoverageFile| - Coverage-File モード (|fuf-coveragefile-mode|)
+ |:FufDir| - Directory モード (|fuf-dir-mode|)
+ |:FufMruFile| - MRU-File モード (|fuf-mrufile-mode|)
+ |:FufMruCmd| - MRU-Command モード (|fuf-mrucmd-mode|)
+ |:FufBookmarkFile| - Bookmark-File モード (|fuf-bookmarkfile-mode|)
+ |:FufBookmarkDir| - Bookmark-Dir モード (|fuf-bookmarkdir-mode|)
+ |:FufTag| - Tag モード (|fuf-tag-mode|)
+ |:FufTaggedFile| - Tagged-File モード (|fuf-taggedfile-mode|)
+ |:FufJumpList| - Jump-List モード (|fuf-jumplist-mode|)
+ |:FufChangeList| - Change-List モード (|fuf-changelist-mode|)
+ |:FufQuickfix| - Quickfix モード (|fuf-quickfix-mode|)
+ |:FufLine| - Line モード (|fuf-line-mode|)
+ |:FufHelp| - Help モード (|fuf-help-mode|)
+
+これらのコマンドを押しやすいキーにマッピングすることを推奨します。
+
+これらのコマンドを実行するとパターンを入力するための1行のバッファを開き、イン
+サートモードを開始します。
+
+FuzzyFinder は入力されたパターンにマッチするアイテムを検索し、それを補完メニュ
+ーに表示します。パターンマッチングの詳細は|fuf-search-patterns|を参照してくだ
+さい。
+
+多くのアイテムがマッチングする場合、FuzzyFinder はレスポンスを向上させるために
+列挙するアイテムの数(|g:fuf_enumeratingLimit|)を制限し、その際、入力されたパタ
+ーンを"Error" グループでハイライトします。
+
+補完メニューの最初のアイテムは自動的に選択状態になります。
+
+<C-w> で入力パターンからカーソル前の、ディレクトリ名などのひとかたまりを削除す
+ることができます。
+
+<C-s> (|g:fuf_keyPrevPattern|) と <C-^> (|g:fuf_keyNextPattern|) で、履歴から
+過去に入力したパターンを呼び出すことができます。
+
+いろいろな方法で、選択されたアイテムを開くことができます:
+
+ <CR> (|g:fuf_keyOpen|) - 直前のウィンドウで開きます。
+ <C-j> (|g:fuf_keyOpenSplit|) - ウィンドウを分割して開きます。
+ <C-k> (|g:fuf_keyOpenVsplit|) - ウィンドウを垂直分割して開きます。
+ <C-l> (|g:fuf_keyOpenTabpage|) - 別のタブページで開きます。
+
+キャンセルして直前のウィンドウに戻るには、インサートモードを抜けてください。
+
+<C-\><C-\> (|g:fuf_keySwitchMatching|) で、検索方法をあいまいマッチングまたは
+部分一致マッチングに交互に切り替えることができます。
+
+<C-t> (|g:fuf_keyNextMode|) と <C-y> (|g:fuf_keyPrevMode|) で、インサートモー
+ドを抜けることなくカレントモードを切り替えることが出来ます。
+
+いくつかのモードでは、選択されたアイテムを <C-@> (|g:fuf_keyPreview|) でプレビ
+ューすることができます。同じアイテムでキーを繰り返すことで別の情報を表示させる
+ことができます。プレビューをサポートするモードを起動すると、コマンドラインの高
+さが|g:fuf_previewHeight|になります。この機能は|g:fuf_previewHeight|が0ではな
+い場合、有効になります。
+
+
+==============================================================================
+モード *fuf-modes*
+
+ *fuf-buffer-mode*
+Buffer モード ~
+
+このモードはバッファを選択して開くインターフェースを提供します。
+
+Buffer モード中に <C-]> (|g:fuf_buffer_keyDelete|) を押すと選択したバッファを
+削除することができます。
+
+ *fuf-file-mode*
+File モード ~
+
+このモードはファイルツリーからファイルを検索して開くインターフェースを提供しま
+す。
+
+ *fuf-coveragefile-mode*
+Coverage-File モード ~
+
+このモードはあらかじめ設定した検索対象の全ファイルからファイルを選択して開くイ
+ンターフェースを提供します。
+
+デフォルトではカレントディレクトリ以下の全ファイルを列挙します。
+(|g:fuf_coveragefile_globPatterns|)
+
+他の検索対象を検索したい場合、|FufCoverageFileRegister|コマンドで新しい検索対
+象を登録し、|FufCoverageFileChange|コマンドで検索対象を選択して Coverage-File
+モードを起動します。
+
+加えて、|fuf#setOneTimeVariables()|関数を使う方法もあります。
+
+
+例: .hと.cファイルだけ検索する:
+>
+ call fuf#setOneTimeVariables(['g:fuf_coveragefile_globPatterns', ['**/*.h', '**/*.c']])
+ \ | FufCoverageFile
+<
+例: デフォルトの検索対象に加えてホームディレクトリも検索する:
+>
+ call fuf#setOneTimeVariables(['g:fuf_coveragefile_globPatterns', g:fuf_coveragefile_globPatterns + ['~/**/.*', '~/**/*']])
+ \ | FufCoverageFile
+<
+
+ *fuf-dir-mode*
+Directory モード ~
+
+このモードはファイルツリーからディレクトリを検索してカレントディレクトリを変更
+するインターフェースを提供します。
+
+ *fuf-mrufile-mode*
+MRU-File モード ~
+
+このモードは最近使ったファイルを選択して開くインターフェースを提供します。
+
+このモード中に <C-]> (|g:fuf_mrufile_keyExpand|) を押すと、最近使ったファイル
+の付近にあるファイルを検索します。このキーを押す毎に、検索範囲をディレクトリツ
+リーの上下に1階層ずつ広げます。
+
+|BufEnter| と |BufWritePost| で行う処理がパフォーマンス上の問題を起こしうるの
+で、デフォルトでは無効化するモードに指定されています。(|g:fuf_modesDisable|)
+
+ *fuf-mrucmd-mode*
+MRU-Command モード ~
+
+このモードは最近使ったコマンドラインを選択して開くインターフェースを提供します
+。
+このモードに必要な、コマンドラインモードの <CR> のマッピングに副作用があるので、
+、デフォルトでは無効化するモードに指定されています。(|g:fuf_modesDisable|)
+
+ *fuf-bookmarkfile-mode*
+Bookmark-File モード ~
+
+このモードは事前に追加したブックマークを選択してその行へジャンプするインターフ
+ェースを提供します。
+
+|:FufBookmarkFileAdd|コマンドでカーソルのある行をブックマークに追加できます。
+このコマンドを実行すると、ブックマーク名の入力を求められます。
+
+FuzzyFinder はジャンプする行番号を調整します。ブックマークされた行がブックマー
+クされたときのパターンとマッチしない場合、FuzzyFinder はブックマークされた位置
+の周辺でマッチする行を探します。なのでブックマークした行が多少移動していたとし
+ても、そこでジャンプすることができます。ブックマークした行番号へ調整せずにジャ
+ンプしたい場合、|g:fuf_bookmarkfile_searchRange|を 0 に設定してください。
+
+このモード中に <C-]> (|g:fuf_bookmarkfile_keyDelete|) を押すと選択したブックマ
+ークを削除することができます。
+
+ *fuf-bookmarkdir-mode*
+Bookmark-Dir モード ~
+
+このモードは事前に追加したブックマークを選択してカレントディレクトリを変更する
+するインターフェースを提供します。
+
+|:FufBookmarkDirAdd|コマンドでディレクトリをブックマークに追加できます。このコ
+マンドを実行すると、ディレクトリのパスとブックマーク名の入力を求められます。
+
+このモード中に <C-]> (|g:fuf_bookmarkdir_keyDelete|) を押すと選択したブックマ
+ークを削除することができます。
+
+ *fuf-tag-mode*
+Tag モード ~
+
+このモードはタグを選択してその定義へジャンプするインターフェースを提供します。
+
+以下は <C-]> を置き換えるマッピングです。
+>
+ noremap <silent> <C-]> :FufTagWithCursorWord!<CR>
+<
+
+ *fuf-taggedfile-mode*
+Tagged-File モード ~
+
+このモードはタグファイルに含まれるファイルを選択して開くインターフェースを提供
+します。
+
+ *fuf-jumplist-mode*
+Jump-List モード ~
+
+このモードはカレントウィンドウの|jumplist|から選択した位置へジャンプするインタ
+ーフェースを提供します。
+
+ *fuf-changelist-mode*
+Change-List モード ~
+
+このモードはカレントバッファの|changelist|から選択した位置へジャンプするインタ
+ーフェースを提供します。
+
+ *fuf-quickfix-mode*
+Quickfix モード ~
+
+このモードは|quickfix|リストから選択した位置へジャンプするインターフェースを提
+供します。
+
+ *fuf-line-mode*
+Line モード ~
+
+このモードはカレントバッファの行を選択してジャンプするインターフェースを提供し
+ます。
+
+ *fuf-help-mode*
+Help モード ~
+
+このモードはヘルプタグを選択してそのヘルプページへジャンプするインターフェース
+を提供します。
+
+ *fuf-givenfile-mode*
+Given-File モード ~
+
+このモードは与えられたリストから選択されたファイルを開く API を提供します。
+
+API 関数:
+>
+ function fuf#givenfile#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - FuzzyFinder 起動直後に挿入される文字列
+ partialMatching - あいまい検索ではなく部分一致検索を行うか
+ prompt - プロンプト文字列
+ items - アイテムのリスト
+
+利用例:
+>
+ " ドットファイルを開く
+ call fuf#givenfile#launch('', 0, '>', split(glob('~/.*'), "\n"))
+<
+
+ *fuf-givendir-mode*
+Given-Directory モード ~
+
+このモードは与えられたリストから選択されたディレクトリにカレントディレクトリを
+変更する API を提供します。
+
+API 関数:
+>
+ function fuf#givendir#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - FuzzyFinder 起動直後に挿入される文字列
+ partialMatching - あいまい検索ではなく部分一致検索を行うか
+ prompt - プロンプト文字列
+ items - アイテムのリスト
+
+
+利用例:
+>
+ " ランタイムディレクトリのどれかをカレントディレクトリにする
+ call fuf#givendir#launch('', 0, '>', split(&runtimepath, ','))
+<
+
+ *fuf-givencmd-mode*
+Given-Command モード ~
+
+このモードは与えられたリストから選択されたコマンドを実行する API を提供します。
+
+選択されたコマンドは feedkeys() によって実行されるので、ノーマルモードでの一連
+のキー入力をエミュレートさせることも可能です。
+
+API 関数:
+>
+ function fuf#givencmd#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - FuzzyFinder 起動直後に挿入される文字列
+ partialMatching - あいまい検索ではなく部分一致検索を行うか
+ prompt - プロンプト文字列
+ items - アイテムのリスト
+
+
+利用例:
+>
+ function GetAllCommands()
+ redir => commands
+ silent command
+ redir END
+ return map((split(commands, "\n")[3:]),
+ \ '":" . matchstr(v:val, ''^....\zs\S*'')')
+ endfunction
+
+ " ユーザー定義コマンドを選択して実行
+ call fuf#givencmd#launch('', 0, '>', GetAllCommands())
+
+<
+
+ *fuf-callbackfile-mode*
+Callback-File モード ~
+
+このモードはファイルを検索して選択されたファイルパスを得る API を提供します。
+
+API 関数:
+>
+ function fuf#callbackfile#launch(
+ \ initialPattern, partialMatching, prompt, exclude, listener)
+<
+ initialPattern - FuzzyFinder 起動直後に挿入される文字列
+ partialMatching - あいまい検索ではなく部分一致検索を行うか
+ prompt - プロンプト文字列
+ exclude - 補完リストから除外したいアイテムの正規表現パターン
+ listener - 'onComplete' と 'onAbort' を持つ|Dictionary|。これ
+ らは FuzzyFinder 終了時に呼ばれます。
+ listener.onComplete(item, method) は選択が完了したと
+ き、選択されたアイテム名とオープン方式番号の2引数と
+ 共に呼ばれます。listener.onAbort() は選択を中止した
+ ときに呼ばれます。
+
+利用例:
+>
+ let listener = {}
+
+ function listener.onComplete(item, method)
+ echo "Item: " . a:item . "\nMethod: " . a:method
+ endfunction
+
+ function listener.onAbort()
+ echo "Abort"
+ endfunction
+
+ " カレントディレクトリからファイルを選択
+ call fuf#callbackfile#launch('', 0, '>', '', listener)
+
+ " ホームディレクトリからファイルを選択
+ call fuf#callbackfile#launch('~/', 0, '>', '', listener)
+<
+
+ *fuf-callbackitem-mode*
+Callback-Item モード ~
+
+このモードは与えられたリストから選択されたアイテムを得るための API を提供しま
+す。
+
+API 関数:
+>
+ function fuf#callbackitem#launch(
+ \ initialPattern, partialMatching, prompt, listener, items, forPath)
+<
+ initialPattern - FuzzyFinder 起動直後に挿入される文字列
+ partialMatching - あいまい検索ではなく部分一致検索を行うか
+ prompt - プロンプト文字列
+ listener - 'onComplete' と 'onAbort' を持つ|Dictionary|。これ
+ らは FuzzyFinder 終了時に呼ばれます。
+ listener.onComplete(item, method) は選択が完了したと
+ き、選択されたアイテム名とオープン方式番号の2引数と
+ 共に呼ばれます。listener.onAbort() は選択を中止した
+ ときに呼ばれます。
+ items - アイテムのリスト
+ forPath - ファイル選択に特化したマッチングを利用するか
+
+利用例:
+>
+ let listener = {}
+
+ function listener.onComplete(item, method)
+ echo "Item: " . a:item . "\nMethod: " . a:method
+ endfunction
+
+ function listener.onAbort()
+ echo "Abort"
+ endfunction
+
+ " 与えられたリストからアイテムを選択
+ call fuf#callbackitem#launch('', 0, '>', listener, ['ed', 'vi', 'vim'], 0)
+
+ " 与えられたリストからファイルを選択
+ call fuf#callbackitem#launch('', 0, '>', listener, ['../foo/bar', 'baz'], 1)
+<
+
+==============================================================================
+詳細なトピック *fuf-detailed-topics*
+
+ *fuf-setting-one-time-option* *fuf#setOneTimeVariables()*
+一回限りのオプションの設定 ~
+
+次回の FuzzyFinder 用に一回限りのオプションを設定したいとき、
+|fuf#setOneTimeVariables()|関数が役に立ちます。この関数は次のようにして使いま
+す:
+>
+ call fuf#setOneTimeVariables(['g:fuf_ignoreCase', 0], ['&lines', 50])
+<
+この関数は 0 個以上の引数を取り、各々は変数名と値のペアです。指定されたオプシ
+ョンは次回 FuzzyFinder が起動したときに実際に設定され、終了するときに復元され
+ます。
+
+ *fuf-search-patterns*
+検索パターン ~
+
+検索パターンとして、一つのプライマリパターンと0個以上の絞り込みパターンを入力
+することができます。入力パターンは ";" (|g:fuf_patternSeparator|) で区切られ、
+最初のパターンがプライマリパターンになり、残りのパターンが絞り込みパターンにな
+ります。
+>
+ プライマリ 絞り込み 絞り込み
+ |----------| |-------| |----|
+ >MruFile>bookmark.vim;autoload/;/home/
+<
+プライマリパターンにマッチしたアイテムのリストを別のパターンで絞り込むために、
+絞り込みパターンを利用します。
+
+プライマリパターンでは、あいまいマッチングと部分一致マッチングのうち、選択され
+た方を行います。絞り込みパターンでは、デフォルトで部分一致マッチングを行います
+。(|g:fuf_fuzzyRefining|)
+
+絞り込みパターンとして数値を入力した場合、アイテムのインデックスに対しても
+マッチングします。
+
+ファイルパスの静的な集合を対象とするモード (Buffer, MRU-File モードなど。File,
+Directory モードなどではない) で|g:fuf_splitPathMatching|が真の場合、プライマ
+リパターンのマッチングは head 部とtail 部に分けて行われます。
+>
+ head tail
+ |------||-----|
+ foo/bar/baz.vim
+
+ あいまいマッチング例:
+ +----------------+---------+---------+---------+
+ | item \ pattern | foo/bar | foo/ | bar |
+ +----------------+---------+---------+---------+
+ | foo/bar | match | match | match |
+ | foo/abc | unmatch | match | unmatch |
+ | abc/bar | unmatch | unmatch | match |
+ | foobar | unmatch | unmatch | match |
+ | foooo/barrrr | match | match | match |
+ | foooo/fooooo | unmatch | match | unmatch |
+ +----------------+---------+---------+---------+
+<
+上記のケースで、絞り込みパターンはパス全体に対してマッチングできます。
+
+ *fuf-sorting-of-completion-items*
+補完アイテムのソート ~
+
+FuzzyFinder は幾つかのルールに従って補完アイテムをソートします。
+
+パターン全体が一部分にぴったりマッチするアイテムは優先されます。例えば、パター
+ン "bc" ではアイテム "abc" は "bac" より優先されます。
+
+このケースで、マッチする部分が先頭であるアイテムはそうでないアイテムより優先さ
+れます。例えばパターン "foo" ではアイテム "foobar" は"barfoo" より優先されます
+。
+
+マッチング位置より後の文字数が少ないほど優先されます。例えばパターン "bar" で
+はアイテム"foobar" は"foobarbaz"より優先されます。
+
+単語の境界文字にだけマッチングするアイテムは優先されます。 例えば、パターン
+"fb" ではアイテム"fooBarBaz" や "foo_bar_baz" などが優先されます。
+
+加えて、FuzzyFinder には学習システムがあります。現在のパターンで、過去に補完さ
+れたことのあるアイテムを優先します。
+
+ *fuf-reusing-window*
+目的のバッファ/ファイルが開かれているウィンドウの再利用 ~
+
+ウィンドウを分割してバッファ/ファイルを開くときに、現在のタブページでそれが開
+かれているウィンドウが見つかった場合、そこへ移動します。別のタブページでバッフ
+ァ/ファイルを開くときに、他のタブページでそれが開かれているウィンドウが見つか
+った場合、そこへ移動します。
+
+常にバッファ/ファイルを新ウィンドウで開きたい場合、'reuse_window'オプションで
+この機能を無効にすることができます。
+
+ *fuf-hiding-menu*
+補完メニューの一時非表示 ~
+
+<C-e> で補完メニューを閉じることができます。また、<C-x><C-o>で再度開くことがで
+きます。
+
+ *fuf-abbreviation* *fuf-multiple-search*
+短縮入力及び複合検索 ~
+
+|g:fuf_abbrevMap|を設定することで、全モードで短縮入力と複合検索が利用できます。
+
+例えば次のように設定したとします:
+>
+ let g:fuf_abbrevMap = {
+ \ "^doc:" : [
+ \ "~/project/**/doc/",
+ \ ".vim/doc/",
+ \ ],
+ \ }
+<
+そして File モードで "doc:txt" と入力すると、次の2つのパターンの検索結果を複合
+します:
+
+ "~/project/**/doc/*t*x*t*"
+ ".vim/doc/*t*x*t*"
+
+ *fuf-data-file*
+データファイル ~
+
+FuzzyFinder は補完統計、MRUデータ、ブックマークなどを|g:fuf_dataDir|以下のファ
+イルに書き込みます。
+
+|:FufEditDataFile|コマンドはデータファイルの編集を補助します。このコマンドを実
+行すると、データファイルを無名バッファに読み込みます。:write などで書き込みを
+行うと、データファイルを更新します。
+
+ *fuf-cache*
+キャッシュ ~
+
+一旦キャッシュが生成されると、レスポンスを向上させるため自動的には更新されませ
+ん。これを更新するには|:FufRenewCache|コマンドを実行してください。
+
+ *fuf-dot-sequence*
+ドット列で親ディレクトリへ移動 ~
+
+ドット列を入力することで親ディレクトリを上がっていくことができます。パス区切り
+文字直後のドット列は "../" の列に展開されます。
+
+ ドット列 展開パターン ~
+ /.. /../
+ /... /../../
+ /.... /../../../
+
+ *fuf-how-to-add-mode*
+モードの追加方法 ~
+
+"mymode" モードを追加するには、ソースファイルを autoload/fuf/mymode.vim に置き
+、 fuf#addMode('mymode') を呼びます。
+
+ *fuf-migemo*
+Migemo とは ~
+
+以下のページを参照してください。
+ - http://0xcc.net/migemo/
+ - http://www.kaoriya.net/#CMIGEMO
+
+
+==============================================================================
+コマンド *fuf-commands*
+
+See also: |fuf-vimrc-example|
+
+ *:FufBuffer*
+:FufBuffer [{pattern}]
+ Buffer モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufFile*
+:FufFile [{pattern}]
+ File モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufFileWithFullCwd*
+:FufFileWithFullCwd [{pattern}]
+ カレントディレクトリのフルパスを初期パターンとする以外は|:FufFile|と同
+ じです。
+
+ *:FufFileWithCurrentBufferDir*
+:FufFileWithCurrentBufferDir [{pattern}]
+ カレントバッファのディレクトリを初期パターンとする以外は|:FufFile|と同
+ じです。
+
+ *:FufDir*
+:FufDir [{pattern}]
+ Directory モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufDirWithFullCwd*
+:FufDirWithFullCwd [{pattern}]
+ カレントディレクトリのフルパスを初期パターンとする以外は|:FufDir|と同
+ じです。
+
+ *:FufDirWithCurrentBufferDir*
+:FufDirWithCurrentBufferDir [{pattern}]
+ カレントバッファのディレクトリを初期パターンとする以外は|:FufDir|と同
+ じです。
+
+ *:FufMruFile*
+:FufMruFile [{pattern}]
+ MRU-File モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufMruCmd*
+:FufMruCmd [{pattern}]
+ MRU-Command モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufBookmarkFile*
+:FufBookmarkFile [{pattern}]
+ Bookmark-File モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufBookmarkDir*
+:FufBookmarkDir [{pattern}]
+ Bookmark-Dir モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufTag*
+:FufTag [{pattern}]
+ Tag モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufTagWithCursorWord*
+:FufTagWithCursorWord [{pattern}]
+ カーソル下の単語を初期パターンとする以外は|:FufTag|と同じです。
+
+ *:FufTaggedFile*
+:FufTaggedFile [{pattern}]
+ Tagged-File モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufJumpList*
+:FufJumpList [{pattern}]
+ Jump-List モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufChangeList*
+:FufChangeList [{pattern}]
+ Change-List モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufQuickfix*
+:FufQuickfix [{pattern}]
+ Quickfix モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufLine*
+:FufLine [{pattern}]
+ Line モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufHelp*
+:FufHelp[!] [{pattern}]
+ Help モードを起動します。
+
+ ! 修飾子を付けて実行した場合、あいまい検索ではなく部分一致検索を行うよ
+ うになります。
+
+ FuzzyFinder 起動後に {pattern} が挿入されます。
+
+ *:FufEditDataFile*
+:FufEditDataFile
+ データファイルを編集するためのバッファを開きます。詳しくは
+ |fuf-data-file|を参照してください。
+
+ *:FufCoverageFileRegister*
+:FufCoverageFileRegister
+ Coverage-File モードで検索される、新しい検索対象を登録します。最初に
+ ~/* のような glob パターンを入力します。 <Esc> を入力するまでパターン
+ を追加することができます。次に対象名を入力します。
+
+ See also: |glob()|, |fuf-coveragefile-mode|
+
+ *:FufCoverageFileChange*
+:FufCoverageFileChange [{name}]
+ |FufCoverageFileRegister|コマンドで登録されている中から選択された検索
+ 対象でCoverage-File モードを起動します。
+
+ 対象名が与えられた場合、選択プロセスは飛ばされます。
+
+ See also: |fuf-coveragefile-mode|
+
+ *:FufBookmarkFileAdd*
+:FufBookmarkFileAdd [{name}]
+ カーソル行をブックマークに追加します。
+
+ See also: |fuf-bookmarkfile-mode|
+
+ *:FufBookmarkFileAddAsSelectedText*
+:FufBookmarkFileAddAsSelectedText
+ 最後に選択されたテキストをブックマーク名とする以外は
+ |:FufBookmarkFileAdd|と同じです。
+
+ *:FufBookmarkDirAdd*
+:FufBookmarkDirAdd [{name}]
+ ディレクトリをブックマークに追加します。
+
+ See also: |fuf-bookmarkdir-mode|
+
+ *:FufRenewCache*
+:FufRenewCache
+ 補完アイテムを作り直すためにキャッシュを削除します。詳しくは
+ |fuf-cache|を参照してください。
+
+
+==============================================================================
+オプション *fuf-options*
+
+ *fuf-options-for-all-modes*
+全モード用 ~
+
+ *g:fuf_modesDisable* >
+ let g:fuf_modesDisable = [ 'mrufile', 'mrucmd', ]
+<
+ 無効にするモード名のリスト。これに含まれるモードは初期化されず、イベン
+ トの処理も行われません。
+
+ *g:fuf_keyOpen* >
+ let g:fuf_keyOpen = '<CR>'
+<
+ 補完を確定し、バッファ/ファイルを直前のウィンドウで開くキー。
+
+ *g:fuf_keyOpenSplit* >
+ let g:fuf_keyOpenSplit = '<C-j>'
+<
+ 補完を確定し、バッファ/ファイルを直前のウィンドウを分割して開くキー。
+
+ *g:fuf_keyOpenVsplit* >
+ let g:fuf_keyOpenVsplit = '<C-k>'
+<
+ 補完を確定し、バッファ/ファイルを直前のウィンドウを垂直分割して開くキ
+ ー。
+
+ *g:fuf_keyOpenTabpage* >
+ let g:fuf_keyOpenTabpage = '<C-l>'
+<
+ 補完を確定し、バッファ/ファイルを別タブページ開くキー。
+
+ *g:fuf_keyPreview* >
+ let g:fuf_keyPreview = '<C-@>'
+<
+ 選択されている補完アイテムの情報をコマンドライン領域に表示するキー。プ
+ レビューをサポートするモードでのみ作用します。
+
+ *g:fuf_keyNextMode* >
+ let g:fuf_keyNextMode = '<C-t>'
+<
+ 次のモードに切り替えるキー。
+
+ *g:fuf_keyPrevMode* >
+ let g:fuf_keyPrevMode = '<C-y>'
+<
+ 前のモードに切り替えるキー。
+
+ *g:fuf_keyPrevPattern* >
+ let g:fuf_keyPrevPattern = '<C-s>'
+<
+ 履歴から前の入力パターンを呼び出すキー。
+
+ *g:fuf_keyNextPattern* >
+ let g:fuf_keyNextPattern = '<C-_>'
+<
+ 履歴から次の入力パターンを呼び出すキー。
+
+ *g:fuf_keySwitchMatching* >
+ let g:fuf_keySwitchMatching = '<C-\><C-\>'
+<
+ あいまいマッチングと部分一致マッチングを切り替えるキー。
+
+ *g:fuf_dataDir* >
+ let g:fuf_dataDir = '~/.vim-fuf-data'
+<
+ データファイルを置くディレクトリのパス。空文字列を設定するとファイルへ
+ の書き込みは行われなくなります。
+
+ *g:fuf_abbrevMap* >
+ let g:fuf_abbrevMap = {}
+<
+ |Dictionary|型でそれぞれの値は|List|型です。入力されたテキストの、キー
+ にマッチする部分が対応する値に展開されます。
+
+ *g:fuf_patternSeparator* >
+ let g:fuf_patternSeparator = ';'
+<
+ 入力パターンをプライマリパターンと絞り込みパターン列に区切る文字列。
+
+ *g:fuf_promptHighlight* >
+ let g:fuf_promptHighlight = 'Question'
+<
+ プロンプトをハイライトするグループ名。
+
+ *g:fuf_ignoreCase* >
+ let g:fuf_ignoreCase = 1
+<
+ 真なら、大文字小文字を無視します。
+
+ *g:fuf_splitPathMatching* >
+ let g:fuf_splitPathMatching = 1
+<
+ 真なら、プライマリパターンのマッチングは head 部とtail 部に分けて行わ
+ れます。
+
+ See also: |fuf-search-patterns|
+
+ *g:fuf_fuzzyRefining* >
+ let g:fuf_fuzzyRefining = 0
+<
+ 真なら、絞り込みパターンについて部分一致マッチングの代わりにあいまいマ
+ ッチングが行われます。
+
+ See also: |fuf-search-patterns|
+
+ *g:fuf_reuseWindow* >
+ let g:fuf_reuseWindow = 1
+<
+ 真なら、すでに開かれているバッファを開くとき、目的のバッファを含むウィ
+ ンドウを再利用します。
+
+ *g:fuf_timeFormat* >
+ let g:fuf_timeFormat = '(%Y-%m-%d %H:%M:%S)'
+<
+ アイテムが登録された日時の書式を設定します。書式の詳細は|strftime()|を
+ 参照してください。
+
+ *g:fuf_learningLimit* >
+ let g:fuf_learningLimit = 100
+<
+ 保持する補完統計データのモード毎の上限値です。
+
+ *g:fuf_enumeratingLimit* >
+ let g:fuf_enumeratingLimit = 50
+<
+ レスポンスを向上させるため、補完アイテムの列挙をこの数に達した時点で打
+ ち切ります。
+
+ *g:fuf_maxMenuWidth* >
+ let g:fuf_maxMenuWidth = 78
+<
+ 長い補完アイテムは、この長さに収まるよう省略して表示します。
+
+ *g:fuf_previewHeight* >
+ let g:fuf_previewHeight = 0
+<
+ プレビューをサポートするモードを起動したとき、'cmdheight'がこの値に設
+ 定されます。選択されている補完アイテムの情報がコマンドライン領域に表示
+ されます。0 ならプレビュー機能は無効になります。
+
+ *g:fuf_autoPreview* >
+ let g:fuf_autoPreview = 0
+<
+ 真ならプレビューを自動的に表示します。
+
+ *g:fuf_useMigemo* >
+ let g:fuf_useMigemo = 0
+<
+ 真なら migemo を利用します。
+
+ *fuf-options-for-buffer-mode*
+Buffer モード用 ~
+
+ *g:fuf_buffer_prompt* >
+ let g:fuf_buffer_prompt = '>Buffer[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_buffer_switchOrder* >
+ let g:fuf_buffer_switchOrder = 10
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_buffer_mruOrder* >
+ let g:fuf_buffer_mruOrder = 1
+<
+ 真なら、最後に使った時間順に補完アイテムをソートします。
+
+ *g:fuf_buffer_keyDelete* >
+ let g:fuf_buffer_keyDelete = '<C-]>'
+<
+ 選択したバッファを削除するキー。
+
+ *fuf-options-for-file-mode*
+File モード用 ~
+
+ *g:fuf_file_prompt* >
+ let g:fuf_file_prompt = '>File[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_file_switchOrder* >
+ let g:fuf_file_switchOrder = 20
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_file_exclude* >
+ let g:fuf_file_exclude = '\v\~$|\.(o|exe|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ 補完リストから除外したいアイテムの正規表現パターン。
+
+ *fuf-options-for-coveragefile-mode*
+Coverage-File モード用 ~
+
+ *g:fuf_coveragefile_prompt* >
+ let g:fuf_coveragefile_prompt = '>CoverageFile[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_coveragefile_switchOrder* >
+ let g:fuf_coveragefile_switchOrder = 30
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_coveragefile_exclude* >
+ let g:fuf_coveragefile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ 補完リストから除外したいアイテムの正規表現パターン。
+
+ *g:fuf_coveragefile_globPatterns* >
+ let g:fuf_coveragefile_globPatterns = ['**/.*', '**/*']
+<
+ 検索されるファイルパスを得るためのglobパターンのリスト。
+
+ *fuf-options-for-dir-mode*
+Directory モード用 ~
+
+ *g:fuf_dir_prompt* >
+ let g:fuf_dir_prompt = '>Dir[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_dir_switchOrder* >
+ let g:fuf_dir_switchOrder = 40
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_dir_exclude* >
+ let g:fuf_dir_exclude = '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ 補完リストから除外したいアイテムの正規表現パターン。
+
+ *fuf-options-for-mrufile-mode*
+MRU-File モード用 ~
+
+ *g:fuf_mrufile_prompt* >
+ let g:fuf_mrufile_prompt = '>MRU-File[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_mrufile_switchOrder* >
+ let g:fuf_mrufile_switchOrder = 50
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_mrufile_exclude* >
+ let g:fuf_mrufile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+<
+ 補完リストから除外したいアイテムの正規表現パターン。
+
+ *g:fuf_mrufile_maxItem* >
+ let g:fuf_mrufile_maxItem = 200
+<
+ 保持するMRUアイテムの上限値。
+
+ *g:fuf_mrufile_maxItemDir* >
+ let g:fuf_mrufile_maxItemDir = 50
+<
+ 保持するMRUアイテムの親ディレクトリ(周辺検索で使われる)の上限値。
+
+ *g:fuf_mrufile_keyExpand* >
+ let g:fuf_mrufile_keyExpand = '<C-]>'
+<
+ 検索する範囲を広げるキー。
+
+ *fuf-options-for-mrucmd-mode*
+MRU-Cmd モード用 ~
+
+ *g:fuf_mrucmd_prompt* >
+ let g:fuf_mrucmd_prompt = '>MRU-Cmd[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_mrucmd_switchOrder* >
+ let g:fuf_mrucmd_switchOrder = 70
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_mrucmd_exclude* >
+ let g:fuf_mrucmd_exclude = '^$'
+<
+ 補完リストから除外したいアイテムの正規表現パターン。
+
+ *g:fuf_mrucmd_maxItem* >
+ let g:fuf_mrucmd_maxItem = 200
+<
+ 保持するMRUアイテムの上限値。
+
+ *fuf-options-for-bookmarkfile-mode*
+Bookmark-File モード用 ~
+
+ *g:fuf_bookmarkfile_prompt* >
+ let g:fuf_bookmarkfile_prompt = '>BookmarkFile[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_bookmarkfile_switchOrder* >
+ let g:fuf_bookmarkfile_switchOrder = 80
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_bookmarkfile_searchRange* >
+ let g:fuf_bookmarkfile_searchRange = 400
+<
+ ジャンプするとき、ブックマークした位置からこの行数の範囲内でブックマー
+ クしたときのパターンとマッチする行を探します。
+
+ *g:fuf_bookmarkfile_keyDelete* >
+ let g:fuf_bookmarkfile_keyDelete = '<C-]>'
+<
+ 選択したブックマークを削除するキー。
+
+ *fuf-options-for-bookmarkdir-mode*
+Bookmark-Dir モード用 ~
+
+ *g:fuf_bookmarkdir_prompt* >
+ let g:fuf_bookmarkdir_prompt = '>BookmarkDir[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_bookmarkdir_switchOrder* >
+ let g:fuf_bookmarkdir_switchOrder = 90
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *g:fuf_bookmarkdir_keyDelete* >
+ let g:fuf_bookmarkdir_keyDelete = '<C-]>'
+<
+ 選択したブックマークを削除するキー。
+
+ *fuf-options-for-tag-mode*
+Tag モード用 ~
+
+ *g:fuf_tag_prompt* >
+ let g:fuf_tag_prompt = '>Tag[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_tag_switchOrder* >
+ let g:fuf_tag_switchOrder = 100
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-taggedfile-mode*
+Tagged-File モード用 ~
+
+ *g:fuf_taggedfile_prompt* >
+ let g:fuf_taggedfile_prompt = '>Tagged-File[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_taggedfile_switchOrder* >
+ let g:fuf_taggedfile_switchOrder = 110
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-jumplist-mode*
+Jump-List モード用 ~
+
+ *g:fuf_jumplist_prompt* >
+ let g:fuf_jumplist_prompt = '>Jump-List[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_jumplist_switchOrder* >
+ let g:fuf_jumplist_switchOrder = 120
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-changelist-mode*
+Change-List モード用 ~
+
+ *g:fuf_changelist_prompt* >
+ let g:fuf_changelist_prompt = '>Change-List[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_changelist_switchOrder* >
+ let g:fuf_changelist_switchOrder = 130
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-quickfix-mode*
+Quickfix モード用 ~
+
+ *g:fuf_quickfix_prompt* >
+ let g:fuf_quickfix_prompt = '>Quickfix[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_quickfix_switchOrder* >
+ let g:fuf_quickfix_switchOrder = 140
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-line-mode*
+Line モード用 ~
+
+ *g:fuf_line_prompt* >
+ let g:fuf_line_prompt = '>Line[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_line_switchOrder* >
+ let g:fuf_line_switchOrder = 150
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+ *fuf-options-for-help-mode*
+Help モード用 ~
+
+ *g:fuf_help_prompt* >
+ let g:fuf_help_prompt = '>Help[]>'
+<
+ プロンプト文字列。"[]" はインジケータに置換されます。
+
+ *g:fuf_help_switchOrder* >
+ let g:fuf_help_switchOrder = 160
+<
+ 次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
+ には切り替えません。
+
+
+==============================================================================
+vimrc の例 *fuf-vimrc-example*
+
+>
+ let g:fuf_modesDisable = []
+ let g:fuf_abbrevMap = {
+ \ '^vr:' : map(filter(split(&runtimepath, ','), 'v:val !~ "after$"'), 'v:val . ''/**/'''),
+ \ '^m0:' : [ '/mnt/d/0/', '/mnt/j/0/' ],
+ \ }
+ let g:fuf_mrufile_maxItem = 500
+ let g:fuf_mrucmd_maxItem = 500
+ nnoremap <silent> sj :FufBuffer<CR>
+ nnoremap <silent> sk :FufFileWithCurrentBufferDir<CR>
+ nnoremap <silent> sK :FufFileWithFullCwd<CR>
+ nnoremap <silent> s<C-k> :FufFile<CR>
+ nnoremap <silent> sl :FufCoverageFileChange<CR>
+ nnoremap <silent> sL :FufCoverageFileChange<CR>
+ nnoremap <silent> s<C-l> :FufCoverageFileRegister<CR>
+ nnoremap <silent> sd :FufDirWithCurrentBufferDir<CR>
+ nnoremap <silent> sD :FufDirWithFullCwd<CR>
+ nnoremap <silent> s<C-d> :FufDir<CR>
+ nnoremap <silent> sn :FufMruFile<CR>
+ nnoremap <silent> sm :FufMruCmd<CR>
+ nnoremap <silent> su :FufBookmarkFile<CR>
+ nnoremap <silent> s<C-u> :FufBookmarkFileAdd<CR>
+ vnoremap <silent> s<C-u> :FufBookmarkFileAddAsSelectedText<CR>
+ nnoremap <silent> si :FufBookmarkDir<CR>
+ nnoremap <silent> s<C-i> :FufBookmarkDirAdd<CR>
+ nnoremap <silent> st :FufTag<CR>
+ nnoremap <silent> sT :FufTag!<CR>
+ noremap <silent> s] :FufTagWithCursorWord!<CR>
+ nnoremap <silent> sg :FufTaggedFile<CR>
+ nnoremap <silent> sG :FufTaggedFile!<CR>
+ nnoremap <silent> so :FufJumpList<CR>
+ nnoremap <silent> sp :FufChangeList<CR>
+ nnoremap <silent> sq :FufQuickfix<CR>
+ nnoremap <silent> sy :FufLine<CR>
+ nnoremap <silent> sh :FufHelp<CR>
+ nnoremap <silent> se :FufEditDataFile<CR>
+ nnoremap <silent> sr :FufRenewCache<CR>
+<
+
+==============================================================================
+あばうと *fuf-about* *fuf-contact* *fuf-author*
+
+作者: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
+ライセンス: MIT Licence
+URL: http://www.vim.org/scripts/script.php?script_id=1984
+ http://bitbucket.org/ns9tks/vim-fuzzyfinder/
+
+バグや要望など ~
+
+こちらへどうぞ: http://bitbucket.org/ns9tks/vim-fuzzyfinder/issues/
+
+==============================================================================
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/doc/fuf.txt b/doc/fuf.txt
new file mode 100644
index 0000000..58b2de0
--- /dev/null
+++ b/doc/fuf.txt
@@ -0,0 +1,1776 @@
+*fuf.txt* buffer/file/command/tag/etc explorer with fuzzy matching.
+
+ Copyright (c) 2007-2010 Takeshi NISHIDA
+
+FuzzyFinder *fuzzyfinder* *fuf*
+
+INTRODUCTION |fuf-introduction|
+INSTALLATION |fuf-installation|
+USAGE |fuf-usage|
+MODES |fuf-modes|
+DETAILED TOPICS |fuf-detailed-topics|
+COMMANDS |fuf-commands|
+OPTIONS |fuf-options|
+VIMRC EXAMPLE |fuf-vimrc-example|
+SPECIAL THANKS |fuf-thanks|
+CHANGELOG |fuf-changelog|
+ABOUT |fuf-about|
+
+==============================================================================
+INTRODUCTION *fuf-introduction*
+
+FuzzyFinder provides convenient ways to quickly reach the
+buffer/file/command/bookmark/tag you want. FuzzyFinder searches with the
+fuzzy/partial pattern to which it converted an entered pattern.
+
+ Entered pattern Fuzzy pattern Partial pattern ~
+>
+ abc *a*b*c* *abc*
+ dir/file dir/*f*i*l*e* dir/*file*
+ d*r/file d*r/*f*i*l*e* d*r/*file*
+ ../**/s ../**/*s* ../**/*s*
+ (** allows searching a directory tree.)
+<
+You will be happy when:
+
+ "./AhLongLongLongLongLongFile.txt"
+ "./AhLongLongLongLongLongName.txt"
+ "./OhLongLongLongLongLongFile.txt"
+ "./OhLongLongLongLongLongName.txt" <- you want :O
+
+Type "ON" and "OhLongLongLongLongLongName.txt" will be selected. :D
+
+FuzzyFinder can search:
+
+ - buffers
+ - files
+ - directories
+ - most recently used files
+ - files around most recently used files
+ - most recently used command-lines
+ - bookmarked files
+ - bookmarked directories
+ - tags
+ - files which are included in current tagfiles
+ - jump list
+ - change list
+ - buffer lines
+ - quickfix
+ - help
+
+FuzzyFinder also provides APIs to use its system of searching files or
+selecting items.
+
+FuzzyFinder supports multibyte characters.
+
+
+==============================================================================
+INSTALLATION *fuf-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/fuf.vim
+ <your runtime directory>/doc/fuf.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 the help for this plugin. See
+|add-local-help| for details.
+
+Requirements: ~
+
+- L9 library (vimscript #3252)
+
+
+==============================================================================
+USAGE *fuf-usage*
+
+You can launch FuzzyFinder by the following commands:
+
+ Command Mode ~
+ |:FufBuffer| - Buffer mode (|fuf-buffer-mode|)
+ |:FufFile| - File mode (|fuf-file-mode|)
+ |:FufCoverageFile| - Coverage-File mode (|fuf-coveragefile-mode|)
+ |:FufDir| - Directory mode (|fuf-dir-mode|)
+ |:FufMruFile| - MRU-File mode (|fuf-mrufile-mode|)
+ |:FufMruCmd| - MRU-Command mode (|fuf-mrucmd-mode|)
+ |:FufBookmarkFile| - Bookmark-File mode (|fuf-bookmarkfile-mode|)
+ |:FufBookmarkDir| - Bookmark-Dir mode (|fuf-bookmarkdir-mode|)
+ |:FufTag| - Tag mode (|fuf-tag-mode|)
+ |:FufTaggedFile| - Tagged-File mode (|fuf-taggedfile-mode|)
+ |:FufJumpList| - Jump-List mode (|fuf-jumplist-mode|)
+ |:FufChangeList| - Change-List mode (|fuf-changelist-mode|)
+ |:FufQuickfix| - Quickfix mode (|fuf-quickfix-mode|)
+ |:FufLine| - Line mode (|fuf-line-mode|)
+ |:FufHelp| - Help mode (|fuf-help-mode|)
+
+It is recommended to map these commands.
+
+These commands open 1-line buffer to enter search pattern and start insert
+mode.
+
+FuzzyFinder searchs for matching items with an entered pattern and shows them
+in a completion menu. For more details on pattern matching, see
+|fuf-search-patterns|.
+
+If there are a lot of matching items, FuzzyFinder limits the number of
+enumerating items (|g:fuf_enumeratingLimit|) to speed up a response time, and
+highlights the pattern with "Error" group.
+
+The first item in the completion menu will be selected automatically.
+
+Typing <C-w> deletes one block of an entered pattern before the cursor, like a
+directory name.
+
+with <C-s> (|g:fuf_keyPrevPattern|) and <C-^> (|g:fuf_keyNextPattern|), You
+can recall patterns which have been entered before from history.
+
+You can open a selected item in various ways:
+
+ <CR> (|g:fuf_keyOpen|) - opens in a previous window.
+ <C-j> (|g:fuf_keyOpenSplit|) - opens in a split window.
+ <C-k> (|g:fuf_keyOpenVsplit|) - opens in a vertical-split window.
+ <C-l> (|g:fuf_keyOpenTabpage|) - opens in a new tab page.
+
+To cancel and return to previous window, just leave Insert mode.
+
+With <C-\><C-\> (|g:fuf_keySwitchMatching|), You can switch search method
+between fuzzy matching and partial matching.
+
+With <C-t> (|g:fuf_keyNextMode|) and <C-y> (|g:fuf_keyPrevMode|), You can
+switch current mode without leaving Insert mode .
+
+You can preview selected item with <C-@> (|g:fuf_keyPreview|) in some modes.
+Repeating the key on the same item shows another information. The height
+of command-line area is changed to |g:fuf_previewHeight| when you launch a
+mode supporting preview. This feature is available when |g:fuf_previewHeight|
+is not 0.
+
+
+==============================================================================
+MODES *fuf-modes*
+
+ *fuf-buffer-mode*
+Buffer mode ~
+
+This mode provides an interface to select a buffer from a list of existing
+buffers and open it.
+
+Press <C-]> (|g:fuf_buffer_keyDelete|) in this mode and selected buffer will
+be deleted.
+
+ *fuf-file-mode*
+File mode ~
+
+This mode provides an interface to search a file tree for a file and open it.
+
+ *fuf-coveragefile-mode*
+Coverage-File mode ~
+
+This mode provides an interface to select a file from all files of a preset
+coverage and open it.
+
+By default, This mode lists all files under the current working directory
+recursively. (|g:fuf_coveragefile_globPatterns|)
+
+If you want to search other coverage, execute |FufCoverageFileRegister|
+command to register new search coverage and |FufCoverageFileChange| command to
+choose a search coverage and launch Coverage-File mode.
+
+In addition, there is another way to change a search coverage with
+|fuf#setOneTimeVariables()| function.
+
+Example: search only .h and .c files:
+>
+ call fuf#setOneTimeVariables(['g:fuf_coveragefile_globPatterns', ['**/*.h', '**/*.c']])
+ \ | FufCoverageFile
+<
+Example: search your home directory in addition to the default coverage:
+>
+ call fuf#setOneTimeVariables(['g:fuf_coveragefile_globPatterns', g:fuf_coveragefile_globPatterns + ['~/**/.*', '~/**/*']])
+ \ | FufCoverageFile
+<
+
+ *fuf-dir-mode*
+Directory mode ~
+
+This mode provides an interface to search a file tree for a directory and
+change the current directory.
+
+ *fuf-mrufile-mode*
+MRU-File mode ~
+
+This mode provides an interface to select a file from the most recently used
+files and open it.
+
+Press <C-]> (|g:fuf_mrufile_keyExpand|) in this mode and files around the most
+recently used files are listed. Each time the key is pressed, the search range
+are expanded one level along the directory tree upwardly/downwardly.
+
+This mode is set to disable by default (|g:fuf_modesDisable|) because
+processes for this mode in |BufEnter| and |BufWritePost| could cause
+Performance issue.
+
+ *fuf-mrucmd-mode*
+MRU-Command mode ~
+
+This mode provides an interface to select a command from the most recently
+used commands and execute it.
+
+This mode is set to disable by default (|g:fuf_modesDisable|) because mapping
+<CR> of Command-line mode required by this mode has side effects.
+
+ *fuf-bookmarkfile-mode*
+Bookmark-File mode ~
+
+This mode provides an interface to select one of the bookmarks you have added
+beforehand and jump there.
+
+You can add a cursor line to bookmarks by |:FufBookmarkFileAdd| command.
+Execute that command and you will be prompted to enter a bookmark name.
+
+FuzzyFinder adjusts a line number for jump. If a line of bookmarked position
+does not match to a pattern when the bookmark was added, FuzzyFinder searches
+a matching line around bookmarked position. So you can jump to a bookmarked
+line even if the line is out of bookmarked position. If you want to jump to
+bookmarked line number without the adjustment, set
+|g:fuf_bookmarkfile_searchRange| option to 0.
+
+Press <C-]> (|g:fuf_bookmarkfile_keyDelete|) in this mode and selected
+bookmark will be deleted.
+
+ *fuf-bookmarkdir-mode*
+Bookmark-Dir mode ~
+
+This mode provides an interface to select one of the bookmarks you have added
+beforehand and change the current directory.
+
+You can add a directory to bookmarks by |:FufBookmarkDirAdd| command. Execute
+that command and you will be prompted to enter a directory path and a
+bookmark name.
+
+Press <C-]> (|g:fuf_bookmarkdir_keyDelete|) in this mode and selected bookmark
+will be deleted.
+
+ *fuf-tag-mode*
+Tag mode ~
+
+This mode provides an interface to select a tag and jump to the definition of
+it.
+
+Following mapping is the replacement for <C-]>:
+>
+ noremap <silent> <C-]> :FufTagWithCursorWord!<CR>
+<
+
+ *fuf-taggedfile-mode*
+Tagged-File mode ~
+
+This mode provides an interface to select one of the files which are included
+in current tagfiles and open it.
+
+ *fuf-jumplist-mode*
+Jump-List mode ~
+
+This mode provides an interface to select one from the |jumplist| of the
+current window and jump there.
+
+ *fuf-changelist-mode*
+Change-List mode ~
+
+This mode provides an interface to select one from the |changelist| of the
+current buffer and jump there.
+
+ *fuf-quickfix-mode*
+Quickfix mode ~
+
+This mode provides an interface to select one from the |quickfix| list and
+jump there.
+
+ *fuf-line-mode*
+Line mode ~
+
+This mode provides an interface to select a line from current buffer and jump
+there.
+
+ *fuf-help-mode*
+Help mode ~
+
+This mode provides an interface to select a help tag and jump to the help
+page.
+
+ *fuf-givenfile-mode*
+Given-File mode ~
+
+This mode provides an API to open a selected file from a given list.
+
+API function:
+>
+ function fuf#givenfile#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - String which is inserted after launching
+ FuzzyFinder.
+ partialMatching - If non-zero, enable partial matching instead of
+ fuzzy matching.
+ prompt - Prompt string
+ items - List of items.
+
+Example of use:
+>
+ " Open one of your dotfiles.
+ call fuf#givenfile#launch('', 0, '>', split(glob('~/.*'), "\n"))
+<
+
+ *fuf-givendir-mode*
+Given-Directory mode ~
+
+This mode provides an API to change current working directory to a selected
+one from a given list.
+
+API function:
+>
+ function fuf#givendir#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - String which is inserted after launching
+ FuzzyFinder.
+ partialMatching - If non-zero, enable partial matching instead of
+ fuzzy matching.
+ prompt - Prompt string
+ items - List of items.
+
+
+Example of use:
+>
+ " Change current working directory to one of your runtime directory.
+ call fuf#givendir#launch('', 0, '>', split(&runtimepath, ','))
+<
+
+ *fuf-givencmd-mode*
+Given-Command mode ~
+
+This mode provides an API to execute a selected command from a given list.
+
+A selected command is executed by |feedkeys()|, so it is able to emulate a
+series of key input in Normal mode.
+
+API function:
+>
+ function fuf#givencmd#launch(
+ \ initialPattern, partialMatching, prompt, items)
+<
+ initialPattern - String which is inserted after launching
+ FuzzyFinder.
+ partialMatching - If non-zero, enable partial matching instead of
+ fuzzy matching.
+ prompt - Prompt string
+ items - List of items.
+
+
+Example of use:
+>
+ function GetAllCommands()
+ redir => commands
+ silent command
+ redir END
+ return map((split(commands, "\n")[3:]),
+ \ '":" . matchstr(v:val, ''^....\zs\S*'')')
+ endfunction
+
+ " execute one of the user-defined commands
+ call fuf#givencmd#launch('', 0, '>', GetAllCommands())
+
+<
+
+ *fuf-callbackfile-mode*
+Callback-File mode ~
+
+This mode provides an API to find and get a file path which is selected by an
+user.
+
+API function:
+>
+ function fuf#callbackfile#launch(
+ \ initialPattern, partialMatching, prompt, exclude, listener)
+<
+ initialPattern - String which is inserted after launching
+ FuzzyFinder.
+ partialMatching - If non-zero, enable partial matching instead of
+ fuzzy matching.
+ prompt - Prompt string.
+ exclude - Regexp pattern for items which you want to exclude
+ from completion list.
+ listener - |Dictionary| which has 'onComplete' and 'onAbort'.
+ They are called at the end of FuzzyFinder.
+ listener.onComplete(item, method) is called with 2
+ arguments which are a name of selected item and a
+ number of open method when completed.
+ listener.onAbort() is called when aborted.
+
+Example of use:
+>
+ let listener = {}
+
+ function listener.onComplete(item, method)
+ echo "Item: " . a:item . "\nMethod: " . a:method
+ endfunction
+
+ function listener.onAbort()
+ echo "Abort"
+ endfunction
+
+ " Find a file from current working directory.
+ call fuf#callbackfile#launch('', 0, '>', '', listener)
+
+ " Find a file from home directory.
+ call fuf#callbackfile#launch('~/', 0, '>', '', listener)
+<
+
+ *fuf-callbackitem-mode*
+Callback-Item mode ~
+
+This mode provides an API to get an item which is selected from a given list
+by an user.
+
+API function:
+>
+ function fuf#callbackitem#launch(
+ \ initialPattern, partialMatching, prompt, listener, items, forPath)
+<
+ initialPattern - String which is inserted after launching
+ FuzzyFinder.
+ partialMatching - If non-zero, enable partial matching instead of
+ fuzzy matching.
+ prompt - Prompt string
+ listener - |Dictionary| which has 'onComplete' and 'onAbort'.
+ They are called at the end of FuzzyFinder.
+ listener.onComplete(item, method) is called with 2
+ arguments which are a name of selected item and a
+ number of open method when completed.
+ listener.onAbort() is called when aborted.
+ items - List of items.
+ forPath - If non-zero, use a matching method for files.
+
+Example of use:
+>
+ let listener = {}
+
+ function listener.onComplete(item, method)
+ echo "Item: " . a:item . "\nMethod: " . a:method
+ endfunction
+
+ function listener.onAbort()
+ echo "Abort"
+ endfunction
+
+ " Select an item from a given list.
+ call fuf#callbackitem#launch('', 0, '>', listener, ['ed', 'vi', 'vim'], 0)
+
+ " Select a file from a given list.
+ call fuf#callbackitem#launch('', 0, '>', listener, ['../foo/bar', 'baz'], 1)
+<
+
+==============================================================================
+DETAILED TOPICS *fuf-detailed-topics*
+
+ *fuf-setting-one-time-option* *fuf#setOneTimeVariables()*
+Setting One-Time Options ~
+
+If you want to set one-time options only for the next FuzzyFinder,
+|fuf#setOneTimeVariables()| function will be of help. This function is used as
+follows:
+>
+ call fuf#setOneTimeVariables(['g:fuf_ignoreCase', 0], ['&lines', 50])
+<
+This function takes 0 or more arguments and each of them is a pair of a
+variable name and its value. Specified options will be set practically next
+time FuzzyFinder is launched, and restored when FuzzyFinder is closed.
+
+ *fuf-search-patterns*
+Search Patterns ~
+
+You can enter one primary pattern and zero or more refining patterns as search
+patterns. An entered pattern is separated by ";" (|g:fuf_patternSeparator|),
+and the first pattern is a primary pattern and the rest of patterns is a
+refining pattern.
+>
+ primary refining refining
+ |----------| |-------| |----|
+ >MruFile>bookmark.vim;autoload/;/home/
+<
+A refining pattern is used to narrow down the list of matching items by
+another pattern.
+
+With a primary pattern, FuzzyFinder does fuzzy matching or partial matching,
+which you specified. With a refining pattern, FuzzyFinder does partial
+matching by default. (|g:fuf_fuzzyRefining|)
+
+When you enter a number as refining pattern, it also can match the index of
+each item.
+
+In a mode which targets a static set of file paths (such as Buffer or MRU-File
+mode, not File or Directory) and |g:fuf_splitPathMatching| is non-zero,
+matching with a primary pattern is divided into head part and tail part and
+done individually.
+>
+ head tail
+ |------||-----|
+ foo/bar/baz.vim
+
+ fuzzy matching example:
+ +----------------+---------+---------+---------+
+ | item \ pattern | foo/bar | foo/ | bar |
+ +----------------+---------+---------+---------+
+ | foo/bar | match | match | match |
+ | foo/abc | unmatch | match | unmatch |
+ | abc/bar | unmatch | unmatch | match |
+ | foobar | unmatch | unmatch | match |
+ | foooo/barrrr | match | match | match |
+ | foooo/fooooo | unmatch | match | unmatch |
+ +----------------+---------+---------+---------+
+<
+refining pattern can match anywhere on each path in the above case.
+
+ *fuf-sorting-of-completion-items*
+Sorting Of Completion Items ~
+
+FuzzyFinder sorts completion items with some rules.
+
+An item, one part of which is matched with a whole pattern, is placed upper.
+E.g., with the pattern "bc", the item "abc" is placed upper than "bac".
+
+In the above case, items, each having matching part at the head of itself, are
+placed upper than others. E.g., with the pattern "foo", the item "foobar" is
+placed upper than "foobarbaz".
+
+And the shorter the length of the item after matching position puts it higher.
+E.g., with the pattern "bar", the item "foobar" is placed upper than
+"foobarbaz".
+
+If a pattern matches an item at only word boundaries of it, the item is placed
+upper. E.g., with a pattern "fb", items such as "fooBarBaz" and "foo_bar_baz"
+is placed upper.
+
+Plus, FuzzyFinder has a learning system. An item which has been completed in
+the past with current pattern is placed upper.
+
+ *fuf-reusing-window*
+Reusing Of A Window Containing Target Buffer/File ~
+
+If a window containing target buffer is found in current tab page when
+FuzzyFinder is going to open the buffer in a split new window, move to it. If
+a window containing target buffer is found in other tab page when FuzzyFinder
+is going to open the buffer in a new tab page, move to it.
+
+You can disable that feature via 'reuse_window' options if always want to open
+a buffer in a new window.
+
+ *fuf-hiding-menu*
+To Hide The Completion Menu Temporarily In FuzzyFinder ~
+
+You can close it by <C-e> and reopen it by <C-x><C-o>.
+
+ *fuf-abbreviation* *fuf-multiple-search*
+Abbreviations And Multiple Search ~
+
+You can use abbreviations and multiple search in all modes by setting
+|g:fuf_abbrevMap| option.
+
+For example, set as below:
+>
+ let g:fuf_abbrevMap = {
+ \ "^doc:" : [
+ \ "~/project/**/doc/",
+ \ ".vim/doc/",
+ \ ],
+ \ }
+<
+and enter "doc:txt" in File mode, then FuzzyFinder searches by the following
+patterns:
+
+ "~/project/**/doc/*t*x*t*"
+ ".vim/doc/*t*x*t*"
+
+and show concatenated search results.
+
+ *fuf-data-file*
+Data File ~
+
+FuzzyFinder writes completion statistics, MRU data, bookmark, etc to files
+under |g:fuf_dataDir|.
+
+|:FufEditDataFile| command is helpful in editing your data files. This command
+reads the data file in new unnamed buffer. Write the buffer and the data file
+will be updated.
+
+ *fuf-cache*
+Cache ~
+
+Once a cache was created, It is not automatically updated to speed up the
+response time by default. To update it, use |:FufRenewCache| command.
+
+ *fuf-dot-sequence*
+Going Up Parent Directories With Dot Sequence ~
+
+You can go up parent directories with entering dot sequence. Dot sequence
+after a path separator is expanded to "../" sequence.
+
+ Dot sequence Expanded pattern ~
+ /.. /../
+ /... /../../
+ /.... /../../../
+
+ *fuf-how-to-add-mode*
+How To Add Mode ~
+
+To add "mymode" mode, put the source file at autoload/fuf/mymode.vim and call
+fuf#addMode("mymode") .
+
+ *fuf-migemo*
+What Is Migemo ~
+
+Migemo is a search method for Japanese language.
+
+
+==============================================================================
+COMMANDS *fuf-commands*
+
+See also: |fuf-vimrc-example|
+
+ *:FufBuffer*
+:FufBuffer[!] [{pattern}]
+ Launchs Buffer mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufFile*
+:FufFile[!] [{pattern}]
+ Launchs File mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufFileWithFullCwd*
+:FufFileWithFullCwd[!] [{pattern}]
+ Is mostly the same as |:FufFile|, except that initial pattern is a
+ full path of current working directory.
+
+ *:FufFileWithCurrentBufferDir*
+:FufFileWithCurrentBufferDir[!] [{pattern}]
+ Is mostly the same as |:FufFile|, except that initial pattern is a
+ path of directory current buffer is in.
+
+ *:FufCoverageFile*
+:FufCoverageFile[!] [{pattern}]
+ Launchs Coverage-File mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufDir*
+:FufDir[!] [{pattern}]
+ Launchs Directory mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufDirWithFullCwd*
+:FufDirWithFullCwd[!] [{pattern}]
+ Is mostly the same as |:FufDir|, except that initial pattern is a full
+ path of current working directory.
+
+ *:FufDirWithCurrentBufferDir*
+:FufDirWithCurrentBufferDir[!] [{pattern}]
+ Is mostly the same as |:FufDir|, except that initial pattern is a path
+ of directory current buffer is in.
+
+ *:FufMruFile*
+:FufMruFile[!] [{pattern}]
+ Launchs MRU-File mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufMruCmd*
+:FufMruCmd[!] [{pattern}]
+ Launchs MRU-Command mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufBookmarkFile*
+:FufBookmarkFile[!] [{pattern}]
+ Launchs Bookmark-File mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufBookmarkDir*
+:FufBookmarkDir[!] [{pattern}]
+ Launchs Bookmark-Dir mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufTag*
+:FufTag[!] [{pattern}]
+ Launchs Tag mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufTagWithCursorWord*
+:FufTagWithCursorWord[!] [{pattern}]
+ Is mostly the same as |:FufTag|, except that
+
+ *:FufTaggedFile*
+:FufTaggedFile[!] [{pattern}]
+ Launchs Tagged-File mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufJumpList*
+:FufJumpList[!] [{pattern}]
+ Launchs Jump-List mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufChangeList*
+:FufChangeList[!] [{pattern}]
+ Launchs Change-List mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufQuickfix*
+:FufQuickfix[!] [{pattern}]
+ Launchs Quickfix mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufLine*
+:FufLine[!] [{pattern}]
+ Launchs Line mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufHelp*
+:FufHelp[!] [{pattern}]
+ Launchs Help mode.
+
+ If a command was executed with a ! modifier, it does partial matching
+ instead of fuzzy matching.
+
+ {pattern} will be inserted after launching FuzzyFinder.
+
+ *:FufEditDataFile*
+:FufEditDataFile
+ Opens a buffer for editing your data files. See |fuf-data-file| for
+ details.
+
+ *:FufCoverageFileRegister*
+:FufCoverageFileRegister
+ Registers new search coverage to be searched in Coverage-File mode.
+ First, input glob patterns, like ~/* . You can add patterns unless
+ typing <Esc>. Next, input coverage name.
+
+ See also: |glob()|, |fuf-coveragefile-mode|
+
+ *:FufCoverageFileChange*
+:FufCoverageFileChange [{name}]
+ Launchs Coverage-File mode with a chosen coverage, registered with
+ |FufCoverageFileRegister| command.
+
+ If location name is given, the choise process will be skipped.
+
+ See also: |fuf-coveragefile-mode|
+
+ *:FufBookmarkFileAdd*
+:FufBookmarkFileAdd [{name}]
+ Adds a cursor line to bookmarks.
+
+ See also: |fuf-bookmarkfile-mode|
+
+ *:FufBookmarkFileAddAsSelectedText*
+:FufBookmarkFileAddAsSelectedText
+ Is mostly the same as |:FufBookmarkFileAdd|, except that initial
+ pattern is last selected one.
+
+ *:FufBookmarkDirAdd*
+:FufBookmarkDirAdd [{name}]
+ Adds a directory to bookmarks.
+
+ See also: |fuf-bookmarkdir-mode|
+
+ *:FufRenewCache*
+:FufRenewCache
+ Removes caches to renew completion items. See |fuf-cache| for details.
+
+
+==============================================================================
+OPTIONS *fuf-options*
+
+ *fuf-options-for-all-modes*
+For All Modes ~
+
+ *g:fuf_modesDisable* >
+ let g:fuf_modesDisable = [ 'mrufile', 'mrucmd', ]
+<
+ List of mode names to disable.
+
+ Modes which are listed will never be initialized and never handle any
+ event.
+
+ *g:fuf_keyOpen* >
+ let g:fuf_keyOpen = '<CR>'
+<
+ Key mapped to select completion item or finish input and open a
+ buffer/file in previous window.
+
+ *g:fuf_keyOpenSplit* >
+ let g:fuf_keyOpenSplit = '<C-j>'
+<
+ Key mapped to select completion item or finish input and open a
+ buffer/file in split new window
+
+ *g:fuf_keyOpenVsplit* >
+ let g:fuf_keyOpenVsplit = '<C-k>'
+<
+ Key mapped to select completion item or finish input and open a
+ buffer/file in vertical-split new window.
+
+ *g:fuf_keyOpenTabpage* >
+ let g:fuf_keyOpenTabpage = '<C-l>'
+<
+
+ Key mapped to select completion item or finish input and open a
+ buffer/file in a new tab page.
+
+ *g:fuf_keyPreview* >
+ let g:fuf_keyPreview = '<C-@>'
+<
+
+ Key mapped to show information of selected completion item on
+ command-line area. This key makes sense only in modes supporting
+ preview.
+
+ *g:fuf_keyNextMode* >
+ let g:fuf_keyNextMode = '<C-t>'
+<
+ Key mapped to switch to next mode.
+
+ *g:fuf_keyPrevMode* >
+ let g:fuf_keyPrevMode = '<C-y>'
+<
+ Key mapped to switch to previous mode.
+
+ *g:fuf_keyPrevPattern* >
+ let g:fuf_keyPrevPattern = '<C-s>'
+<
+ Key mapped to recall previous entered patten from history.
+
+ *g:fuf_keyNextPattern* >
+ let g:fuf_keyNextPattern = '<C-_>'
+<
+ Key mapped to recall next entered patten from history.
+
+ *g:fuf_keySwitchMatching* >
+ let g:fuf_keySwitchMatching = '<C-\><C-\>'
+<
+ Key mapped to switch between fuzzy matching and partial matching.
+
+ *g:fuf_dataDir* >
+ let g:fuf_dataDir = '~/.vim-fuf-data'
+<
+ Directory path to which data files is put. If empty string,
+ FuzzyFinder does not write data files.
+
+ *g:fuf_abbrevMap* >
+ let g:fuf_abbrevMap = {}
+<
+ |Dictionary|. Each value must be a |List|. All matchs of a
+ key in entered text is expanded with the value.
+
+ *g:fuf_patternSeparator* >
+ let g:fuf_patternSeparator = ';'
+<
+ String which sparates a input pattern into a primary pattern and
+ refining patterns.
+
+ *g:fuf_promptHighlight* >
+ let g:fuf_promptHighlight = 'Question'
+<
+ a highlight group name for a prompt string.
+
+ *g:fuf_ignoreCase* >
+ let g:fuf_ignoreCase = 1
+<
+ If non-zero, FuzzyFinder ignores case in search patterns.
+
+ *g:fuf_splitPathMatching* >
+ let g:fuf_splitPathMatching = 1
+<
+ If non-zero, matching with a primary pattern is divided into head part
+ and tail part and done individually.
+
+ See also: |fuf-search-patterns|
+
+ *g:fuf_fuzzyRefining* >
+ let g:fuf_fuzzyRefining = 0
+<
+ If non-zero, fuzzy matching is done with refining pattern instead of
+ partial matching.
+
+ See also: |fuf-search-patterns|
+
+ *g:fuf_reuseWindow* >
+ let g:fuf_reuseWindow = 1
+<
+ If non-zero and when FuzzyFinder opens a buffer which has already been
+ opened, it reuses a window containing the target buffer.
+
+ *g:fuf_timeFormat* >
+ let g:fuf_timeFormat = '(%Y-%m-%d %H:%M:%S)'
+<
+ String to format time string. See |strftime()| for details.
+
+ *g:fuf_learningLimit* >
+ let g:fuf_learningLimit = 100
+<
+ Ceiling for the number of completion statistics to be stored.
+
+ *g:fuf_enumeratingLimit* >
+ let g:fuf_enumeratingLimit = 50
+<
+ To speed up the response time, FuzzyFinder ends enumerating completion
+ items when found over this.
+
+ *g:fuf_maxMenuWidth* >
+ let g:fuf_maxMenuWidth = 78
+<
+ If a length of a completion item is more than this, it is snipped in
+ completion menu.
+
+ *g:fuf_previewHeight* >
+ let g:fuf_previewHeight = 0
+<
+ 'cmdheight' is set to this when a mode supporting preview is launched.
+ Information of selected completion item will be shown on command-line
+ area. If zero, preview feature is disabled.
+
+ *g:fuf_autoPreview* >
+ let g:fuf_autoPreview = 0
+<
+ If non-zero, previews will be shown automatically.
+
+ *g:fuf_useMigemo* >
+ let g:fuf_useMigemo = 0
+<
+ If non-zero, FuzzyFinder uses Migemo.
+
+ *fuf-options-for-buffer-mode*
+For Buffer Mode ~
+
+ *g:fuf_buffer_prompt* >
+ let g:fuf_buffer_prompt = '>Buffer[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_buffer_switchOrder* >
+ let g:fuf_buffer_switchOrder = 10
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_buffer_mruOrder* >
+ let g:fuf_buffer_mruOrder = 1
+<
+ If non-zero, completion items is sorted in order of recently used.
+
+ *g:fuf_buffer_keyDelete* >
+ let g:fuf_buffer_keyDelete = '<C-]>'
+<
+ Key mapped to delete selected buffer.
+
+ *fuf-options-for-file-mode*
+For File Mode ~
+
+ *g:fuf_file_prompt* >
+ let g:fuf_file_prompt = '>File[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_file_switchOrder* >
+ let g:fuf_file_switchOrder = 20
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_file_exclude* >
+ let g:fuf_file_exclude = '\v\~$|\.(o|exe|dll|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ Regexp pattern for items which you want to exclude from completion
+ list.
+
+ *fuf-options-for-coveragefile-mode*
+For Coverage-File Mode ~
+
+ *g:fuf_coveragefile_prompt* >
+ let g:fuf_coveragefile_prompt = '>CoverageFile[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_coveragefile_switchOrder* >
+ let g:fuf_coveragefile_switchOrder = 30
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_coveragefile_exclude* >
+ let g:fuf_coveragefile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ Regexp pattern for items which you want to exclude from completion
+ list.
+
+ *g:fuf_coveragefile_globPatterns* >
+ let g:fuf_coveragefile_globPatterns = ['**/.*', '**/*']
+<
+ List of glob patterns to get file paths to be searched.
+
+ See also: |glob()|
+
+ *fuf-options-for-dir-mode*
+For Directory Mode ~
+
+ *g:fuf_dir_prompt* >
+ let g:fuf_dir_prompt = '>Dir[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_dir_switchOrder* >
+ let g:fuf_dir_switchOrder = 40
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_dir_exclude* >
+ let g:fuf_dir_exclude = '\v(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+<
+ Regexp pattern for items which you want to exclude from completion
+ list.
+
+ *fuf-options-for-mrufile-mode*
+For MRU-File Mode ~
+
+ *g:fuf_mrufile_prompt* >
+ let g:fuf_mrufile_prompt = '>MRU-File[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_mrufile_switchOrder* >
+ let g:fuf_mrufile_switchOrder = 50
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_mrufile_exclude* >
+ let g:fuf_mrufile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+<
+ Regexp pattern for items which you want to exclude from completion
+ list.
+
+ *g:fuf_mrufile_maxItem* >
+ let g:fuf_mrufile_maxItem = 200
+<
+ Ceiling for the number of MRU items to be stored.
+
+ *g:fuf_mrufile_maxItemDir* >
+ let g:fuf_mrufile_maxItemDir = 50
+<
+ Ceiling for the number of parent directories of MRU items to be
+ stored, which are used for around search.
+
+ *g:fuf_mrufile_keyExpand* >
+ let g:fuf_mrufile_keyExpand = '<C-]>'
+<
+ Key mapped to expand search range.
+
+ *fuf-options-for-mrucmd-mode*
+For MRU-Cmd Mode ~
+
+ *g:fuf_mrucmd_prompt* >
+ let g:fuf_mrucmd_prompt = '>MRU-Cmd[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_mrucmd_switchOrder* >
+ let g:fuf_mrucmd_switchOrder = 70
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_mrucmd_exclude* >
+ let g:fuf_mrucmd_exclude = '^$'
+<
+ Regexp pattern for items which you want to exclude from completion
+ list.
+
+ *g:fuf_mrucmd_maxItem* >
+ let g:fuf_mrucmd_maxItem = 200
+<
+ This is the ceiling for the number of MRU items to be stored.
+
+ *fuf-options-for-bookmarkfile-mode*
+For Bookmark-File Mode ~
+
+ *g:fuf_bookmarkfile_prompt* >
+ let g:fuf_bookmarkfile_prompt = '>BookmarkFile[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_bookmarkfile_switchOrder* >
+ let g:fuf_bookmarkfile_switchOrder = 80
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_bookmarkfile_searchRange* >
+ let g:fuf_bookmarkfile_searchRange = 400
+<
+ Number of lines which FuzzyFinder searches a matching line from
+ bookmarked position within.
+
+ *g:fuf_bookmarkfile_keyDelete* >
+ let g:fuf_bookmarkfile_keyDelete = '<C-]>'
+<
+ Key mapped to delete selected bookmark.
+
+ *fuf-options-for-bookmarkdir-mode*
+For Bookmark-Dir Mode ~
+
+ *g:fuf_bookmarkdir_prompt* >
+ let g:fuf_bookmarkdir_prompt = '>BookmarkDir[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_bookmarkdir_switchOrder* >
+ let g:fuf_bookmarkdir_switchOrder = 90
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *g:fuf_bookmarkdir_keyDelete* >
+ let g:fuf_bookmarkdir_keyDelete = '<C-]>'
+<
+ Key mapped to delete selected bookmark.
+
+ *fuf-options-for-tag-mode*
+For Tag Mode ~
+
+ *g:fuf_tag_prompt* >
+ let g:fuf_tag_prompt = '>Tag[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_tag_switchOrder* >
+ let g:fuf_tag_switchOrder = 100
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-taggedfile-mode*
+For Tagged-File Mode ~
+
+ *g:fuf_taggedfile_prompt* >
+ let g:fuf_taggedfile_prompt = '>Tagged-File[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_taggedfile_switchOrder* >
+ let g:fuf_taggedfile_switchOrder = 110
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-jumplist-mode*
+For Jump-List Mode ~
+
+ *g:fuf_jumplist_prompt* >
+ let g:fuf_jumplist_prompt = '>Jump-List[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_jumplist_switchOrder* >
+ let g:fuf_jumplist_switchOrder = 120
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-changelist-mode*
+For Change-List Mode ~
+
+ *g:fuf_changelist_prompt* >
+ let g:fuf_changelist_prompt = '>Change-List[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_changelist_switchOrder* >
+ let g:fuf_changelist_switchOrder = 130
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-quickfix-mode*
+For Quickfix Mode ~
+
+ *g:fuf_quickfix_prompt* >
+ let g:fuf_quickfix_prompt = '>Quickfix[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_quickfix_switchOrder* >
+ let g:fuf_quickfix_switchOrder = 140
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-line-mode*
+For Line Mode ~
+
+ *g:fuf_line_prompt* >
+ let g:fuf_line_prompt = '>Line[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_line_switchOrder* >
+ let g:fuf_line_switchOrder = 150
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+ *fuf-options-for-help-mode*
+For Help Mode ~
+
+ *g:fuf_help_prompt* >
+ let g:fuf_help_prompt = '>Help[]>'
+<
+ Prompt string. "[]" will be substituted with indicators.
+
+ *g:fuf_help_switchOrder* >
+ let g:fuf_help_switchOrder = 160
+<
+ Number of order for switching to the next/previous mode. If negative
+ number, Fuzzyfinder never switches to this mode.
+
+
+==============================================================================
+VIMRC EXAMPLE *fuf-vimrc-example*
+
+>
+ let g:fuf_modesDisable = []
+ let g:fuf_abbrevMap = {
+ \ '^vr:' : map(filter(split(&runtimepath, ','), 'v:val !~ "after$"'), 'v:val . ''/**/'''),
+ \ '^m0:' : [ '/mnt/d/0/', '/mnt/j/0/' ],
+ \ }
+ let g:fuf_mrufile_maxItem = 500
+ let g:fuf_mrucmd_maxItem = 500
+ nnoremap <silent> sj :FufBuffer<CR>
+ nnoremap <silent> sk :FufFileWithCurrentBufferDir<CR>
+ nnoremap <silent> sK :FufFileWithFullCwd<CR>
+ nnoremap <silent> s<C-k> :FufFile<CR>
+ nnoremap <silent> sl :FufCoverageFileChange<CR>
+ nnoremap <silent> sL :FufCoverageFileChange<CR>
+ nnoremap <silent> s<C-l> :FufCoverageFileRegister<CR>
+ nnoremap <silent> sd :FufDirWithCurrentBufferDir<CR>
+ nnoremap <silent> sD :FufDirWithFullCwd<CR>
+ nnoremap <silent> s<C-d> :FufDir<CR>
+ nnoremap <silent> sn :FufMruFile<CR>
+ nnoremap <silent> sm :FufMruCmd<CR>
+ nnoremap <silent> su :FufBookmarkFile<CR>
+ nnoremap <silent> s<C-u> :FufBookmarkFileAdd<CR>
+ vnoremap <silent> s<C-u> :FufBookmarkFileAddAsSelectedText<CR>
+ nnoremap <silent> si :FufBookmarkDir<CR>
+ nnoremap <silent> s<C-i> :FufBookmarkDirAdd<CR>
+ nnoremap <silent> st :FufTag<CR>
+ nnoremap <silent> sT :FufTag!<CR>
+ noremap <silent> s] :FufTagWithCursorWord!<CR>
+ nnoremap <silent> sg :FufTaggedFile<CR>
+ nnoremap <silent> sG :FufTaggedFile!<CR>
+ nnoremap <silent> so :FufJumpList<CR>
+ nnoremap <silent> sp :FufChangeList<CR>
+ nnoremap <silent> sq :FufQuickfix<CR>
+ nnoremap <silent> sy :FufLine<CR>
+ nnoremap <silent> sh :FufHelp<CR>
+ nnoremap <silent> se :FufEditDataFile<CR>
+ nnoremap <silent> sr :FufRenewCache<CR>
+<
+
+==============================================================================
+SPECIAL THANKS *fuf-thanks*
+
+- Vincent Wang
+- Ingo Karkat
+- Nikolay Golubev
+- Brian Doyle
+- id:secondlife
+- Nathan Neff
+
+
+==============================================================================
+CHANGELOG *fuf-changelog*
+
+4.1.1:
+ - Fixed a bug causing a error in MRU-File mode.
+
+4.1:
+ - Added Bookmark-Dir mode.
+ - Added Bookmark-File mode and removed Bookmark mode.
+ - Changed the filename to store data of Coverage-File mode, from
+ '~/.vim-fuf-data/coveragefile/items' to
+ '~/.vim-fuf-data/coveragefile/coverages' .
+ - Fixed a bug that floating point numbers weren't evaluated correctly and
+ caused errors on some non-English locales.
+ - Removed Around-MRU-File mode and integrated its feature to MRU-File mode.
+
+4.0:
+ - From this version, L9 library (vimscript #3252) is required.
+ - Added Coverage-File mode for users wanting something like TextMate's
+ command-t. (But I've never used it.)
+ - Added Around-MRU-File mode. (Too slow. There is room for improvement.)
+ - Added new feature which deletes selected buffer with FuzzyFinder and
+ g:fuf_buffer_keyDelete option.
+ - Added new feature which allows to set one-time options/variables with
+ fuf#setOneTimeVariables() function.
+ - Added g:fuf_dataDir option and removed g:fuf_infoFile,
+ g:g:fuf_tag_cache_dir, g:fuf_taggedfile_cache_dir, and
+ g:fuf_help_cache_dir options.
+ - Added :FufEditDataFile command and removed :FufEditInfo command.
+ - Added g:fuf_fuzzyRefining option.
+ - Added new feature which is auto-preview and g:fuf_autoPreview option.
+ - Changed the default value of g:fuf_previewHeight to 0 in order to disable
+ preview feature. There is an unfixable problem which is caused by a Vim's
+ bug.
+ - Changed the default value of g:fuf_modesDisable option.
+ - Changed the default value of g:fuf_*_switchOrder options.
+ - Improved speed of changing buffers.
+ - Improved the way to add user-defined mode.
+ - Fixed a bug that FuzzyFinder caused reseting window layout.
+ - Removed g:fuf_smartBs option. Use <C-w> instead.
+
+3.5:
+ - Added Line mode.
+ - Added Help mode.
+ - Added key mapping to switch between fuzzy matching and partial matching.
+ - Changed the default values of g:fuf_file_exclude for ignoring "*.dll".
+ - Changed Tag mode and Tagged-File mode to cache parsed data to files in
+ "~/.vim-fuf-cache/".
+ - Fixed a bug that repeating preview key produced no effect.
+ - Fixed a bug that File mode and Directory mode didn't list items in a
+ directory whose name includes uppercase characters. (Thanks, ryo7000)
+
+3.4:
+ - Added new feature which makes it possible to preview selected completion
+ item.
+ - Changed matching rules and added g:fuf_splitPathMatching.
+ - Changed sorting rules.
+ - Changed the default values of g:fuf_file_exclude and g:fuf_dir_exclude in
+ order to ignore ".hg", ".git", and ".bzr" directories.
+ - Changed the default value of g:fuf_mrufile_exclude in order to ignore
+ network files (\\*) on Windows and ignore /mnt/* and /media/* on Unix like
+ systems.
+ - Fixed a bug that an exclude pattern of File, Dir, and Callback-File mode
+ can't be changed.
+
+3.3:
+ - Added Jump-List mode, Change-List mode, and Quickfix mode which enable
+ jumps with jump list, change list, and quickfix list.
+ - Added new feature which deletes selected bookmark with FuzzyFinder and
+ g:fuf_bookmark_keyDelete option.
+ - Changed default values of g:fuf_keyPrevPattern.
+ - Changed to show error message when incompatible with a installed vim.
+
+3.2:
+ - Added g:fuf_promptHighlight option to integrate such options for each
+ mode.
+ - Changed APIs of Given-File, Given-Directory, Given-Command, Callback-File,
+ and Callback-Item modes to be able to set a prompt string.
+ - Changed default values of g:fuf_keyPrevPattern and g:fuf_keyNextPattern.
+ - Fixed a bug that MRU-File data was not updated When a file was opened with
+ FuzzyFinder.
+ - Fixed a bug with scoring matchings for sorting. Thanks to Vincent.
+ - Brought back the removed feature which is switching to an other mode in
+ FuzzyFinder.
+
+3.1:
+ - Added new feature to recall patterns which have been entered before from
+ history.
+
+3.0:
+ - Redesigned the whole plugin for improvements of maintainability and
+ performance. "fuzzyfinder" is abbreviated to "fuf" in the sorce code and
+ filenames. All commands and options are renamed.
+ - Added new feature which is refining pattern.
+ - Improved the rules for sorting completion items. Thanks to the suggestion
+ by Nathan, the rule for boundary matching was implemented.
+ - Changed to open one line buffer of FuzzyFinder with :topleft command
+ instead of :leftabove. The window will alway appear at the top and occupy
+ the full with of the vim window. Thanks to Jan Christoph.
+ - Changed default filename of information file.
+ - Changed MRU-File mode and MRU-Command mode to be disabled by default
+ due to performance and side effect issues.
+ - Removed the feature which is switching to an other mode in FuzzyFinder.
+ - Removed the feature which is temporarily switching 'ignorecase' in
+ FuzzyFinder.
+
+2.22.3:
+ - Fixed a bug that Fuzzyfinder could not open files with '$' in the name on
+ Windows.
+
+2.22.2:
+ - Changed to consider a length of a date/time string when abbreviates long
+ completion items.
+ - Fixed a bug that '**/' pattern did not search for files directly under the
+ current working directory in File mode. Thanks to Martin for reporting.
+
+2.22.1:
+ - Fixed a bug that Fuzzyfinder could not expand abbreviations to patterns
+ including '\' correctly.
+ - Fixed to show item number in Given-File, Given-Directory, and
+ Given-Command mode.
+
+2.22.0:
+ - More improved the abbreviation method for long completion items.
+ - Added Given-File mode for third-party script to select a file from a given
+ list and open.
+ - Added Given-Directory mode for third-party script to select a directory
+ from a given list and change current working directory to it.
+ - Added Given-Command mode for third-party script to select a command from a
+ given list and execute.
+ - Changed ways to launch Callback-File mode and Callback-item mode.
+
+2.21.0:
+ - Improved a method of trimming long completion items. Thanks to Andy,
+ pyrhockz, and Nathan.
+ - Changed not to map command-line <CR> for MRU-Command mode if
+ g:FuzzyFinderOptions.MruCmd.mode_available is set 0 before loading
+ fuzzyfinder.vim.
+ - Added Callback-File mode and Callback-Item mode for third-party script to
+ find a file/directory or an item from a given list using Fuzzyfinder.
+ - Changed not to append ".." to a completion menu in File/Directory mode.
+ Use dot sequence feature.
+ - Changed default value of g:FuzzyFinderOptions.File.excluded_path option.
+ - Changed default value of g:FuzzyFinderOptions.Dir.excluded_path option.
+ - Fixed a bug that couldn't jump to a tag. Thanks to Thinca.
+
+2.20:
+ - Added help files which are doc/fuzzyfinder.txt and doc/fuzzyfinder.jax.
+ - Fixed a bug that an error occurs if current directory included spaces.
+ Thanks id:cho45 and id:secondlife.
+ - Implemented a feature to reuse a window containing target buffer.
+ - Added g:FuzzyFinderOptions.Buffer.reuse_window option.
+ - Added g:FuzzyFinderOptions.File.reuse_window option.
+ - Added g:FuzzyFinderOptions.MruFile.reuse_window option.
+ - Added g:FuzzyFinderOptions.Bookmark.reuse_window option.
+ - Added g:FuzzyFinderOptions.TaggedFile.reuse_window option.
+ - Changed to use 'omnifunc' instead of 'completefunc'. Now you can use <C-u>
+ to delete all entered characters.
+ - Changed default value of g:FuzzyFinderOptions.Base.key_open_tab option.
+ - Changed default value of g:FuzzyFinderOptions.Base.key_next_mode option.
+ - Changed default value of g:FuzzyFinderOptions.Base.key_prev_mode option.
+ - Changed default value of g:FuzzyFinderOptions.Base.key_ignore_case option.
+ - Changed to truncate long completion items from the head instead of tail.
+ - Added g:FuzzyFinderOptions.Base.max_menu_width option instead of
+ g:FuzzyFinderOptions.Base.trim_length option.
+ - Added :FuzzyFinderFileWithFullCwd command.
+ - Added :FuzzyFinderFileWithCurrentBufferDir command.
+ - Added :FuzzyFinderDirWithFullCwd command.
+ - Added :FuzzyFinderDirWithCurrentBufferDir command.
+ - Added :FuzzyFinderTagWithCursorWord command.
+ - Renamed :FuzzyFinderRemoveCache command to :FuzzyFinderRenewCache.
+
+2.19:
+ - Changed MRU-File mode that always formats completion items to be relative
+ to the home directory.
+ - Fixed a bug that a file was opened in an unintended window with Tag List
+ plugin. Thanks Alexey.
+ - Fixed a bug that garbage characters were entered when switched current
+ mode. Thanks id:lugecy.
+
+2.18:
+ - Improved rules for the sorting of completion items.
+ - Changed not to learn a completion if an entered pattern is empty.
+ - Fixed a bug that Buffer mode did not work. Thanks ryo7000.
+
+2.17:
+ - Introduced a learning system for the sorting of completion items.
+ - Added g:FuzzyFinderOptions.Base.learning_limit option.
+ - Changed the specification of the information file. Please remove your
+ information file for Fuzzyfinder.
+
+2.16:
+ - Improved response time by caching in MRU-File mode.
+ - Fixed a bug in Bookmark mode that Fuzzyfinder did not jump to the
+ Bookmarked line number when Bookmarked pattern was not found.
+
+2.15:
+ - Added Bookmark mode.
+ - Removed Favorite-file mode. Use Bookmark mode instead.
+ - Fixed not to record a entry of input() in MRU-Command mode.
+
+2.14:
+ - Changed to show buffer status in Buffer mode.
+ - Fixed a bug that an error occurs when nonexistent buffer-name was entered
+ in Buffer mode. Thanks Maxim Kim.
+ - Added 'enumerating_limit' option. Thanks id:secondlife.
+ - Removed 'matching_limit' option. Use 'enumerating_limit' instead.
+
+2.13:
+ - Fixed a bug that a directory disappeared when a file in that directory was
+ being opened in File/Mru-File mode.
+
+2.12:
+ - Changed to be able to show completion items in the order of recently used
+ in Buffer mode.
+ - Added g:FuzzyFinderOptions.Buffer.mru_order option.
+
+2.11:
+ - Changed that a dot sequence of entered pattern is expanded to parent
+ directories in File/Dir mode.
+ E.g.: "foo/...bar" -> "foo/../../bar"
+ - Fixed a bug that a prompt string was excessively inserted.
+
+2.10:
+ - Changed not to show a current buffer in a completion menu.
+ - Fixed a bug that a filename to open was not been escaped.
+ - Added 'prompt' option.
+ - Added 'prompt_highlight' option.
+ - Removed g:FuzzyFinderOptions.MruFile.no_special_buffer option.
+
+2.9:
+ - Enhanced <BS> behavior in Fuzzyfinder and added 'smart_bs' option.
+ - Fixed a bug that entered pattern was not been escaped.
+ - Fixed not to insert "zv" with "c/pattern<CR>" command in Normal mode.
+ - Avoid the slow down problem caused by filereadable() check for the MRU
+ information in BufEnter/BufWritePost.
+
+2.8.1:
+ - Fixed a bug caused by the non-escaped buffer name "[Fuzzyfinder]".
+ - Fixed a command to open in a new tab page in Buffer mode.
+2.8:
+ - Added 'trim_length' option.
+ - Added 'switch_order' option.
+ - Fixed a bug that entered command did not become the newest in the history.
+ - Fixed a bug that folds could not open with <CR> in a command-line when
+ searching.
+ - Removed 'excluded_indicator' option. Now a completion list in Buffer mode
+ is the same as a result of :buffers.
+
+2.7:
+ - Changed to find an item whose index is matched with the number suffixed
+ with entered pattern.
+ - Fixed the cache bug after changing current directory in File mode.
+
+2.6.2:
+ - Fixed not to miss changes in options when updates the MRU information.
+
+2.6.1:
+ - Fixed a bug related to floating-point support.
+ - Added support for GetLatestVimScripts.
+
+2.6:
+ - Revived MRU-command mode. The problem with a command-line abbreviation was
+ solved.
+ - Changed the specification of the information file.
+ - Added :FuzzyFinderEditInfo command.
+
+2.5.1:
+ - Fixed to be able to match "foo/./bar" by "foo/**/bar" in File mode.
+ - Fixed to be able to open a space-containing file in File mode.
+ - Fixed to honor the current working directory properly in File mode.
+
+2.5:
+ - Fixed the bug that a wrong initial text is entered after switching to a
+ next mode.
+ - Fixed the bug that it does not return to previous window after leaving
+ Fuzzyfinder one.
+
+2.4:
+ - Fixed the bug that Fuzzyfinder fails to open a file caused by auto-cd
+ plugin/script.
+
+2.3:
+ - Added a key mapping to open items in a new tab page and
+ g:FuzzyFinderOptions.Base.key_open_tab option.
+ - Changed to show Fuzzyfinder window above last window even if 'splitbelow'
+ was set.
+ - Changed to set nocursorline and nocursorcolumn in Fuzzyfinder.
+ - Fixed not to push up a buffer number unlimitedly.
+
+2.2:
+ - Added new feature, which is the partial matching.
+ - Fixed the bug that an error occurs when "'" was entered.
+
+2.1:
+ - Restructured the option system AGAIN. Sorry :p
+ - Changed to inherit a typed text when switching a mode without leaving
+ Insert mode.
+ - Changed commands which launch explorers to be able to take a argument for
+ initial text.
+ - Changed to complete file names by relative path and not full path in the
+ buffer/mru-file/tagged-file mode.
+ - Changed to highlight a typed text when the completion item was not found
+ or the completion process was aborted.
+ - Changed to create caches for each tag file and not working directory in
+ the tag/tagged-file mode.
+ - Fixed the bug that the buffer mode couldn't open a unnamed buffer.
+ - Added 'matching_limit' option.
+ - Removed 'max_match' option. Use 'matching_limit' option instead.
+ - Removed 'initial_text' option. Use command argument instead.
+ - Removed the MRU-command mode.
+
+2.0:
+ - Added the tag mode.
+ - Added the tagged-file mode.
+ - Added :FuzzyFinderRemoveCache command.
+ - Restructured the option system. many options are changed names or default
+ values of some options.
+ - Changed to hold and reuse caches of completion lists by default.
+ - Changed to set filetype 'fuzzyfinder'.
+ - Disabled the MRU-command mode by default because there are problems.
+ - Removed FuzzyFinderAddMode command.
+
+1.5:
+ - Added the directory mode.
+ - Fixed the bug that it caused an error when switch a mode in Insert mode.
+ - Changed g:FuzzyFinder_KeySwitchMode type to a list.
+
+1.4:
+ - Changed the specification of the information file.
+ - Added the MRU-commands mode.
+ - Renamed :FuzzyFinderAddFavorite command to :FuzzyFinderAddFavFile.
+ - Renamed g:FuzzyFinder_MruModeVars option to g:FuzzyFinder_MruFileModeVars.
+ - Renamed g:FuzzyFinder_FavoriteModeVars option to
+ g:FuzzyFinder_FavFileModeVars.
+ - Changed to show registered time of each item in MRU/favorite mode.
+ - Added 'timeFormat' option for MRU/favorite modes.
+
+1.3:
+ - Fixed a handling of multi-byte characters.
+
+1.2:
+ - Added support for Migemo. (Migemo is Japanese search method.)
+
+1.1:
+ - Added the favorite mode.
+ - Added new features, which are abbreviations and multiple search.
+ - Added 'abbrevMap' option for each mode.
+ - Added g:FuzzyFinder_MruModeVars['ignoreSpecialBuffers'] option.
+ - Fixed the bug that it did not work correctly when a user have mapped <C-p>
+ or <Down>.
+
+1.0:
+ - Added the MRU mode.
+ - Added commands to add and use original mode.
+ - Improved the sorting algorithm for completion items.
+ - Added 'initialInput' option to automatically insert a text at the
+ beginning of a mode.
+ - Changed that 'excludedPath' option works for the entire path.
+ - Renamed some options.
+ - Changed default values of some options.
+ - Packed the mode-specific options to dictionaries.
+ - Removed some options.
+
+0.6:
+ - Fixed some bugs.
+
+0.5:
+ - Improved response by aborting processing too many items.
+ - Changed to be able to open a buffer/file not only in previous window but
+ also in new window.
+ - Fixed a bug that recursive searching with '**' does not work.
+ - Added g:FuzzyFinder_CompletionItemLimit option.
+ - Added g:FuzzyFinder_KeyOpen option.
+
+0.4:
+ - Improved response of the input.
+ - Improved the sorting algorithm for completion items. It is based on the
+ matching level. 1st is perfect matching, 2nd is prefix matching, and 3rd
+ is fuzzy matching.
+ - Added g:FuzzyFinder_ExcludePattern option.
+ - Removed g:FuzzyFinder_WildIgnore option.
+ - Removed g:FuzzyFinder_EchoPattern option.
+ - Removed g:FuzzyFinder_PathSeparator option.
+ - Changed the default value of g:FuzzyFinder_MinLengthFile from 1 to 0.
+
+0.3:
+ - Added g:FuzzyFinder_IgnoreCase option.
+ - Added g:FuzzyFinder_KeyToggleIgnoreCase option.
+ - Added g:FuzzyFinder_EchoPattern option.
+ - Changed the open command in a buffer mode from ":edit" to ":buffer" to
+ avoid being reset cursor position.
+ - Changed the default value of g:FuzzyFinder_KeyToggleMode from <C-Space> to
+ <F12> because <C-Space> does not work on some CUI environments.
+ - Changed to avoid being loaded by Vim before 7.0.
+ - Fixed a bug with making a fuzzy pattern which has '\'.
+
+0.2:
+ - A bug it does not work on Linux is fixed.
+
+0.1:
+ - First release.
+
+
+==============================================================================
+ABOUT *fuf-about* *fuf-contact* *fuf-author*
+
+Author: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
+Licence: MIT Licence
+URL: http://www.vim.org/scripts/script.php?script_id=1984
+ http://bitbucket.org/ns9tks/vim-fuzzyfinder/
+
+Bugs/Issues/Suggestions/Improvements ~
+
+Please submit to http://bitbucket.org/ns9tks/vim-fuzzyfinder/issues/ .
+
+==============================================================================
+ vim:tw=78:ts=8:ft=help:norl:
diff --git a/doc/l9.jax b/doc/l9.jax
new file mode 100644
index 0000000..9b11bc7
--- /dev/null
+++ b/doc/l9.jax
@@ -0,0 +1,55 @@
+*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スクリプトの関数やコマンドを提供するライブラリです。
+
+
+==============================================================================
+インストール *fuf-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:
diff --git a/doc/l9.txt b/doc/l9.txt
new file mode 100644
index 0000000..ca7b303
--- /dev/null
+++ b/doc/l9.txt
@@ -0,0 +1,67 @@
+*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 *fuf-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.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:
diff --git a/doc/vim-addon-manager.txt b/doc/vim-addon-manager.txt
new file mode 100644
index 0000000..32e1ca1
--- /dev/null
+++ b/doc/vim-addon-manager.txt
@@ -0,0 +1,572 @@
+*vim-addon-manager.txt* Package manager for Vim
+==============================================================================
+CONTENS *vim-addon-manager-contents*
+
+ 1. Intro |vim-addon-manager-intro|
+ 2. Installation |vim-addon-manager-installation|
+ 3. Functionality provided |vim-addon-manager-functionality|
+ 3.1. Commands |vim-addon-manager-commands|
+ 3.2. Functions |vim-addon-manager-functions|
+ 4. Options |vim-addon-manager-options|
+ 5. Installing plugins |vim-addon-manager-install-plugins|
+ 6. Addon-info file |vim-addon-manager-addon-info|
+ 7. Author, credits, some notes |vim-addon-manager-related|
+ 8. Testing this plugin |vim-addon-manager-testing|
+ 9. Some notes for windows users |vim-addon-manager-windows|
+ 10. Some notes for Gentoo users |vim-addon-manager-gentoo|
+ 11. Trouble shooting & KNOWS BUGS |vim-addon-manager-trouble-shooting|
+
+==============================================================================
+1. Intro *vim-addon-manager-intro*
+
+This plugin allows users to install and uninstall plugins with a minimum of
+work. Features:
+
+ - Separate directories for each plugins
+ - Dependency resolution
+ - Popular VCS support: plugin supports fetching from Mercurial, Git and
+ Subversion repositories
+
+Dependencies:
+ - Curl, wget or other program that can output URL contents to stdout (in
+ order to get http protocol support)
+ - Mercurial, Git and Subversion (if you want to install plugins from
+ appropriate repositories)
+ - vcs_checkouts plugin (comes with this addon)
+ - Tar, gzip and zip (required for unpacking some addons)
+ - Vimball plugin (required for installing some addons) (in latest vim it
+ is included by default)
+
+------------------------------------------------------------------------------
+Getting started fast: ~
+Read:
+|vim-addon-manager-installation|
+|vim-addon-manager-install-plugins|
+
+==============================================================================
+2. Installation *vim-addon-manager-installation*
+
+Windows users: see |vim-addon-manager-windows|.
+Gentoo users: see |vim-addon-manager-gentoo|.
+
+1. Create a separate directory that will hold your plugins, for example
+ ~/vim-addons The addon manager intentionally installs each addon
+ into its own directory which is not ~/.vim .
+2. Install vim-addon-manager to ~/vim-addons/vim-addon-manager. If you use
+ git, you should do the following: >
+ cd ~/vim-addons
+ git clone git://github.com/MarcWeber/vim-addon-manager.git
+< Git will create ~/vim-addons/vim-addon-manager for you.
+3. Add ~/vim-addons/vim-addon-manager to your runtimepath by adding the
+ following lines to your vimrc: >
+ fun ActivateAddons()
+ set runtimepath+=~/vim-addons/vim-addon-manager
+ try
+ call scriptmanager#Activate([])
+ catch /.*/
+ echoe v:exception
+ endtry
+ endf
+ call ActivateAddons()
+ " experimental: run after gui has been started
+ " report breakage in this case, please
+ " au GUIEnter * call Activate()
+
+
+Continue reading|vim-addon-manager-install-plugins|.
+
+==============================================================================
+3. Functionality provided *vim-addon-manager-functionality*
+
+------------------------------------------------------------------------------
+3.1. Commands *vim-addon-manager-commands*
+
+ActivateAddons {name} ... *:ActivateAddons*
+ Activate addons with given names. See |scriptmanager#Activate()| for
+ more details.
+
+ActivateInstalledAddons {name} ... *:ActivateInstalledAddons*
+ See |:ActivateAddons|, this command is just the same, but completion
+ function completes only installed addon names.
+
+UpdateAddons [{name} ...] *:UpdateAddons*
+ Update addons with given names. Without arguments updates all addons.
+ See |scriptmanager2#Update()| for more details.
+
+UninstallNotLoadedAddons {name} ... *:UninstallNotLoadedAddons*
+ Unistall addons with given names. See
+ |scriptmanager2#UninstallAddons()| for more details.
+
+------------------------------------------------------------------------------
+3.2. Functions *vim-addon-manager-functions*
+
+scriptmanager#Activate([{name}, ...]) *scriptmanager#Activate()*
+ Activates addons with given names. Used by |:ActivateAddons|.
+ Note: This is probably all you need.
+ Second note: [{name}, ...] in arguments means that you should pass
+ a list of strings, not that {name} is optional. Typical calls (both
+ are equivalent): >
+ call scriptmanager#Activate([
+ \ "name1",
+ \ "name2",
+ \ ])
+ call scriptmanager#Activate(
+ \ "name1",
+ \ "name2"
+ \ )
+<
+ Activating a plugin means that function will do the following steps:
+ 0. Check, whether requested addon is already installed. If not,
+ install it.
+ 1. Activate plugins that are mentioned in dependencies dictionary (see
+ |addon-info-dependencies|)
+ 2. Add plugin runtime directory to 'runtimepath' option
+ 3. Check whether vim has already started. If it was then source first
+ all files under addon's plugin directory, then under after/plugin
+ directory. If it was not, then wait until vim loads and source
+ files under addon's after/plugin directory (Vim does not sources
+ them in this case by default).
+ Note that in order to bring installed plugins to work, you need to add
+ the following line to your vimrc: >
+ call scriptmanager#Activate([List_of_all_addons_you_need])
+
+scriptmanager2#Install([{arg}]) *scriptmanager2#Install()*
+ Installs plugins from the given list. Each {arg} may be one the
+ following:
+ - Name of the plugin
+ - Path to |addon-info.txt| file (it must contain at least one
+ forward or back slash, so use `./plugname-addon-info.txt' for
+ files located in the current directory)i
+ - |addon-info.txt| URL. In this case {arg} must start with
+ `http://'.
+ After installing the plugin help tags are updated, see |:helptags|.
+
+scriptmanager2#Update([{name}]) *scriptmanager2#Update()*
+ Updates plugins with given names. If an empty list is given, then
+ updates all plugins. Note that it is able to update only those plugins
+ that were fetched by VCS. scriptmanager2#Update also updates the help
+ tags.
+
+scriptmanager#AddonInfo({name}) *scriptmanager#AddonInfo()*
+ Returns dictionary that contains information given in |addon-info.txt|
+ file that comes with requested addon. If no |addon-info.txt| file is
+ present, it is not readable or addon with given name is not installed,
+ then it returns empty dictionary.
+
+ *scriptmanage2#MergePluginFiles()*
+scriptmanager2#MergePluginFiles([{name}] [, blacklist-regex ])
+ Highly experimental function that may speed up vim start on heavy IO
+ load. This function renames all `plugin' directories to
+ contents into `~/.vim/after/plugin/vim-addon-manager-merged.vim' which
+ should cause less IO stress to your system, thus Vim will startup
+ faster. This can scripts because:
+ - s:... script global variables are renamed automatically to
+ prevent name clashes
+ - Guards are replaced by if ... endif which might be inefficient
+ - `finish' statement that start line and every line after them are
+ just commented out
+
+ Using the blacklist-regex you can filter plugin/*.vim files and
+ prevent them from being included. For example this excludes many tlib
+ plugins.: >
+
+ let s:merge = [ "tlib" ]
+ call scriptmanager#Activate(s:merge)
+ command MergePluginFiles call scriptmanager2#MergePluginFiles(s:merge+["tlib"], '\%(cmdlinehelp\|concordance\|evalselection\|glark\|hookcursormoved\|linglang\|livetimestamp\|localvariables\|loremipsum\|my_tinymode\|pim\|quickfixsigns\|scalefont\|setsyntax\|shymenu\|spec\|tassert\|tbak\|tbibtools\|tcalc\|tcomment\|techopair\|tgpg\|tmarks\|tmboxbrowser\|tortoisesvn\|tregisters\|tselectbuffer\|tselectfile\|tsession\|tskeleton\|tstatus\|viki\|vikitasks\)\.vim_merged')
+ command UnmergePluginFiles call scriptmanager2#UnmergePluginFiles()
+<
+
+ Yes, the info files should be cached as well (TODO)
+
+==============================================================================
+4. Options *vim-addon-manager-options*
+ *g:vim_script_manager*
+
+All options are located in the global dictionary g:vim_script_manager. It also
+contains some stuff that user should never modify if he wants to see this
+plugin working. Possible keys:
+
+auto_install *vim-addon-manager-auto_install*
+ This options disables plugin installation confirmation. It will not
+ disable deprecation warnings and other prompts.
+plugin_sources *vim-addon-manager-plugin_sources*
+ This option contains a dictionary where keys are plugin names and
+ values are described by |addon-info-repository|. Values defined in
+ this dictionary override corresponding values in |addon-info.txt|
+ files, so be careful when you extend it.
+plugin_root_dir *vim-addon-manager-plugin_root_dir*
+ Defines a directory where plugins will be installed to. If
+ autoload/scriptmanager.vim file that comes with this plugin is
+ writeable by user, then it defaults to the directory three levels up
+ relative to autoload/scriptmanager.vim (so, if user has installed
+ vim-addon-manager to ~/vim-addons/vim-addon-manager, this will be
+ equal to ~/vim-addons). If autoload/scriptmanager.vim is not writeable
+ by the user, then it defaults to ~/vim-addons. Note that you must set
+ this variable before calling any scriptmanager function.
+
+==============================================================================
+5. Installing plugins *vim-addon-manager-install-plugins*
+
+First read |vim-addon-manager-installation|.
+
+As documented |scriptmanager#Activate| or |:ActivateAddons| will fetch
+(=install) the plugin if it failed to find requested addon in your addons
+directory.
+
+You can use |:ActivateAddons|'s tab completion to find the plugin name fast.
+
+Usually you add the names of the addons this way to your .vimrc: >
+ set runtimepath+=~/vim-addons/vim-addon-manager
+ call scriptmanager#Activate(["pluginA","pluginB"])
+<
+You can use the Install function to install plugins only - however in practise
+you use the Activate command / function only.
+
+You can install plugins by URL. See |scriptmanager2#Install()|.
+I prefer you telling me about your repository location, though.
+Also see |vim-addon-manager-repository-locations|.
+
+Implementation details: ~
+Vim does not source plugin/*.vim and after/plugin/*.vim automatically
+if you add pathes to runtimepath after Vim has startup. vim-addon-manager
+takes care of that for you.
+
+
+==============================================================================
+6. Addon-info file *vim-addon-manager-addon-info*
+ *addon-info.txt*
+
+Each plugin that intends to use vim-addon-manager for distributing itself
+needs to have {plugname}-addon-info.txt file in its root, that contains the
+JSON dictionary with the following keys (none of the keys are required):
+
+name *addon-info-name*
+ Name of the plugin. Must not contain any characters that cannot be
+ used in a directory name (including directory names separator).
+ Note that if the value of this key, {plugname} part in addon-info.txt
+ file name and directory under which plugin is installed are not equal,
+ then user that tries to use your plugin may catch strange bugs.
+
+repository *addon-info-repository*
+ Describes where the plugin should be fetched from. Ignored unless the
+ plugin is installed using either the second or third form of
+ |scriptmanager2#Install()| call (see its description). This is
+ a dictionary with the following keys:
+
+ !! Note: As very common in extreme programming documentation may be
+ !! outdated. So may be this section. So refer to the code:
+ !! |scriptmanager2#Checkout()| to find out about all supported keys
+ !! Its easy to read and extend. Contact me if you're unsure. I'll help
+ !! you.
+ !! I'd even consider moving this section into the code only refering
+ |! to it - so that its kept in sync.
+
+ Key Description ~
+ type Required, must be either one of `hg', `git', `svn' or an
+ empty string.
+ url If `type' key contains a VCS name (`hg', `git' or `svn'),
+ then this key describes a url that will be passed to this
+ VCS. If `type' key contains an empty string, then it should
+ contain location of the archive.
+ script-type
+ One of `plugin', `syntax', or `indent'. The .vim file will be
+ moved into the specific subdirectory.
+ archive_name
+ If `type' key contains an empty string, then archive which
+ location is described by the `url' key will be saved in file
+ with name {archive_name} and processed according to its
+ extension. Supported extensions:
+ Extension How it is handled ~
+ .vim This extension designates that plugin is a single
+ file. So, if exists key `script-type' and it is
+ equal to `syntax' or `indent', then this file
+ is put under {plugname}/syntax or under
+ {plugname}/indent, otherwise it is put under
+ directory described by {plugname}/{target_dir}
+ (where {target_dir} is a value of `target_dir'
+ key if it is present and `plugin' otherwise).
+ .tar.gz, .tgz This extension designates that plugin is
+ contained inside tar archive compressed by
+ gzip. In this case, archive is unpacked to its
+ directory by `tar' (note that it must support
+ -z option), {N} components are stripped before
+ unpacking (here {N} is defined by
+ `strip-components' key if it is present,
+ default value 1. See tar man page for more
+ information).
+ .tar.bz2, .tbz2
+ Like .tar.gz, but with bzip2 compression. Note
+ that your tar must support -j option or it
+ won't work.
+ .tar This extension designates that plugin is
+ contained inside uncompressed tar archive. In
+ this case, archive is unpacked to its directory
+ by `tar', {N} components are stripped before
+ unpacking (here {N} is defined by
+ `strip-components' key if it is present,
+ default value 1. See tar man page for more
+ information).
+ .zip This extension designates that plugin is
+ contained inside a zip archive. In this case
+ archive is unpacked to its directory by
+ `unzip'.
+ .7z, .rar, .cab, .arj, .jar
+ This extension designates that plugin is
+ contained inside an archive that is supported
+ by p7zip archiver. In this case archive is
+ unpacked to its directory by `7z x'.
+ .vba This extension designates that plugin is
+ contained in a vimball archive. In this case
+ vimball#Vimball() function is used, see
+ |:UseVimball| for more details.
+ .vba.gz This extension designates that plugin is
+ contained in a vimball archive compressed by
+ gzip. In this case archive is uncompressed and
+ vimball#Vimball() function is used, see
+ |:UseVimball| for more details.
+ .vba.bz2 Like .vba.bz2, but with bzip2 compression.
+ deprecated
+ If this key is present and contains non-empty string, then
+ every time when user tries to install this plugin he will see
+ this message and will have to confirm installation.
+
+dependencies *addon-info-dependencies*
+ Describes plugins that are required for the plugin, must contain
+ a dictionary where keys are plugin names and values describe where
+ appropriate plugins should be fetched from (overriden by
+ |vim-addon-manager-plugin_sources|). The format of the values is the
+ same as |addon-info-repository|.
+
+
+version *addon-info-version*
+author *addon-info-author*
+maintainer *addon-info-maintainer*
+description *addon-info-description*
+homepage *addon-info-homepage*
+ Version, author, maintainer, description and plugin homepage. Ignored,
+ but setting them to the real values will not do any harm.
+
+==============================================================================
+7. Author, credits, some notes *vim-addon-manager-related*
+
+ *vim-addon-manager-repository-locations*
+List of known repositories is defined in a separate plugin called
+|vim-addon-manager-known-repositories|. If you want your plugin to be added to
+this list, then contact the author. Note that this list is also populated
+automatically from www.vim.org site, so sometimes you do not need to do
+anything.
+
+As alternative you can specify them in your .vimrc like what that plugin is
+doing: Add your own dicts to: >
+ g:vim_script_manager['plugin_sources']['your-plugin-name'] = { ... }
+<
+In your .vimrc or somewhere else (see |vim-addon-manager-plugin_sources|).
+
+
+Related work: ~
+There are also some other package managers for vim:
+ http://github.com/c9s/Vimana
+ http://snk.tuxfamily.org/log/vim-script-management-system.html
+You can try and see which is the best.
+
+There is another project which has the same name:
+http://packages.debian.org/sid/vim-addon-manager
+The author (Jamessan) is fine with this project sharing the same name.
+
+------------------------------------------------------------------------------
+7.1. Author contacts *vim-addon-manager-author*
+
+Github account: MarcWeber
+Email: marco-oweber@gmx.de
+
+------------------------------------------------------------------------------
+7.2. Contributors *vim-addon-manager-contributors*
+
+(Incomplete list):
+Tim Pope
+ - Json validation
+ZyX (Nikolay Pavlov, ZyX-I on github)
+ - enhancing this vim documentation
+ - various fixes
+ - discussing implementation details
+ - initial implementation for updating plugins which were installed by
+ archive
+Tux Tom (http://github.com/TuxTom)
+ - helping fixing a cd bug on Windows
+creidiki (Leonardo Valeri Manera)
+ - greatly improving Windows support
+ - working around the tar issues on Windows
+..
+Mike Smullin:
+ - for asking to find a way to source plugins in gvim.
+ There is a hint now. This is important if you don't start vim from console
+
+
+------------------------------------------------------------------------------
+ROADMAP:
+
+What features are missing?
+
+- When updating archive based plugins create diffs so that you can patch
+ those files without changes being lost. I expect users to customize mappings
+ and such
+
+- add a command like AddonManagerFetchUtils which does all the work listed in
+ 9. for you putting the tar etc into a directory and adding it to PATH
+
+- suggestions?
+
+
+==============================================================================
+8. Testing this plugin *vim-addon-manager-testing*
+
+Run >
+ # Replace ~/vim-addons/vim-addon-manager with the path you installed this
+ # plugin to
+ cd ~/vim-addons/vim-addon-manager
+ sh vim-addon-manager-test.sh
+.
+You should see >
+ 1
+ 1
+ 1
+at the end. Written for Linux only. Code coverage is bad. Its a starting
+point.
+
+==============================================================================
+9. Some notes for windows users *vim-addon-manager-windows*
+
+
+Win32 tools for vim-addon-manager
+
+Fast: put curl into ~/vim-addons/binary-utils/dist then call this function
+to setup the remaining tools (tar, bzip, gzip, unzip) >
+ call scriptmanager2#FetchAdditionalWindowsTools()
+<
+Does it make sense to support svn and git this way as well?
+Is it even possible?
+At least we can fetch and execute the installers..
+
+Section provided by creidiki:
+
+Curl:
+ Get Curl here: http://curl.haxx.se/download.html
+
+ 1. Scroll down to the end of the "Packages" list. You want (ideally) the
+ latest version, of type `binary' (not libcurl or devel). SSL is not
+ necessary but won't hurt. If your OS is 64-bit, you can get the Win64
+ version if you want, but it won't be any faster.
+ 2. Install it. Then point vim-addon-manager (and, incidentally, netrw) to
+ it by putting something like this in your _vimrc: >
+ let g:netrw_http_cmd='{path_to_curl}\curl.exe -o'
+< (replace {path-to-curl} with the installation directory, including the
+ brackets).
+
+ Don't forget the -o argument at the end. :)
+
+Archives:
+ Get Tar, Gzip and Unzip from the GnuWin32 project
+ Gzip: http://gnuwin32.sourceforge.net/packages/gzip.htm
+ Tar: http://gnuwin32.sourceforge.net/packages/gtar.htm
+ Unzip: http://gnuwin32.sourceforge.net/packages/unzip.htm
+
+ Either get the complete package setups, or the binary installers. All you
+ need is the binaries.
+ Install or unpack them somewhere.
+
+ Get xzdec here: http://nullprogram.com/blog/2010/04/16/
+ or here: http://www.stats.ox.ac.uk/pub/Rtools/goodies/xzutils.zip
+ You only need xzdec.exe. Put in the same place you put those other archive
+ tools.
+
+ Get p7zip here: http://7-zip.org/download.html. You need the full version
+ with gui because package with command-line version contains only 7za
+ executable, while you need 7z in order to support more archives.
+
+ Either add them to your system or user path (google it!) or add them just
+ to vim's path by putting something like this in _vimrc: >
+ let $PATH='{path-to-gnu-utils};'.$PATH
+< Again, replace the whole of {path-to-gnu-utils} including brackets with
+ the directory you have installed/unpacked them to.
+
+VCS:
+ MSysGit (and TortoiseGit/GitExtensions) by default add the `git'
+ executable to your PATH. If you chose not to for whatever reason, you can
+ use the trick above to let vim see them. TortoiseHG does the same with the
+ mercurial `hg' executable. TortoiseSVN does not include the commandline
+ `svn' executable, so if you need it install SilkSVN
+
+ SilkSVN: http://www.sliksvn.com/en/download/
+ MsysGit: http://code.google.com/p/msysgit/
+ Mercurial: http://mercurial.selenic.com/
+
+==============================================================================
+10. Some notes for Gentoo users *vim-addon-manager-gentoo*
+
+Gentoo users may consider installing this plugin from pluginloader overlay
+which is accessible via mercurial, url:
+http://vimpluginloader.hg.sourceforge.net:8000/hgroot/vimpluginloader/pluginloader-overlay
+
+In order to use this overlay paludis users can add the pluginloader.conf file
+to /etc/paludis/repositories/ with the following contents: >
+ location = /var/paludis/repositories/pluginloader
+ format = e
+ sync = hg+http://vimpluginloader.hg.sourceforge.net:8000/hgroot/vimpluginloader/pluginloader-overlay
+
+ master_repository = gentoo
+ names_cache = ${location}/.cache/names
+ write_cache = /var/cache/paludis/metadata
+
+Then you should unmask app-vim/vim-addon-manager and run >
+ paludis --sync && paludis --install vim-addon-manager
+or >
+ cave sync && cave resolve -x vim-addon-manager
+and everything will probably be fine.
+
+For portage+layman users:
+1. Create a file /var/lib/layman/pluginloader-overlay.xml with the following
+ contents: >
+ <?xml version="1.0" encoding="UTF-8"?>
+ <!DOCTYPE repositories SYSTEM "/dtd/repositories.dtd">
+ <repositories xmlns="" version="1.0">
+ <repo quality="experimental" status="unofficial">
+ <name>pluginloader-overlay</name>
+ <description>Overlay that contains some additional vim plugins</description>
+ <source type="mercurial">http://vimpluginloader.hg.sourceforge.net:8000/hgroot/vimpluginloader/pluginloader-overlay</source>
+ </repo>
+ </repositories>
+2. Add the following line to /etc/layman/layman.cfg just after the line that
+ starts with `overlays' (do not forget to indent it, see comment above the
+ target line): >
+ file:///var/lib/layman/pluginloader-overlay.xml
+3. Run >
+ layman -ka pluginloader-overlay
+4. Unmask vim-addon-manager and run >
+ emerge vim-addon-manager
+
+==============================================================================
+11. Trouble shooting & KNOWS BUGS *vim-addon-manage-trouble-shooting*
+
+Don't have those commands? See |vim-addon-manager-installation|.
+Windows installation is more tedious than on Linux - yes.
+
+Still trouble? Get in touch, see |vim-addon-manager-author|
+
+You have to trust script authors:
+Because everybody can upload everything to the repositories (in particular
+www.vim.org) you must trust authors. I can't review all code - so expect code
+to steal your passwords, run sudo rm -fr / ... etc. (This never happened to
+me. But it could)
+Briefly: I'm not responsible for the code you get using vim-addon-manager.
+
+If something goes wrong - and if I don't reply within 24h:
+The following github users are collaborators. This means they have write
+access to the official repository:
+tpope, dertuxmalwieder, TuxTom.
+
+If a plugin behaves strangely then try
+http://github.com/dahu/VimLint/blob/master/plugin/vimlint.vim.
+Maybe you have an uncommon Vim setting causing some plugins to fail.
+
+
+vim:tw=78:fo=tcq2:isk=!-~,^*,^\|,^\":ts=8:ft=help:norl:
diff --git a/plugin/fuf.vim b/plugin/fuf.vim
new file mode 100644
index 0000000..7329144
--- /dev/null
+++ b/plugin/fuf.vim
@@ -0,0 +1,154 @@
+"=============================================================================
+" Copyright (c) 2007-2010 Takeshi NISHIDA
+"
+" GetLatestVimScripts: 1984 1 :AutoInstall: FuzzyFinder
+"=============================================================================
+" LOAD GUARD {{{1
+
+try
+ if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100)
+ 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_mrufile_searchAroundLevel', -1) " private option
+ "---------------------------------------------------------------------------
+ call l9#defineVariableDefault('g:fuf_mrucmd_prompt' , '>MRU-Cmd[]>')
+ call l9#defineVariableDefault('g:fuf_mrucmd_switchOrder', 70)
+ call l9#defineVariableDefault('g:fuf_mrucmd_exclude' , '^$')
+ call l9#defineVariableDefault('g:fuf_mrucmd_maxItem' , 200)
+ "---------------------------------------------------------------------------
+ call l9#defineVariableDefault('g:fuf_bookmarkfile_prompt' , '>BookmarkFile[]>')
+ call l9#defineVariableDefault('g:fuf_bookmarkfile_switchOrder', 80)
+ call l9#defineVariableDefault('g:fuf_bookmarkfile_searchRange', 400)
+ call l9#defineVariableDefault('g:fuf_bookmarkfile_keyDelete' , '<C-]>')
+ "---------------------------------------------------------------------------
+ call l9#defineVariableDefault('g:fuf_bookmarkdir_prompt' , '>BookmarkDir[]>')
+ call l9#defineVariableDefault('g:fuf_bookmarkdir_switchOrder', 90)
+ call l9#defineVariableDefault('g:fuf_bookmarkdir_keyDelete' , '<C-]>')
+ "---------------------------------------------------------------------------
+ call l9#defineVariableDefault('g:fuf_tag_prompt' , '>Tag[]>')
+ call l9#defineVariableDefault('g:fuf_tag_switchOrder', 100)
+ "---------------------------------------------------------------------------
+ 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('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:
diff --git a/plugin/l9.vim b/plugin/l9.vim
new file mode 100644
index 0000000..b59f862
--- /dev/null
+++ b/plugin/l9.vim
@@ -0,0 +1,108 @@
+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+" TODO: GetLatestVimScripts
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion())
+ 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: