comparison .vim/plugin/fuzzyfinder.vim @ 0:c30d68fbd368

Initial import from svn.
author Augie Fackler <durin42@gmail.com>
date Wed, 26 Nov 2008 10:56:09 -0600
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:c30d68fbd368
1 "=============================================================================
2 " fuzzyfinder.vim : Fuzzy/Partial pattern explorer for
3 " buffer/file/MRU/command/favorite/tag/etc.
4 "=============================================================================
5 "
6 " Author: Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
7 " Version: 2.13, for Vim 7.1
8 " Licence: MIT Licence
9 " URL: http://www.vim.org/scripts/script.php?script_id=1984
10 "
11 " GetLatestVimScripts: 1984 1 :AutoInstall: fuzzyfinder.vim
12 "
13 "=============================================================================
14 " DOCUMENT: {{{1
15 " Japanese: http://vim.g.hatena.ne.jp/keyword/fuzzyfinder.vim
16 "
17 "-----------------------------------------------------------------------------
18 " Description:
19 " Fuzzyfinder provides convenient ways to quickly reach the buffer/file you
20 " want. Fuzzyfinder finds matching files/buffers with a fuzzy/partial
21 " pattern to which it converted the entered pattern.
22 "
23 " E.g.: entered pattern -> fuzzy pattern / partial pattern
24 " abc -> *a*b*c* / *abc*
25 " a?c -> *a?c* / *a?c*
26 " dir/file -> dir/*f*i*l*e* / dir/*file*
27 " d*r/file -> d*r/*f*i*l*e* / d*r/*file*
28 " ../**/s -> ../**/*s* / ../**/*s*
29 "
30 " (** allows searching a directory tree.)
31 "
32 " You will be happy when:
33 " "./OhLongLongLongLongLongFile.txt"
34 " "./AhLongLongLongLongLongName.txt"
35 " "./AhLongLongLongLongLongFile.txt" <- you want :O
36 " Type "AF" and "AhLongLongLongLongLongFile.txt" will be select. :D
37 "
38 " Fuzzyfinder has some modes:
39 " - Buffer mode
40 " - File mode
41 " - Directory mode (yet another :cd command)
42 " - MRU-file mode (most recently used files)
43 " - MRU-command mode (most recently used command-lines)
44 " - Favorite-file mode
45 " - Tag mode (yet another :tag command)
46 " - Tagged-file mode (files which are included in current tags)
47 "
48 " Fuzzyfinder supports the multibyte.
49 "
50 "-----------------------------------------------------------------------------
51 " Installation:
52 " Drop this file in your plugin directory.
53 "
54 "-----------------------------------------------------------------------------
55 " Usage:
56 " Starting Fuzzyfinder:
57 " You can start Fuzzyfinder by the following commands:
58 "
59 " :FuzzyFinderBuffer - launchs buffer-mode Fuzzyfinder.
60 " :FuzzyFinderFile - launchs file-mode Fuzzyfinder.
61 " :FuzzyFinderDir - launchs directory-mode Fuzzyfinder.
62 " :FuzzyFinderMruFile - launchs MRU-file-mode Fuzzyfinder.
63 " :FuzzyFinderMruCmd - launchs MRU-command-mode Fuzzyfinder.
64 " :FuzzyFinderFavFile - launchs favorite-file-mode Fuzzyfinder.
65 " :FuzzyFinderTag - launchs tag-mode Fuzzyfinder.
66 " :FuzzyFinderTaggedFile - launchs tagged-file-mode Fuzzyfinder.
67 "
68 " It is recommended to map these commands. These commands can take initial
69 " text as a command argument. The text will be entered after Fuzzyfinder
70 " launched. If a command was executed with a ! modifier (e.g.
71 " :FuzzyFinderTag!), it enables the partial matching instead of the fuzzy
72 " matching.
73 "
74 "
75 " In Fuzzyfinder:
76 " The entered pattern is converted to the fuzzy pattern and buffers/files
77 " which match the pattern is shown in a completion menu.
78 "
79 " A completion menu is shown when you type at the end of the line and the
80 " length of entered pattern is more than setting value. By default, it is
81 " shown at the beginning.
82 "
83 " If too many items (200, by default) were matched, the completion is
84 " aborted to reduce nonresponse.
85 "
86 " If an item were matched with entered pattern exactly, it is shown first.
87 " The item whose file name has longer prefix matching is placed upper.
88 " Also, an item which matched more sequentially is placed upper. The item
89 " whose index were matched with a number suffixed with entered pattern is
90 " placed lower. the first item in the completion menu will be selected
91 " automatically.
92 "
93 " You can open a selected item in various ways:
94 " <CR> - opens in a previous window.
95 " <C-j> - opens in a split window.
96 " <C-k> - opens in a vertical-split window.
97 " <C-]> - opens in a new tab page.
98 " In MRU-command mode, <CR> executes a selected command and others just
99 " put it into a command-line. These key mappings are customizable.
100 "
101 " To cancel and return to previous window, leave Insert mode.
102 "
103 " To Switch the mode without leaving Insert mode, use <C-l> or <C-o>.
104 " This key mapping is customizable.
105 "
106 " If you want to temporarily change whether or not to ignore case, use
107 " <C-t>. This key mapping is customizable.
108 "
109 " To Hide The Completion Temporarily Menu In Fuzzyfinder:
110 " You can close it by <C-e> and reopen it by <C-x><C-u>.
111 "
112 " About Highlighting:
113 " Fuzzyfinder highlights the buffer with "Error" group when the completion
114 " item was not found or the completion process was aborted.
115 "
116 " About Alternative Approach For Tag Jump:
117 " Following mappings are replacements for :tag and <C-]>:
118 "
119 " nnoremap <silent> <C-f><C-t> :FuzzyFinderTag!<CR>
120 " nnoremap <silent> <C-]> :FuzzyFinderTag! <C-r>=expand('<cword>')<CR><CR>
121 "
122 " In the tag mode, it is recommended to use partial matching instead of
123 " fuzzy matching.
124 "
125 " About Tagged File Mode:
126 " The files which are included in the current tags are the ones which are
127 " related to the current working environment. So this mode is a pseudo
128 " project mode.
129 "
130 " About Usage Of Command Argument:
131 " As an example, if you want to launch file-mode Fuzzyfinder with the full
132 " path of current directory, map like below:
133 "
134 " nnoremap <C-p> :FuzzyFinderFile <C-r>=fnamemodify(getcwd(), ':p')<CR><CR>
135 "
136 " Instead, if you want the directory of current buffer and not current
137 " directory:
138 "
139 " nnoremap <C-p> :FuzzyFinderFile <C-r>=expand('%:~:.')[:-1-len(expand('%:~:.:t'))]<CR><CR>
140 "
141 " About Abbreviations And Multiple Search:
142 " You can use abbreviations and multiple search in each mode. For example,
143 " set as below:
144 "
145 " let g:FuzzyFinderOptions.Base.abbrev_map = {
146 " \ "^WORK" : [
147 " \ "~/project/**/src/",
148 " \ ".vim/plugin/",
149 " \ ],
150 " \ }
151 "
152 " And type "WORKtxt" in file-mode Fuzzyfinder, then it searches by
153 " following patterns:
154 "
155 " "~/project/**/src/*t*x*t*"
156 " ".vim/plugin/*t*x*t*"
157 "
158 " Adding Favorite Files:
159 " You can add a favorite file by the following commands:
160 "
161 " :FuzzyFinderAddFavFile {filename}
162 "
163 " If you do not specify the filename, current file name is used.
164 "
165 " About Information File:
166 " Fuzzyfinder writes information of the MRU, favorite, etc to the file by
167 " default (~/.vimfuzzyfinder).
168
169 " :FuzzyFinderEditInfo command is helpful in editing your information
170 " file. This command reads the information file in new unnamed buffer.
171 " Write the buffer and the information file will be updated.
172 "
173 " About Cache:
174 " Once a cache was created, It is not updated automatically to improve
175 " response by default. To update it, use :FuzzyFinderRemoveCache command.
176 "
177 " About Migemo:
178 " Migemo is a search method for Japanese language.
179 "
180 "-----------------------------------------------------------------------------
181 " Options:
182 " You can set options via g:FuzzyFinderOptions which is a dictionary. See
183 " the folded section named "GLOBAL OPTIONS:" for details. To easily set
184 " options for customization, put necessary entries from GLOBAL OPTIONS into
185 " your vimrc file and edit those values.
186 "
187 "-----------------------------------------------------------------------------
188 " Setting Example:
189 " let g:FuzzyFinderOptions = { 'Base':{}, 'Buffer':{}, 'File':{}, 'Dir':{}, 'MruFile':{}, 'MruCmd':{}, 'FavFile':{}, 'Tag':{}, 'TaggedFile':{}}
190 " let g:FuzzyFinderOptions.Base.ignore_case = 1
191 " let g:FuzzyFinderOptions.Base.abbrev_map = {
192 " \ '\C^VR' : [
193 " \ '$VIMRUNTIME/**',
194 " \ '~/.vim/**',
195 " \ '$VIM/.vim/**',
196 " \ '$VIM/vimfiles/**',
197 " \ ],
198 " \ }
199 " let g:FuzzyFinderOptions.MruFile.max_item = 200
200 " let g:FuzzyFinderOptions.MruCmd.max_item = 200
201 " nnoremap <silent> <C-n> :FuzzyFinderBuffer<CR>
202 " nnoremap <silent> <C-m> :FuzzyFinderFile <C-r>=expand('%:~:.')[:-1-len(expand('%:~:.:t'))]<CR><CR>
203 " nnoremap <silent> <C-j> :FuzzyFinderMruFile<CR>
204 " nnoremap <silent> <C-k> :FuzzyFinderMruCmd<CR>
205 " nnoremap <silent> <C-p> :FuzzyFinderDir <C-r>=expand('%:p:~')[:-1-len(expand('%:p:~:t'))]<CR><CR>
206 " nnoremap <silent> <C-f><C-d> :FuzzyFinderDir<CR>
207 " nnoremap <silent> <C-f><C-f> :FuzzyFinderFavFile<CR>
208 " nnoremap <silent> <C-f><C-t> :FuzzyFinderTag!<CR>
209 " nnoremap <silent> <C-f><C-g> :FuzzyFinderTaggedFile<CR>
210 " noremap <silent> g] :FuzzyFinderTag! <C-r>=expand('<cword>')<CR><CR>
211 " nnoremap <silent> <C-f>F :FuzzyFinderAddFavFile<CR>
212 " nnoremap <silent> <C-f><C-e> :FuzzyFinderEditInfo<CR>
213 "
214 "-----------------------------------------------------------------------------
215 " Special Thanks:
216 " Vincent Wang
217 " Ingo Karkat
218 " Nikolay Golubev
219 " Brian Doyle
220 " id:secondlife
221 " Matt Tolton
222 "
223 "-----------------------------------------------------------------------------
224 " ChangeLog:
225 " 2.13:
226 " - Fixed a bug that a directory disappeared when a file in that directroy
227 " was being opened in File/Mru-File mode.
228 "
229 " 2.12:
230 " - Changed to be able to show completion items in the order of recently
231 " used in Buffer mode.
232 " - Added g:FuzzyFinderOptions.Buffer.mru_order option.
233 "
234 " 2.11:
235 " - Changed that a dot sequence of entered pattern is expanded to parent
236 " directroies in File/Dir mode.
237 " E.g.: "foo/...bar" -> "foo/../../bar"
238 " - Fixed a bug that a prompt string was excessively inserted.
239 "
240 " 2.10:
241 " - Changed not to show a current buffer in a completion menu.
242 " - Fixed a bug that a filename to open was not been escaped.
243 " - Added 'prompt' option.
244 " - Added 'prompt_highlight' option.
245 " - Removed g:FuzzyFinderOptions.MruFile.no_special_buffer option.
246 "
247 " 2.9:
248 " - Enhanced <BS> behavior in Fuzzyfinder and added 'smart_bs' option.
249 " - Fixed a bug that entered pattern was not been escaped.
250 " - Fixed not to insert "zv" with "c/pattern<CR>" command in Normal mode.
251 " - Avoid the slow down problem caused by filereadable() check for the MRU
252 " information in BufEnter/BufWritePost.
253 "
254 " 2.8.1:
255 " - Fixed a bug caused by the non-escaped buffer name "[Fuzzyfinder]".
256 " - Fixed a command to open in a new tab page in Buffer mode.
257 " 2.8:
258 " - Added 'trim_length' option.
259 " - Added 'switch_order' option.
260 " - Fixed a bug that entered command did not become the newest in the
261 " history.
262 " - Fixed a bug that folds could not open with <CR> in a command-line when
263 " searching.
264 " - Removed 'excluded_indicator' option. Now a completion list in Buffer
265 " mode is the same as a result of :buffers.
266 "
267 " 2.7:
268 " - Changed to find an item whose index is matched with the number
269 " suffixed with entered pattern.
270 " - Fixed the cache bug after changing current directroy in File mode.
271 "
272 " 2.6.2:
273 " - Fixed not to miss changes in options when updates the MRU information.
274 "
275 " 2.6.1:
276 " - Fixed a bug related to floating-point support.
277 " - Added support for GetLatestVimScripts.
278 "
279 " 2.6:
280 " - Revived MRU-command mode. The problem with a command-line abbreviation
281 " was solved.
282 " - Changed the specification of the information file.
283 " - Added :FuzzyFinderEditInfo command.
284
285 " 2.5.1:
286 " - Fixed to be able to match "foo/./bar" by "foo/**/bar" in File mode.
287 " - Fixed to be able to open a space-containing file in File mode.
288 " - Fixed to honor the current working directory properly in File mode.
289 "
290 " 2.5:
291 " - Fixed the bug that a wrong initial text is entered after switching to a
292 " next mode.
293 " - Fixed the bug that it does not return to previous window after leaving
294 " Fuzzyfinder one.
295 "
296 " 2.4:
297 " - Fixed the bug that Fuzzyfinder fails to open a file caused by auto-cd
298 " plugin/script.
299 "
300 " 2.3:
301 " - Added a key mapping to open items in a new tab page and
302 " g:FuzzyFinderOptions.Base.key_open_tab opton.
303 " - Changed to show Fuzzyfinder window above last window even if
304 " 'splitbelow' was set.
305 " - Changed to set nocursorline and nocursorcolumn in Fuzzyfinder.
306 " - Fixed not to push up a buffer number unlimitedly.
307 "
308 " 2.2:
309 " - Added new feature, which is the partial matching.
310 " - Fixed the bug that an error occurs when "'" was entered.
311 "
312 " 2.1:
313 " - Restructured the option system AGAIN. Sorry :p
314 " - Changed to inherit a typed text when switching a mode without leaving
315 " Insert mode.
316 " - Changed commands which launch explorers to be able to take a argument
317 " for initial text.
318 " - Changed to complete file names by relative path and not full path in
319 " the buffer/mru-file/tagged-file mode.
320 " - Changed to highlight a typed text when the completion item was not
321 " found or the completion process was aborted.
322 " - Changed to create caches for each tag file and not working directory
323 " in the tag/tagged-file mode.
324 " - Fixed the bug that the buffer mode couldn't open a unnamed buffer.
325 " - Added 'matching_limit' option.
326 " - Removed 'max_match' option. Use 'matching_limit' option instead.
327 " - Removed 'initial_text' option. Use command argument instead.
328 " - Removed the MRU-command mode.
329 "
330 " 2.0:
331 " - Added the tag mode.
332 " - Added the tagged-file mode.
333 " - Added :FuzzyFinderRemoveCache command.
334 " - Restructured the option system. many options are changed names or
335 " default values of some options.
336 " - Changed to hold and reuse caches of completion lists by default.
337 " - Changed to set filetype 'fuzzyfinder'.
338 " - Disabled the MRU-command mode by default because there are problems.
339 " - Removed FuzzyFinderAddMode command.
340 "
341 " 1.5:
342 " - Added the directory mode.
343 " - Fixed the bug that it caused an error when switch a mode in Insert
344 " mode.
345 " - Changed g:FuzzyFinder_KeySwitchMode type to a list.
346 "
347 " 1.4:
348 " - Changed the specification of the information file.
349 " - Added the MRU-commands mode.
350 " - Renamed :FuzzyFinderAddFavorite command to :FuzzyFinderAddFavFile.
351 " - Renamed g:FuzzyFinder_MruModeVars option to
352 " g:FuzzyFinder_MruFileModeVars.
353 " - Renamed g:FuzzyFinder_FavoriteModeVars option to
354 " g:FuzzyFinder_FavFileModeVars.
355 " - Changed to show registered time of each item in MRU/favorite mode.
356 " - Added 'timeFormat' option for MRU/favorite modes.
357 "
358 " 1.3:
359 " - Fixed a handling of multi-byte characters.
360 "
361 " 1.2:
362 " - Added support for Migemo. (Migemo is Japanese search method.)
363 "
364 " 1.1:
365 " - Added the favorite mode.
366 " - Added new features, which are abbreviations and multiple search.
367 " - Added 'abbrevMap' option for each mode.
368 " - Added g:FuzzyFinder_MruModeVars['ignoreSpecialBuffers'] option.
369 " - Fixed the bug that it did not work correctly when a user have mapped
370 " <C-p> or <Down>.
371 "
372 " 1.0:
373 " - Added the MRU mode.
374 " - Added commands to add and use original mode.
375 " - Improved the sorting algorithm for completion items.
376 " - Added 'initialInput' option to automatically insert a text at the
377 " beginning of a mode.
378 " - Changed that 'excludedPath' option works for the entire path.
379 " - Renamed some options.
380 " - Changed default values of some options.
381 " - Packed the mode-specific options to dictionaries.
382 " - Removed some options.
383 "
384 " 0.6:
385 " - Fixed some bugs.
386
387 " 0.5:
388 " - Improved response by aborting processing too many items.
389 " - Changed to be able to open a buffer/file not only in previous window
390 " but also in new window.
391 " - Fixed a bug that recursive searching with '**' does not work.
392 " - Added g:FuzzyFinder_CompletionItemLimit option.
393 " - Added g:FuzzyFinder_KeyOpen option.
394 "
395 " 0.4:
396 " - Improved response of the input.
397 " - Improved the sorting algorithm for completion items. It is based on
398 " the matching level. 1st is perfect matching, 2nd is prefix matching,
399 " and 3rd is fuzzy matching.
400 " - Added g:FuzzyFinder_ExcludePattern option.
401 " - Removed g:FuzzyFinder_WildIgnore option.
402 " - Removed g:FuzzyFinder_EchoPattern option.
403 " - Removed g:FuzzyFinder_PathSeparator option.
404 " - Changed the default value of g:FuzzyFinder_MinLengthFile from 1 to 0.
405 "
406 " 0.3:
407 " - Added g:FuzzyFinder_IgnoreCase option.
408 " - Added g:FuzzyFinder_KeyToggleIgnoreCase option.
409 " - Added g:FuzzyFinder_EchoPattern option.
410 " - Changed the open command in a buffer mode from ":edit" to ":buffer" to
411 " avoid being reset cursor position.
412 " - Changed the default value of g:FuzzyFinder_KeyToggleMode from
413 " <C-Space> to <F12> because <C-Space> does not work on some CUI
414 " environments.
415 " - Changed to avoid being loaded by Vim before 7.0.
416 " - Fixed a bug with making a fuzzy pattern which has '\'.
417 "
418 " 0.2:
419 " - A bug it does not work on Linux is fixed.
420 "
421 " 0.1:
422 " - First release.
423 "
424 " }}}1
425 "=============================================================================
426 " INCLUDE GUARD: {{{1
427 if exists('loaded_fuzzyfinder') || v:version < 701
428 finish
429 endif
430 let loaded_fuzzyfinder = 1
431
432 " }}}1
433 "=============================================================================
434 " FUNCTION: {{{1
435 "-----------------------------------------------------------------------------
436 " LIST FUNCTIONS:
437
438 function! s:Unique(in)
439 let sorted = sort(a:in)
440 if len(sorted) < 2
441 return sorted
442 endif
443 let last = remove(sorted, 0)
444 let result = [last]
445 for item in sorted
446 if item != last
447 call add(result, item)
448 let last = item
449 endif
450 endfor
451 return result
452 endfunction
453
454 " [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ]
455 function! s:Concat(in)
456 let result = []
457 for l in a:in
458 let result += l
459 endfor
460 return result
461 endfunction
462
463 " [ [ 0, 1 ], [ 2, 3, 4 ], ] -> [ [0,2], [0,3], [0,4], [1,2], [1,3], [1,4] ]
464 function! s:CartesianProduct(lists)
465 if empty(a:lists)
466 return []
467 endif
468 "let result = map((a:lists[0]), '[v:val]')
469 let result = [ [] ]
470 for l in a:lists
471 let temp = []
472 for r in result
473 let temp += map(copy(l), 'add(copy(r), v:val)')
474 endfor
475 let result = temp
476 endfor
477 return result
478 endfunction
479
480 " copy + filter + limit
481 function! s:FilterEx(in, expr, limit)
482 if a:limit <= 0
483 return filter(copy(a:in), a:expr)
484 endif
485 let result = []
486 let stride = a:limit * 3 / 2 " x1.5
487 for i in range(0, len(a:in) - 1, stride)
488 let result += filter(a:in[i : i + stride - 1], a:expr)
489 if len(result) >= a:limit
490 return remove(result, 0, a:limit - 1)
491 endif
492 endfor
493 return result
494 endfunction
495
496 "
497 function! s:FilterMatching(entries, key, pattern, index, limit)
498 return s:FilterEx(a:entries, 'v:val[''' . a:key . '''] =~ ' . string(a:pattern) . ' || v:val.index == ' . a:index, a:limit)
499 endfunction
500
501 function! s:ExtendIndexToEach(in, offset)
502 for i in range(len(a:in))
503 let a:in[i].index = i + a:offset
504 endfor
505 return a:in
506 endfunction
507
508 function! s:UpdateMruList(mrulist, new_item, key, max_item, excluded)
509 let result = copy(a:mrulist)
510 let result = filter(result,'v:val[a:key] != a:new_item[a:key]')
511 let result = insert(result, a:new_item)
512 let result = filter(result, 'v:val[a:key] !~ a:excluded')
513 return result[0 : a:max_item - 1]
514 endfunction
515
516 "-----------------------------------------------------------------------------
517 " STRING FUNCTIONS:
518
519 " trims a:str and add a:mark if a length of a:str is more than a:len
520 function! s:TrimLast(str, len)
521 if a:len <= 0 || len(a:str) <= a:len
522 return a:str
523 endif
524 return a:str[:(a:len - len(s:ABBR_TRIM_MARK) - 1)] . s:ABBR_TRIM_MARK
525 endfunction
526
527 " takes suffix numer. if no digits, returns -1
528 function! s:SuffixNumber(str)
529 let s = matchstr(a:str, '\d\+$')
530 return (len(s) ? str2nr(s) : -1)
531 endfunction
532
533 function! s:ConvertWildcardToRegexp(expr)
534 let re = escape(a:expr, '\')
535 for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ]
536 let re = substitute(re, pat, sub, 'g')
537 endfor
538 return '\V' . re
539 endfunction
540
541 " "foo/bar/hoge" -> { head: "foo/bar/", tail: "hoge" }
542 function! s:SplitPath(path)
543 let dir = matchstr(a:path, '^.*[/\\]')
544 return {
545 \ 'head' : dir,
546 \ 'tail' : a:path[strlen(dir):]
547 \ }
548 endfunction
549
550 function! s:EscapeFilename(fn)
551 return escape(a:fn, " \t\n*?[{`$%#'\"|!<")
552 endfunction
553
554 " "foo/.../bar/...hoge" -> "foo/.../bar/../../hoge"
555 function! s:ExpandTailDotSequenceToParentDir(base)
556 return substitute(a:base, '^\(.*[/\\]\)\?\zs\.\(\.\+\)\ze[^/\\]*$',
557 \ '\=repeat(".." . s:PATH_SEPARATOR, len(submatch(2)))', '')
558 endfunction
559
560 "-----------------------------------------------------------------------------
561 " FUNCTIONS FOR COMPLETION ITEM:
562
563 function! s:FormatCompletionItem(expr, number, abbr, trim_len, time, base_pattern, evals_path_tail)
564 if a:evals_path_tail
565 let rate = s:EvaluateMatchingRate(s:SplitPath(matchstr(a:expr, '^.*[^/\\]')).tail,
566 \ s:SplitPath(a:base_pattern).tail)
567 else
568 let rate = s:EvaluateMatchingRate(a:expr, a:base_pattern)
569 endif
570 return {
571 \ 'word' : a:expr,
572 \ 'abbr' : s:TrimLast((a:number >= 0 ? printf('%2d: ', a:number) : '') . a:abbr, a:trim_len),
573 \ 'menu' : printf('%s[%s]', (len(a:time) ? a:time . ' ' : ''), s:MakeRateStar(rate, 5)),
574 \ 'ranks' : [-rate, (a:number >= 0 ? a:number : a:expr)]
575 \ }
576 endfunction
577
578 function! s:EvaluateMatchingRate(expr, pattern)
579 if a:expr == a:pattern
580 return s:MATCHING_RATE_BASE
581 endif
582 let rate = 0
583 let rate_increment = (s:MATCHING_RATE_BASE * 9) / (len(a:pattern) * 10) " zero divide ok
584 let matched = 1
585 let i_pattern = 0
586 for i_expr in range(len(a:expr))
587 if a:expr[i_expr] == a:pattern[i_pattern]
588 let rate += rate_increment
589 let matched = 1
590 let i_pattern += 1
591 if i_pattern >= len(a:pattern)
592 break
593 endif
594 elseif matched
595 let rate_increment = rate_increment / 2
596 let matched = 0
597 endif
598 endfor
599 return rate
600 endfunction
601
602 function! s:MakeRateStar(rate, base)
603 let len = (a:base * a:rate) / s:MATCHING_RATE_BASE
604 return repeat('*', len) . repeat('.', a:base - len)
605 endfunction
606
607 "-----------------------------------------------------------------------------
608 " MISC FUNCTIONS:
609
610 function! s:IsAvailableMode(mode)
611 return exists('a:mode.mode_available') && a:mode.mode_available
612 endfunction
613
614 function! s:GetAvailableModes()
615 return filter(values(g:FuzzyFinderMode), 's:IsAvailableMode(v:val)')
616 endfunction
617
618 function! s:GetSortedAvailableModes()
619 let modes = filter(items(g:FuzzyFinderMode), 's:IsAvailableMode(v:val[1])')
620 let modes = map(modes, 'extend(v:val[1], { "ranks" : [v:val[1].switch_order, v:val[0]] })')
621 return sort(modes, 's:CompareRanks')
622 endfunction
623
624 function! s:GetSidPrefix()
625 return matchstr(expand('<sfile>'), '<SNR>\d\+_')
626 endfunction
627
628 function! s:OnCmdCR()
629 for m in s:GetAvailableModes()
630 call m.extend_options()
631 call m.on_command_pre(getcmdtype() . getcmdline())
632 endfor
633 " lets last entry become the newest in the history
634 if getcmdtype() =~ '[:/=@]'
635 call histadd(getcmdtype(), getcmdline())
636 endif
637
638 " this is not mapped again (:help recursive_mapping)
639 return "\<CR>"
640 endfunction
641
642 function! s:ExpandAbbrevMap(base, abbrev_map)
643 let result = [a:base]
644
645 " expand
646 for [pattern, sub_list] in items(a:abbrev_map)
647 let exprs = result
648 let result = []
649 for expr in exprs
650 let result += map(copy(sub_list), 'substitute(expr, pattern, v:val, "g")')
651 endfor
652 endfor
653
654 return s:Unique(result)
655 endfunction
656
657 " "**" is expanded to ["**", "."]. E.g.: "foo/**/bar" -> [ "foo/./bar", "foo/**/bar" ]
658 function! s:ExpandEx(dir)
659 if a:dir !~ '\S'
660 return ['']
661 endif
662
663 " [ ["foo/"], ["**/", "./" ], ["bar/"] ]
664 let lists = []
665 for i in split(a:dir, '[/\\]\zs')
666 let m = matchlist(i, '^\*\{2,}\([/\\]*\)$')
667 call add(lists, (empty(m) ? [i] : [i, '.' . m[1]]))
668 endfor
669
670 " expand wlidcards
671 return split(join(map(s:CartesianProduct(lists), 'expand(join(v:val, ""))'), "\n"), "\n")
672 endfunction
673
674 function! s:EnumExpandedDirsEntries(dir, excluded)
675 let dirs = s:ExpandEx(a:dir)
676 let entries = s:Concat(map(copy(dirs), 'split(glob(v:val . ".*"), "\n") + ' .
677 \ 'split(glob(v:val . "*" ), "\n")'))
678 if len(dirs) <= 1
679 call map(entries, 'extend(s:SplitPath(v:val), { "suffix" : (isdirectory(v:val) ? s:PATH_SEPARATOR : ""), "head" : a:dir })')
680 else
681 call map(entries, 'extend(s:SplitPath(v:val), { "suffix" : (isdirectory(v:val) ? s:PATH_SEPARATOR : "") })')
682 endif
683 if len(a:excluded)
684 call filter(entries, '(v:val.head . v:val.tail . v:val.suffix) !~ a:excluded')
685 endif
686 return entries
687 endfunction
688
689 function! s:GetTagList(tagfile)
690 return map(readfile(a:tagfile), 'matchstr(v:val, ''^[^!\t][^\t]*'')')
691 endfunction
692
693 function! s:GetTaggedFileList(tagfile)
694 execute 'cd ' . fnamemodify(a:tagfile, ':h')
695 let result = map(readfile(a:tagfile), 'fnamemodify(matchstr(v:val, ''^[^!\t][^\t]*\t\zs[^\t]\+''), '':p:~'')')
696 cd -
697 return result
698 endfunction
699
700 function! s:HighlightPrompt(prompt, highlight)
701 syntax clear
702 execute printf('syntax match %s /^\V%s/', a:highlight, escape(a:prompt, '\'))
703 endfunction
704
705 function! s:HighlightError()
706 syntax clear
707 syntax match Error /^.*$/
708 endfunction
709
710 function! s:CompareTimeDescending(i1, i2)
711 return a:i1.time == a:i2.time ? 0 : a:i1.time > a:i2.time ? -1 : +1
712 endfunction
713
714 function! s:CompareRanks(i1, i2)
715 if exists('a:i1.ranks') && exists('a:i2.ranks')
716 for i in range(min([len(a:i1.ranks), len(a:i2.ranks)]))
717 if a:i1.ranks[i] > a:i2.ranks[i]
718 return +1
719 elseif a:i1.ranks[i] < a:i2.ranks[i]
720 return -1
721 endif
722 endfor
723 endif
724 return 0
725 endfunction
726
727 function! s:GetCurrentTagFiles()
728 return sort(filter(map(tagfiles(), 'fnamemodify(v:val, '':p'')'), 'filereadable(v:val)'))
729 endfunction
730
731 " }}}1
732 "=============================================================================
733 " OBJECT: {{{1
734 "-----------------------------------------------------------------------------
735 let g:FuzzyFinderMode = { 'Base' : {} }
736
737 function! g:FuzzyFinderMode.Base.launch(initial_text, partial_matching, prev_bufnr, tag_files)
738 " initializes this object
739 call self.extend_options()
740 let self.partial_matching = a:partial_matching
741 let self.prev_bufnr = a:prev_bufnr
742 let self.tag_files = a:tag_files " to get local value of current buffer
743 let self.last_col = -1
744 call s:InfoFileManager.load()
745 if !s:IsAvailableMode(self)
746 echo 'This mode is not available: ' . self.to_str()
747 return
748 endif
749
750 call s:WindowManager.activate(self.make_complete_func('CompleteFunc'))
751 call s:OptionManager.set('completeopt', 'menuone')
752 call s:OptionManager.set('ignorecase', self.ignore_case)
753
754 " local autocommands
755 augroup FuzzyfinderLocal
756 autocmd!
757 execute 'autocmd CursorMovedI <buffer> call ' . self.to_str('on_cursor_moved_i()')
758 execute 'autocmd InsertLeave <buffer> nested call ' . self.to_str('on_insert_leave()' )
759 augroup END
760
761 " local mapping
762 for [lhs, rhs] in [
763 \ [ self.key_open , self.to_str('on_cr(0, 0)' ) ],
764 \ [ self.key_open_split , self.to_str('on_cr(1, 0)' ) ],
765 \ [ self.key_open_vsplit, self.to_str('on_cr(2, 0)' ) ],
766 \ [ self.key_open_tab , self.to_str('on_cr(3, 0)' ) ],
767 \ [ '<BS>' , self.to_str('on_bs()' ) ],
768 \ [ '<C-h>' , self.to_str('on_bs()' ) ],
769 \ [ self.key_next_mode , self.to_str('on_switch_mode(+1)' ) ],
770 \ [ self.key_prev_mode , self.to_str('on_switch_mode(-1)' ) ],
771 \ [ self.key_ignore_case, self.to_str('on_switch_ignore_case()') ],
772 \ ]
773 " hacks to be able to use feedkeys().
774 execute printf('inoremap <buffer> <silent> %s <C-r>=%s ? "" : ""<CR>', lhs, rhs)
775 endfor
776
777 call self.on_mode_enter()
778
779 " Starts Insert mode and makes CursorMovedI event now. Command prompt is
780 " needed to forces a completion menu to update every typing.
781 call setline(1, self.prompt . a:initial_text)
782 call feedkeys("A", 'n') " startinsert! does not work in InsertLeave handler
783 endfunction
784
785 function! g:FuzzyFinderMode.Base.on_cursor_moved_i()
786 let ln = getline('.')
787 let cl = col('.')
788 if !self.exists_prompt(ln)
789 " if command prompt is removed
790 "call setline('.', self.prompt . ln)
791 call setline('.', self.restore_prompt(ln))
792 call feedkeys(repeat("\<Right>", len(getline('.')) - len(ln)), 'n')
793 elseif cl <= len(self.prompt)
794 " if the cursor is moved before command prompt
795 call feedkeys(repeat("\<Right>", len(self.prompt) - cl + 1), 'n')
796 elseif cl > strlen(ln) && cl != self.last_col
797 " if the cursor is placed on the end of the line and has been actually moved.
798 let self.last_col = cl
799 call feedkeys("\<C-x>\<C-u>", 'n')
800 endif
801 endfunction
802
803 function! g:FuzzyFinderMode.Base.on_insert_leave()
804 let text = getline('.')
805 call self.on_mode_leave()
806 call self.empty_cache_if_existed(0)
807 call s:OptionManager.restore_all()
808 call s:WindowManager.deactivate()
809
810 " switchs to next mode, or finishes fuzzyfinder.
811 if exists('s:reserved_switch_mode')
812 let m = self.next_mode(s:reserved_switch_mode < 0)
813 call m.launch(self.remove_prompt(text), self.partial_matching, self.prev_bufnr, self.tag_files)
814 unlet s:reserved_switch_mode
815 else
816 if exists('s:reserved_command')
817 call feedkeys(self.on_open(s:reserved_command[0], s:reserved_command[1]), 'n')
818 unlet s:reserved_command
819 endif
820 endif
821 endfunction
822
823 function! g:FuzzyFinderMode.Base.on_buf_enter()
824 endfunction
825
826 function! g:FuzzyFinderMode.Base.on_buf_write_post()
827 endfunction
828
829 function! g:FuzzyFinderMode.Base.on_command_pre(cmd)
830 endfunction
831
832 function! g:FuzzyFinderMode.Base.on_cr(index, check_dir)
833 if pumvisible()
834 call feedkeys(printf("\<C-y>\<C-r>=%s(%d, 1) ? '' : ''\<CR>", self.to_str('on_cr'), a:index), 'n')
835 elseif !a:check_dir || getline('.') !~ '[/\\]$'
836 let s:reserved_command = [self.remove_prompt(getline('.')), a:index]
837 call feedkeys("\<Esc>", 'n')
838 endif
839 endfunction
840
841 function! g:FuzzyFinderMode.Base.on_bs()
842 let bs_count = 1
843 if self.smart_bs && col('.') > 2 && getline('.')[col('.') - 2] =~ '[/\\]'
844 let bs_count = len(matchstr(getline('.')[:col('.') - 3], '[^/\\]*$')) + 1
845 endif
846 call feedkeys((pumvisible() ? "\<C-e>" : "") . repeat("\<BS>", bs_count), 'n')
847 endfunction
848
849 function! g:FuzzyFinderMode.Base.on_mode_enter()
850 endfunction
851
852 function! g:FuzzyFinderMode.Base.on_mode_leave()
853 endfunction
854
855 function! g:FuzzyFinderMode.Base.on_open(expr, mode)
856 return [
857 \ ':edit ',
858 \ ':split ',
859 \ ':vsplit ',
860 \ ':tabedit ',
861 \ ][a:mode] . s:EscapeFilename(a:expr) . "\<CR>"
862 endfunction
863
864 function! g:FuzzyFinderMode.Base.on_switch_mode(next_prev)
865 let s:reserved_switch_mode = a:next_prev
866 call feedkeys("\<Esc>", 'n')
867 endfunction
868
869 function! g:FuzzyFinderMode.Base.on_switch_ignore_case()
870 let &ignorecase = !&ignorecase
871 echo "ignorecase = " . &ignorecase
872 let self.last_col = -1
873 call self.on_cursor_moved_i()
874 endfunction
875
876 " export string list
877 function! g:FuzzyFinderMode.Base.serialize_info()
878 let header = self.to_key() . "\t"
879 return map(copy(self.info), 'header . string(v:val)')
880 endfunction
881
882 " import related items from string list
883 function! g:FuzzyFinderMode.Base.deserialize_info(lines)
884 let header = self.to_key() . "\t"
885 let self.info = map(filter(copy(a:lines), 'v:val[: len(header) - 1] ==# header'),
886 \ 'eval(v:val[len(header) :])')
887 endfunction
888
889 function! g:FuzzyFinderMode.Base.complete(findstart, base)
890 if a:findstart
891 return 0
892 elseif !self.exists_prompt(a:base) || len(self.remove_prompt(a:base)) < self.min_length
893 return []
894 endif
895 call s:HighlightPrompt(self.prompt, self.prompt_highlight)
896 " FIXME: ExpandAbbrevMap duplicates index
897 let result = []
898 for expanded_base in s:ExpandAbbrevMap(self.remove_prompt(a:base), self.abbrev_map)
899 let result += self.on_complete(expanded_base)
900 endfor
901 call sort(result, 's:CompareRanks')
902 if empty(result)
903 call s:HighlightError()
904 else
905 call feedkeys("\<C-p>\<Down>", 'n')
906 endif
907 return result
908 endfunction
909
910 " This function is set to 'completefunc' which doesn't accept dictionary-functions.
911 function! g:FuzzyFinderMode.Base.make_complete_func(name)
912 execute printf("function! s:%s(findstart, base)\n" .
913 \ " return %s.complete(a:findstart, a:base)\n" .
914 \ "endfunction", a:name, self.to_str())
915 return s:GetSidPrefix() . a:name
916 endfunction
917
918 " fuzzy : 'str' -> {'base':'str', 'wi':'*s*t*r*', 're':'\V\.\*s\.\*t\.\*r\.\*'}
919 " partial: 'str' -> {'base':'str', 'wi':'*str*', 're':'\V\.\*str\.\*'}
920 function! g:FuzzyFinderMode.Base.make_pattern(base)
921 if self.partial_matching
922 let wi = (a:base !~ '^[*?]' ? '*' : '') . a:base .
923 \ (a:base =~ '[^*?]$' ? '*' : '')
924 let re = s:ConvertWildcardToRegexp(wi)
925 return { 'base': a:base, 'wi':wi, 're': re }
926 else
927 let wi = ''
928 for char in split(a:base, '\zs')
929 if wi !~ '[*?]$' && char !~ '[*?]'
930 let wi .= '*'. char
931 else
932 let wi .= char
933 endif
934 endfor
935
936 if wi !~ '[*?]$'
937 let wi .= '*'
938 endif
939
940 let re = s:ConvertWildcardToRegexp(wi)
941
942 if self.migemo_support && a:base !~ '[^\x01-\x7e]'
943 let re .= '\|\m.*' . substitute(migemo(a:base), '\\_s\*', '.*', 'g') . '.*'
944 endif
945
946 return { 'base': a:base, 'wi':wi, 're': re }
947 endif
948 endfunction
949
950 " glob with caching-feature, etc.
951 function! g:FuzzyFinderMode.Base.glob_ex(dir, file, excluded, index, matching_limit)
952 let key = fnamemodify(a:dir, ':p')
953 call extend(self, { 'cache' : {} }, 'keep')
954 if !exists('self.cache[key]')
955 echo 'Caching file list...'
956 let self.cache[key] = s:EnumExpandedDirsEntries(key, a:excluded)
957 call s:ExtendIndexToEach(self.cache[key], 1)
958 endif
959 echo 'Filtering file list...'
960 "return map(s:FilterEx(self.cache[key], 'v:val.tail =~ ' . string(a:file), a:matching_limit),
961 return map(s:FilterMatching(self.cache[key], 'tail', a:file, a:index, a:matching_limit),
962 \ '{ "index" : v:val.index, "path" : (v:val.head == key ? a:dir : v:val.head) . v:val.tail . v:val.suffix }')
963 endfunction
964
965 function! g:FuzzyFinderMode.Base.glob_dir_ex(dir, file, excluded, index, matching_limit)
966 let key = fnamemodify(a:dir, ':p')
967 call extend(self, { 'cache' : {} }, 'keep')
968 if !exists('self.cache[key]')
969 echo 'Caching file list...'
970 let self.cache[key] = filter(s:EnumExpandedDirsEntries(key, a:excluded), 'len(v:val.suffix)')
971 call insert(self.cache[key], { 'head' : key, 'tail' : '..', 'suffix' : s:PATH_SEPARATOR })
972 call insert(self.cache[key], { 'head' : key, 'tail' : '.' , 'suffix' : '' })
973 call s:ExtendIndexToEach(self.cache[key], 1)
974 endif
975 echo 'Filtering file list...'
976 "return map(s:FilterEx(self.cache[key], 'v:val.tail =~ ' . string(a:file), a:matching_limit),
977 return map(s:FilterMatching(self.cache[key], 'tail', a:file, a:index, a:matching_limit),
978 \ '{ "index" : v:val.index, "path" : (v:val.head == key ? a:dir : v:val.head) . v:val.tail . v:val.suffix }')
979 endfunction
980
981 function! g:FuzzyFinderMode.Base.empty_cache_if_existed(force)
982 if exists('self.cache') && (a:force || !exists('self.lasting_cache') || !self.lasting_cache)
983 unlet self.cache
984 "let self.cache = (type(self.cache) == type({}) ? {} :
985 " \ type(self.cache) == type([]) ? [] :
986 " \ type(self.cache) == type('') ? '' : 0)
987 endif
988 endfunction
989
990 function! g:FuzzyFinderMode.Base.to_key()
991 return filter(keys(g:FuzzyFinderMode), 'g:FuzzyFinderMode[v:val] is self')[0]
992 endfunction
993
994 " returns 'g:FuzzyFinderMode.{key}{.argument}'
995 function! g:FuzzyFinderMode.Base.to_str(...)
996 return 'g:FuzzyFinderMode.' . self.to_key() . (a:0 > 0 ? '.' . a:1 : '')
997 endfunction
998
999 " takes in g:FuzzyFinderOptions
1000 function! g:FuzzyFinderMode.Base.extend_options()
1001 let n = filter(keys(g:FuzzyFinderMode), 'g:FuzzyFinderMode[v:val] is self')[0]
1002 call extend(self, g:FuzzyFinderOptions.Base, 'force')
1003 call extend(self, g:FuzzyFinderOptions[self.to_key()], 'force')
1004 endfunction
1005
1006 function! g:FuzzyFinderMode.Base.next_mode(rev)
1007 let modes = (a:rev ? s:GetSortedAvailableModes() : reverse(s:GetSortedAvailableModes()))
1008 let m_last = modes[-1]
1009 for m in modes
1010 if m is self
1011 break
1012 endif
1013 let m_last = m
1014 endfor
1015 return m_last
1016 " vim crashed using map()
1017 endfunction
1018
1019 function! g:FuzzyFinderMode.Base.exists_prompt(in)
1020 return strlen(a:in) >= strlen(self.prompt) && a:in[:strlen(self.prompt) -1] ==# self.prompt
1021 endfunction
1022
1023 function! g:FuzzyFinderMode.Base.remove_prompt(in)
1024 return a:in[(self.exists_prompt(a:in) ? strlen(self.prompt) : 0):]
1025 endfunction
1026
1027 function! g:FuzzyFinderMode.Base.restore_prompt(in)
1028 let i = 0
1029 while i < len(self.prompt) && i < len(a:in) && self.prompt[i] ==# a:in[i]
1030 let i += 1
1031 endwhile
1032 return self.prompt . a:in[i : ]
1033 endfunction
1034
1035 "-----------------------------------------------------------------------------
1036 let g:FuzzyFinderMode.Buffer = copy(g:FuzzyFinderMode.Base)
1037
1038 function! g:FuzzyFinderMode.Buffer.on_complete(base)
1039 let patterns = self.make_pattern(a:base)
1040 let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
1041 return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
1042 endfunction
1043
1044 function! g:FuzzyFinderMode.Buffer.on_open(expr, mode)
1045 " attempts to convert the path to the number for handling unnamed buffer
1046 return printf([
1047 \ ':%sbuffer',
1048 \ ':%ssbuffer',
1049 \ ':vertical :%ssbuffer',
1050 \ ':tab :%ssbuffer',
1051 \ ][a:mode] . "\<CR>", filter(self.cache, 'v:val.path == a:expr')[0].buf_nr)
1052 endfunction
1053
1054 function! g:FuzzyFinderMode.Buffer.on_mode_enter()
1055 let self.cache = map(filter(range(1, bufnr('$')), 'buflisted(v:val) && v:val != self.prev_bufnr'),
1056 \ 'self.make_item(v:val)')
1057 if self.mru_order
1058 call s:ExtendIndexToEach(sort(self.cache, 's:CompareTimeDescending'), 1)
1059 endif
1060 endfunction
1061
1062 function! g:FuzzyFinderMode.Buffer.on_buf_enter()
1063 call self.update_buf_times()
1064 endfunction
1065
1066 function! g:FuzzyFinderMode.Buffer.on_buf_write_post()
1067 call self.update_buf_times()
1068 endfunction
1069
1070 function! g:FuzzyFinderMode.Buffer.update_buf_times()
1071 if !exists('self.buf_times')
1072 let self.buf_times = {}
1073 endif
1074 let self.buf_times[bufnr('%')] = localtime()
1075 endfunction
1076
1077 function! g:FuzzyFinderMode.Buffer.make_item(nr)
1078 return {
1079 \ 'index' : a:nr,
1080 \ 'buf_nr' : a:nr,
1081 \ 'path' : empty(bufname(a:nr)) ? '[No Name]' : fnamemodify(bufname(a:nr), ':~:.'),
1082 \ 'time' : (exists('self.buf_times[a:nr]') ? strftime(self.time_format, self.buf_times[a:nr]) : ''),
1083 \ }
1084 endfunction
1085
1086 "-----------------------------------------------------------------------------
1087 let g:FuzzyFinderMode.File = copy(g:FuzzyFinderMode.Base)
1088
1089 function! g:FuzzyFinderMode.File.on_complete(base)
1090 let base = s:ExpandTailDotSequenceToParentDir(a:base)
1091 let patterns = map(s:SplitPath(base), 'self.make_pattern(v:val)')
1092 let result = self.glob_ex(patterns.head.base, patterns.tail.re, self.excluded_path, s:SuffixNumber(patterns.tail.base), self.matching_limit)
1093 let result = filter(result, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
1094 if len(result) >= self.matching_limit
1095 call s:HighlightError()
1096 endif
1097 return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, "", base, 1)')
1098 endfunction
1099
1100 "-----------------------------------------------------------------------------
1101 let g:FuzzyFinderMode.Dir = copy(g:FuzzyFinderMode.Base)
1102
1103 function! g:FuzzyFinderMode.Dir.on_complete(base)
1104 let base = s:ExpandTailDotSequenceToParentDir(a:base)
1105 let patterns = map(s:SplitPath(base), 'self.make_pattern(v:val)')
1106 let result = self.glob_dir_ex(patterns.head.base, patterns.tail.re, self.excluded_path, s:SuffixNumber(patterns.tail.base), 0)
1107 return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, "", base, 1)')
1108 endfunction
1109
1110 function! g:FuzzyFinderMode.Dir.on_open(expr, mode)
1111 return ':cd ' . escape(a:expr, ' ') . [
1112 \ "\<CR>",
1113 \ "",
1114 \ "",
1115 \ "",
1116 \ ][a:mode]
1117 endfunction
1118
1119 "-----------------------------------------------------------------------------
1120 let g:FuzzyFinderMode.MruFile = copy(g:FuzzyFinderMode.Base)
1121
1122 function! g:FuzzyFinderMode.MruFile.on_complete(base)
1123 let patterns = self.make_pattern(a:base)
1124 let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
1125 return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
1126 endfunction
1127
1128 function! g:FuzzyFinderMode.MruFile.on_mode_enter()
1129 let self.cache = copy(self.info)
1130 let self.cache = filter(self.cache, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
1131 let self.cache = filter(self.cache, 'filereadable(v:val.path)')
1132 let self.cache = map(self.cache, '{ "path" : fnamemodify(v:val.path, ":~:."), "time" : strftime(self.time_format, v:val.time) }')
1133 let self.cache = s:ExtendIndexToEach(self.cache, 1)
1134 endfunction
1135
1136 function! g:FuzzyFinderMode.MruFile.on_buf_enter()
1137 call self.update_info()
1138 endfunction
1139
1140 function! g:FuzzyFinderMode.MruFile.on_buf_write_post()
1141 call self.update_info()
1142 endfunction
1143
1144 function! g:FuzzyFinderMode.MruFile.update_info()
1145 "if !empty(&buftype) || !filereadable(expand('%'))
1146 if !empty(&buftype)
1147 return
1148 endif
1149 call s:InfoFileManager.load()
1150 let self.info = s:UpdateMruList(self.info, { 'path' : expand('%:p'), 'time' : localtime() },
1151 \ 'path', self.max_item, self.excluded_path)
1152 call s:InfoFileManager.save()
1153 endfunction
1154
1155 "-----------------------------------------------------------------------------
1156 let g:FuzzyFinderMode.MruCmd = copy(g:FuzzyFinderMode.Base)
1157
1158 function! g:FuzzyFinderMode.MruCmd.on_complete(base)
1159 let patterns = self.make_pattern(a:base)
1160 let result = s:FilterMatching(self.cache, 'command', patterns.re, s:SuffixNumber(patterns.base), 0)
1161 return map(result, 's:FormatCompletionItem(v:val.command, v:val.index, v:val.command, self.trim_length, v:val.time, a:base, 0)')
1162 endfunction
1163
1164 function! g:FuzzyFinderMode.MruCmd.on_open(expr, mode)
1165 redraw
1166 " use feedkeys to remap <CR>
1167 return a:expr . [
1168 \ "\<C-r>=feedkeys(\"\\<CR>\", 'm')?'':''\<CR>",
1169 \ "",
1170 \ "",
1171 \ "",
1172 \ ][a:mode]
1173 endfunction
1174
1175 function! g:FuzzyFinderMode.MruCmd.on_mode_enter()
1176 let self.cache = s:ExtendIndexToEach(map(copy(self.info),
1177 \ '{ "command" : v:val.command, "time" : strftime(self.time_format, v:val.time) }'), 1)
1178 endfunction
1179
1180 function! g:FuzzyFinderMode.MruCmd.on_command_pre(cmd)
1181 call self.update_info(a:cmd)
1182 endfunction
1183
1184 function! g:FuzzyFinderMode.MruCmd.update_info(cmd)
1185 call s:InfoFileManager.load()
1186 let self.info = s:UpdateMruList(self.info, { 'command' : a:cmd, 'time' : localtime() },
1187 \ 'command', self.max_item, self.excluded_command)
1188 call s:InfoFileManager.save()
1189 endfunction
1190
1191 "-----------------------------------------------------------------------------
1192 let g:FuzzyFinderMode.FavFile = copy(g:FuzzyFinderMode.Base)
1193
1194 function! g:FuzzyFinderMode.FavFile.on_complete(base)
1195 let patterns = self.make_pattern(a:base)
1196 let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
1197 return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
1198 endfunction
1199
1200 function! g:FuzzyFinderMode.FavFile.on_mode_enter()
1201 let self.cache = copy(self.info)
1202 let self.cache = filter(self.cache, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
1203 let self.cache = map(self.cache, '{ "path" : fnamemodify(v:val.path, ":~:."), "time" : strftime(self.time_format, v:val.time) }')
1204 let self.cache = s:ExtendIndexToEach(self.cache, 1)
1205 endfunction
1206
1207 function! g:FuzzyFinderMode.FavFile.add(in_file, adds)
1208 call s:InfoFileManager.load()
1209
1210 let file = fnamemodify((empty(a:in_file) ? expand('%') : a:in_file), ':p:~')
1211
1212 call filter(self.info, 'v:val.path != file')
1213 if a:adds
1214 call add(self.info, { 'path' : file, 'time' : localtime() })
1215 endif
1216
1217 call s:InfoFileManager.save()
1218 endfunction
1219
1220 "-----------------------------------------------------------------------------
1221 let g:FuzzyFinderMode.Tag = copy(g:FuzzyFinderMode.Base)
1222
1223 function! g:FuzzyFinderMode.Tag.on_complete(base)
1224 let patterns = self.make_pattern(a:base)
1225 let result = self.find_tag(patterns.re, self.matching_limit)
1226 if len(result) >= self.matching_limit
1227 call s:HighlightError()
1228 endif
1229 return map(result, 's:FormatCompletionItem(v:val, -1, v:val, self.trim_length, "", a:base, 1)')
1230 endfunction
1231
1232 function! g:FuzzyFinderMode.Tag.on_open(expr, mode)
1233 return [
1234 \ ':tjump ',
1235 \ ':stjump ',
1236 \ ':vertical :stjump ',
1237 \ ':tab :stjump ',
1238 \ ][a:mode] . a:expr . "\<CR>"
1239 endfunction
1240
1241 function! g:FuzzyFinderMode.Tag.find_tag(pattern, matching_limit)
1242 if !len(self.tag_files)
1243 return []
1244 endif
1245
1246 let key = join(self.tag_files, "\n")
1247
1248 " cache not created or tags file updated?
1249 call extend(self, { 'cache' : {} }, 'keep')
1250 if !exists('self.cache[key]') || max(map(copy(self.tag_files), 'getftime(v:val) >= self.cache[key].time'))
1251 echo 'Caching tag list...'
1252 let self.cache[key] = {
1253 \ 'time' : localtime(),
1254 \ 'data' : s:Unique(s:Concat(map(copy(self.tag_files), 's:GetTagList(v:val)'))),
1255 \ }
1256 endif
1257
1258 echo 'Filtering tag list...'
1259 return s:FilterEx(self.cache[key].data, 'v:val =~ ' . string(a:pattern), a:matching_limit)
1260 endfunction
1261
1262 "-----------------------------------------------------------------------------
1263 let g:FuzzyFinderMode.TaggedFile = copy(g:FuzzyFinderMode.Base)
1264
1265 function! g:FuzzyFinderMode.TaggedFile.on_complete(base)
1266 let patterns = self.make_pattern(a:base)
1267 echo 'Making tagged file list...'
1268 let result = self.find_tagged_file(patterns.re, self.matching_limit)
1269 if len(result) >= self.matching_limit
1270 call s:HighlightError()
1271 endif
1272 return map(result, 's:FormatCompletionItem(v:val, -1, v:val, self.trim_length, "", a:base, 1)')
1273 endfunction
1274
1275 function! g:FuzzyFinderMode.TaggedFile.find_tagged_file(pattern, matching_limit)
1276 if !len(self.tag_files)
1277 return []
1278 endif
1279
1280 let key = join(self.tag_files, "\n")
1281
1282 " cache not created or tags file updated?
1283 call extend(self, { 'cache' : {} }, 'keep')
1284 if !exists('self.cache[key]') || max(map(copy(self.tag_files), 'getftime(v:val) >= self.cache[key].time'))
1285 echo 'Caching tagged-file list...'
1286 let self.cache[key] = {
1287 \ 'time' : localtime(),
1288 \ 'data' : s:Unique(s:Concat(map(copy(self.tag_files), 's:GetTaggedFileList(v:val)'))),
1289 \ }
1290 endif
1291
1292 echo 'Filtering tagged-file list...'
1293 return s:FilterEx(map(self.cache[key].data, 'fnamemodify(v:val, '':.'')'),
1294 \ 'v:val =~ ' . string(a:pattern),
1295 \ a:matching_limit)
1296
1297 endfunction
1298
1299 "-----------------------------------------------------------------------------
1300 " sets or restores temporary options
1301 let s:OptionManager = { 'originals' : {} }
1302
1303 function! s:OptionManager.set(name, value)
1304 call extend(self.originals, { a:name : eval('&' . a:name) }, 'keep')
1305 execute printf('let &%s = a:value', a:name)
1306 endfunction
1307
1308 function! s:OptionManager.restore_all()
1309 for [name, value] in items(self.originals)
1310 execute printf('let &%s = value', name)
1311 endfor
1312 let self.originals = {}
1313 endfunction
1314
1315 "-----------------------------------------------------------------------------
1316 " manages buffer/window for fuzzyfinder
1317 let s:WindowManager = { 'buf_nr' : -1 }
1318
1319 function! s:WindowManager.activate(complete_func)
1320 let self.prev_winnr = winnr()
1321 let cwd = getcwd()
1322
1323 if !bufexists(self.buf_nr)
1324 leftabove 1new
1325 file `='[Fuzzyfinder]'`
1326 let self.buf_nr = bufnr('%')
1327 elseif bufwinnr(self.buf_nr) == -1
1328 leftabove 1split
1329 execute self.buf_nr . 'buffer'
1330 delete _
1331 elseif bufwinnr(self.buf_nr) != bufwinnr('%')
1332 execute bufwinnr(self.buf_nr) . 'wincmd w'
1333 endif
1334
1335 " countermeasure for auto-cd script
1336 execute ':lcd ' . cwd
1337
1338 setlocal filetype=fuzzyfinder
1339 setlocal bufhidden=delete
1340 setlocal buftype=nofile
1341 setlocal noswapfile
1342 setlocal nobuflisted
1343 setlocal modifiable
1344 setlocal nocursorline " for highlighting
1345 setlocal nocursorcolumn " for highlighting
1346 let &l:completefunc = a:complete_func
1347
1348 redraw " for 'lazyredraw'
1349
1350 " suspend autocomplpop.vim
1351 if exists(':AutoComplPopLock')
1352 :AutoComplPopLock
1353 endif
1354 endfunction
1355
1356 function! s:WindowManager.deactivate()
1357 " resume autocomplpop.vim
1358 if exists(':AutoComplPopUnlock')
1359 :AutoComplPopUnlock
1360 endif
1361
1362 close
1363 execute self.prev_winnr . 'wincmd w'
1364 endfunction
1365
1366 "-----------------------------------------------------------------------------
1367 let s:InfoFileManager = { 'originals' : {} }
1368
1369 function! s:InfoFileManager.load()
1370 for m in s:GetAvailableModes()
1371 let m.info = []
1372 endfor
1373
1374 try
1375 let lines = readfile(expand(self.get_info_file()))
1376 catch /.*/
1377 return
1378 endtry
1379
1380 " compatibility check
1381 if !count(lines, self.get_info_version_line())
1382 call self.warn_old_info()
1383 let g:FuzzyFinderOptions.Base.info_file = ''
1384 return
1385 endif
1386
1387 for m in s:GetAvailableModes()
1388 call m.deserialize_info(lines)
1389 endfor
1390 endfunction
1391
1392 function! s:InfoFileManager.save()
1393 let lines = [ self.get_info_version_line() ]
1394 for m in s:GetAvailableModes()
1395 let lines += m.serialize_info()
1396 endfor
1397
1398 try
1399 call writefile(lines, expand(self.get_info_file()))
1400 catch /.*/
1401 endtry
1402 endfunction
1403
1404 function! s:InfoFileManager.edit()
1405
1406 new
1407 file `='[FuzzyfinderInfo]'`
1408 let self.bufnr = bufnr('%')
1409
1410 setlocal filetype=vim
1411 setlocal bufhidden=delete
1412 setlocal buftype=acwrite
1413 setlocal noswapfile
1414
1415 augroup FuzzyfinderInfo
1416 autocmd!
1417 autocmd BufWriteCmd <buffer> call s:InfoFileManager.on_buf_write_cmd()
1418 augroup END
1419
1420 execute '0read ' . expand(self.get_info_file())
1421 setlocal nomodified
1422
1423 endfunction
1424
1425 function! s:InfoFileManager.on_buf_write_cmd()
1426 for m in s:GetAvailableModes()
1427 call m.deserialize_info(getline(1, '$'))
1428 endfor
1429 call self.save()
1430 setlocal nomodified
1431 execute printf('%dbdelete! ', self.bufnr)
1432 echo "Information file updated"
1433 endfunction
1434
1435 function! s:InfoFileManager.get_info_version_line()
1436 return "VERSION\t206"
1437 endfunction
1438
1439 function! s:InfoFileManager.get_info_file()
1440 return g:FuzzyFinderOptions.Base.info_file
1441 endfunction
1442
1443 function! s:InfoFileManager.warn_old_info()
1444 echohl WarningMsg
1445 echo printf("==================================================\n" .
1446 \ " Your Fuzzyfinder information file is no longer \n" .
1447 \ " supported. Please remove \n" .
1448 \ " %-48s\n" .
1449 \ "==================================================\n" ,
1450 \ '"' . expand(self.get_info_file()) . '".')
1451 echohl None
1452 endfunction
1453
1454 " }}}1
1455 "=============================================================================
1456 " GLOBAL OPTIONS: {{{1
1457 " stores user-defined g:FuzzyFinderOptions ------------------------------ {{{2
1458 let user_options = (exists('g:FuzzyFinderOptions') ? g:FuzzyFinderOptions : {})
1459 " }}}2
1460
1461 " Initializes g:FuzzyFinderOptions.
1462 let g:FuzzyFinderOptions = { 'Base':{}, 'Buffer':{}, 'File':{}, 'Dir':{}, 'MruFile':{}, 'MruCmd':{}, 'FavFile':{}, 'Tag':{}, 'TaggedFile':{}}
1463 "-----------------------------------------------------------------------------
1464 " [All Mode] This is mapped to select completion item or finish input and
1465 " open a buffer/file in previous window.
1466 let g:FuzzyFinderOptions.Base.key_open = '<CR>'
1467 " [All Mode] This is mapped to select completion item or finish input and
1468 " open a buffer/file in split new window
1469 let g:FuzzyFinderOptions.Base.key_open_split = '<C-j>'
1470 " [All Mode] This is mapped to select completion item or finish input and
1471 " open a buffer/file in vertical-split new window.
1472 let g:FuzzyFinderOptions.Base.key_open_vsplit = '<C-k>'
1473 " [All Mode] This is mapped to select completion item or finish input and
1474 " open a buffer/file in a new tab page.
1475 let g:FuzzyFinderOptions.Base.key_open_tab = '<C-]>'
1476 " [All Mode] This is mapped to switch to the next mode.
1477 let g:FuzzyFinderOptions.Base.key_next_mode = '<C-l>'
1478 " [All Mode] This is mapped to switch to the previous mode.
1479 let g:FuzzyFinderOptions.Base.key_prev_mode = '<C-o>'
1480 " [All Mode] This is mapped to temporarily switch whether or not to ignore
1481 " case.
1482 let g:FuzzyFinderOptions.Base.key_ignore_case = '<C-t>'
1483 " [All Mode] This is the file name to write information of the MRU, etc. If
1484 " "" was set, Fuzzyfinder does not write to the file.
1485 let g:FuzzyFinderOptions.Base.info_file = '~/.vimfuzzyfinder'
1486 " [All Mode] Fuzzyfinder does not start a completion if a length of entered
1487 " text is less than this.
1488 let g:FuzzyFinderOptions.Base.min_length = 0
1489 " [All Mode] This is a dictionary. Each value must be a list. All matchs of a
1490 " key in entered text is expanded with the value.
1491 let g:FuzzyFinderOptions.Base.abbrev_map = {}
1492 " [All Mode] Fuzzyfinder ignores case in search patterns if non-zero is set.
1493 let g:FuzzyFinderOptions.Base.ignore_case = 1
1494 " [All Mode] This is a string to format time string. See :help strftime() for
1495 " details.
1496 let g:FuzzyFinderOptions.Base.time_format = '(%x %H:%M:%S)'
1497 " [All Mode] If a length of completion item is more than this, it is trimmed
1498 " when shown in completion menu.
1499 let g:FuzzyFinderOptions.Base.trim_length = 80
1500 " [All Mode] Fuzzyfinder does not remove caches of completion lists at the end
1501 " of explorer to reuse at the next time if non-zero was set.
1502 let g:FuzzyFinderOptions.Base.lasting_cache = 1
1503 " [All Mode] Fuzzyfinder uses Migemo if non-zero is set.
1504 let g:FuzzyFinderOptions.Base.migemo_support = 0
1505 "-----------------------------------------------------------------------------
1506 " [Buffer Mode] This disables all functions of this mode if zero was set.
1507 let g:FuzzyFinderOptions.Buffer.mode_available = 1
1508 " [Buffer Mode] The prompt string.
1509 let g:FuzzyFinderOptions.Buffer.prompt = '>Buffer>'
1510 " [Buffer Mode] The highlight group name for a prompt string.
1511 let g:FuzzyFinderOptions.Buffer.prompt_highlight = 'Question'
1512 " [Buffer Mode] Pressing <BS> after a path separator deletes one directory
1513 " name if non-zero is set.
1514 let g:FuzzyFinderOptions.Buffer.smart_bs = 1
1515 " [Buffer Mode] The completion items is sorted in the order of recently used
1516 " if non-zero is set.
1517 let g:FuzzyFinderOptions.Buffer.mru_order = 1
1518 " [Buffer Mode] This is used to sort modes for switching to the next/previous
1519 " mode.
1520 let g:FuzzyFinderOptions.Buffer.switch_order = 10
1521 "-----------------------------------------------------------------------------
1522 " [File Mode] This disables all functions of this mode if zero was set.
1523 let g:FuzzyFinderOptions.File.mode_available = 1
1524 " [File Mode] The prompt string.
1525 let g:FuzzyFinderOptions.File.prompt = '>File>'
1526 " [File Mode] The highlight group name for a prompt string.
1527 let g:FuzzyFinderOptions.File.prompt_highlight = 'Question'
1528 " [File Mode] Pressing <BS> after a path separator deletes one directory name
1529 " if non-zero is set.
1530 let g:FuzzyFinderOptions.File.smart_bs = 1
1531 " [File Mode] This is used to sort modes for switching to the next/previous
1532 " mode.
1533 let g:FuzzyFinderOptions.File.switch_order = 20
1534 " [File Mode] The items matching this are excluded from the completion list.
1535 let g:FuzzyFinderOptions.File.excluded_path = '\v\~$|\.o$|\.exe$|\.bak$|\.swp$|((^|[/\\])\.[/\\]$)'
1536 " [File Mode] If a number of matched items was over this, the completion
1537 " process is aborted.
1538 let g:FuzzyFinderOptions.File.matching_limit = 200
1539 "-----------------------------------------------------------------------------
1540 " [Directory Mode] This disables all functions of this mode if zero was set.
1541 let g:FuzzyFinderOptions.Dir.mode_available = 1
1542 " [Directory Mode] The prompt string.
1543 let g:FuzzyFinderOptions.Dir.prompt = '>Dir>'
1544 " [Directory Mode] The highlight group name for a prompt string.
1545 let g:FuzzyFinderOptions.Dir.prompt_highlight = 'Question'
1546 " [Directory Mode] Pressing <BS> after a path separator deletes one directory
1547 " name if non-zero is set.
1548 let g:FuzzyFinderOptions.Dir.smart_bs = 1
1549 " [Directory Mode] This is used to sort modes for switching to the
1550 " next/previous mode.
1551 let g:FuzzyFinderOptions.Dir.switch_order = 30
1552 " [Directory Mode] The items matching this are excluded from the completion
1553 " list.
1554 let g:FuzzyFinderOptions.Dir.excluded_path = '\v(^|[/\\])\.{1,2}[/\\]$'
1555 "-----------------------------------------------------------------------------
1556 " [Mru-File Mode] This disables all functions of this mode if zero was set.
1557 let g:FuzzyFinderOptions.MruFile.mode_available = 1
1558 " [Mru-File Mode] The prompt string.
1559 let g:FuzzyFinderOptions.MruFile.prompt = '>MruFile>'
1560 " [Mru-File Mode] The highlight group name for a prompt string.
1561 let g:FuzzyFinderOptions.MruFile.prompt_highlight = 'Question'
1562 " [Mru-File Mode] Pressing <BS> after a path separator deletes one directory
1563 " name if non-zero is set.
1564 let g:FuzzyFinderOptions.MruFile.smart_bs = 1
1565 " [Mru-File Mode] This is used to sort modes for switching to the
1566 " next/previous mode.
1567 let g:FuzzyFinderOptions.MruFile.switch_order = 40
1568 " [Mru-File Mode] The items matching this are excluded from the completion
1569 " list.
1570 let g:FuzzyFinderOptions.MruFile.excluded_path = '\v\~$|\.bak$|\.swp$'
1571 " [Mru-File Mode] This is an upper limit of MRU items to be stored.
1572 let g:FuzzyFinderOptions.MruFile.max_item = 99
1573 "-----------------------------------------------------------------------------
1574 " [Mru-Cmd Mode] This disables all functions of this mode if zero was set.
1575 let g:FuzzyFinderOptions.MruCmd.mode_available = 1
1576 " [Mru-Cmd Mode] The prompt string.
1577 let g:FuzzyFinderOptions.MruCmd.prompt = '>MruCmd>'
1578 " [Mru-Cmd Mode] The highlight group name for a prompt string.
1579 let g:FuzzyFinderOptions.MruCmd.prompt_highlight = 'Question'
1580 " [Mru-Cmd Mode] Pressing <BS> after a path separator deletes one directory
1581 " name if non-zero is set.
1582 let g:FuzzyFinderOptions.MruCmd.smart_bs = 0
1583 " [Mru-Cmd Mode] This is used to sort modes for switching to the next/previous
1584 " mode.
1585 let g:FuzzyFinderOptions.MruCmd.switch_order = 50
1586 " [Mru-Cmd Mode] The items matching this are excluded from the completion
1587 " list.
1588 let g:FuzzyFinderOptions.MruCmd.excluded_command = '^$'
1589 " [Mru-Cmd Mode] This is an upper limit of MRU items to be stored.
1590 let g:FuzzyFinderOptions.MruCmd.max_item = 99
1591 "-----------------------------------------------------------------------------
1592 " [Favorite-File Mode] This disables all functions of this mode if zero was
1593 " set.
1594 let g:FuzzyFinderOptions.FavFile.mode_available = 1
1595 " [Favorite-File Mode] The prompt string.
1596 let g:FuzzyFinderOptions.FavFile.prompt = '>FavFile>'
1597 " [Favorite-File Mode] The highlight group name for a prompt string.
1598 let g:FuzzyFinderOptions.FavFile.prompt_highlight = 'Question'
1599 " [Favorite-File Mode] Pressing <BS> after a path separator deletes one
1600 " directory name if non-zero is set.
1601 let g:FuzzyFinderOptions.FavFile.smart_bs = 1
1602 " [Favorite-File Mode] This is used to sort modes for switching to the
1603 " next/previous mode.
1604 let g:FuzzyFinderOptions.FavFile.switch_order = 60
1605 "-----------------------------------------------------------------------------
1606 " [Tag Mode] This disables all functions of this mode if zero was set.
1607 let g:FuzzyFinderOptions.Tag.mode_available = 1
1608 " [Tag Mode] The prompt string.
1609 let g:FuzzyFinderOptions.Tag.prompt = '>Tag>'
1610 " [Tag Mode] The highlight group name for a prompt string.
1611 let g:FuzzyFinderOptions.Tag.prompt_highlight = 'Question'
1612 " [Tag Mode] Pressing <BS> after a path separator deletes one directory name
1613 " if non-zero is set.
1614 let g:FuzzyFinderOptions.Tag.smart_bs = 0
1615 " [Tag Mode] This is used to sort modes for switching to the next/previous
1616 " mode.
1617 let g:FuzzyFinderOptions.Tag.switch_order = 70
1618 " [Tag Mode] The items matching this are excluded from the completion list.
1619 let g:FuzzyFinderOptions.Tag.excluded_path = '\v\~$|\.bak$|\.swp$'
1620 " [Tag Mode] If a number of matched items was over this, the completion
1621 " process is aborted.
1622 let g:FuzzyFinderOptions.Tag.matching_limit = 200
1623 "-----------------------------------------------------------------------------
1624 " [Tagged-File Mode] This disables all functions of this mode if zero was set.
1625 let g:FuzzyFinderOptions.TaggedFile.mode_available = 1
1626 " [Tagged-File Mode] The prompt string.
1627 let g:FuzzyFinderOptions.TaggedFile.prompt = '>TaggedFile>'
1628 " [Tagged-File Mode] The highlight group name for a prompt string.
1629 let g:FuzzyFinderOptions.TaggedFile.prompt_highlight = 'Question'
1630 " [Tagged-File Mode] Pressing <BS> after a path separator deletes one
1631 " directory name if non-zero is set.
1632 let g:FuzzyFinderOptions.TaggedFile.smart_bs = 0
1633 " [Tagged-File Mode] This is used to sort modes for switching to the
1634 " next/previous mode.
1635 let g:FuzzyFinderOptions.TaggedFile.switch_order = 80
1636 " [Tagged-File Mode] If a number of matched items was over this, the
1637 " completion process is aborted.
1638 let g:FuzzyFinderOptions.TaggedFile.matching_limit = 200
1639
1640 " overwrites default values of g:FuzzyFinderOptions with user-defined values - {{{2
1641 call map(user_options, 'extend(g:FuzzyFinderOptions[v:key], v:val, ''force'')')
1642 call map(copy(g:FuzzyFinderMode), 'v:val.extend_options()')
1643 " }}}2
1644
1645 " }}}1
1646 "=============================================================================
1647 " COMMANDS/AUTOCOMMANDS/MAPPINGS/ETC.: {{{1
1648
1649 let s:PATH_SEPARATOR = (has('win32') || has('win64') ? '\' : '/')
1650 let s:MATCHING_RATE_BASE = 10000000
1651 let s:ABBR_TRIM_MARK = '...'
1652
1653 augroup FuzzyfinderGlobal
1654 autocmd!
1655 autocmd BufEnter * for m in s:GetAvailableModes() | call m.extend_options() | call m.on_buf_enter() | endfor
1656 autocmd BufWritePost * for m in s:GetAvailableModes() | call m.extend_options() | call m.on_buf_write_post() | endfor
1657 augroup END
1658
1659 " cnoremap has a problem, which doesn't expand cabbrev.
1660 cmap <silent> <expr> <CR> <SID>OnCmdCR()
1661
1662 command! -bang -narg=? -complete=buffer FuzzyFinderBuffer call g:FuzzyFinderMode.Buffer.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1663 command! -bang -narg=? -complete=file FuzzyFinderFile call g:FuzzyFinderMode.File.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1664 command! -bang -narg=? -complete=dir FuzzyFinderDir call g:FuzzyFinderMode.Dir.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1665 command! -bang -narg=? -complete=file FuzzyFinderMruFile call g:FuzzyFinderMode.MruFile.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1666 command! -bang -narg=? -complete=file FuzzyFinderMruCmd call g:FuzzyFinderMode.MruCmd.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1667 command! -bang -narg=? -complete=file FuzzyFinderFavFile call g:FuzzyFinderMode.FavFile.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1668 command! -bang -narg=? -complete=tag FuzzyFinderTag call g:FuzzyFinderMode.Tag.launch (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1669 command! -bang -narg=? -complete=file FuzzyFinderTaggedFile call g:FuzzyFinderMode.TaggedFile.launch(<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
1670 command! -bang -narg=? -complete=file FuzzyFinderEditInfo call s:InfoFileManager.edit()
1671 command! -bang -narg=? -complete=file FuzzyFinderAddFavFile call g:FuzzyFinderMode.FavFile.add(<q-args>, 1)
1672 command! -bang -narg=0 FuzzyFinderRemoveCache for m in s:GetAvailableModes() | call m.empty_cache_if_existed(1) | endfor
1673
1674 " }}}1
1675 "=============================================================================
1676 " vim: set fdm=marker: