Mercurial > dotfiles
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: |