diff .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
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/.vim/plugin/fuzzyfinder.vim
@@ -0,0 +1,1676 @@
+"=============================================================================
+" fuzzyfinder.vim : Fuzzy/Partial pattern explorer for
+"                   buffer/file/MRU/command/favorite/tag/etc.
+"=============================================================================
+"
+" Author:  Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
+" Version: 2.13, for Vim 7.1
+" Licence: MIT Licence
+" URL:     http://www.vim.org/scripts/script.php?script_id=1984
+"
+" GetLatestVimScripts: 1984 1 :AutoInstall: fuzzyfinder.vim
+"
+"=============================================================================
+" DOCUMENT: {{{1
+"   Japanese: http://vim.g.hatena.ne.jp/keyword/fuzzyfinder.vim
+"
+"-----------------------------------------------------------------------------
+" Description:
+"   Fuzzyfinder provides convenient ways to quickly reach the buffer/file you
+"   want. Fuzzyfinder finds matching files/buffers with a fuzzy/partial
+"   pattern to which it converted the entered pattern.
+"
+"   E.g.: entered pattern -> fuzzy pattern / partial pattern
+"         abc             -> *a*b*c*       / *abc*
+"         a?c             -> *a?c*         / *a?c*
+"         dir/file        -> dir/*f*i*l*e* / dir/*file*
+"         d*r/file        -> d*r/*f*i*l*e* / d*r/*file*
+"         ../**/s         -> ../**/*s*     / ../**/*s*
+"
+"     (** allows searching a directory tree.)
+"
+"   You will be happy when:
+"     "./OhLongLongLongLongLongFile.txt"
+"     "./AhLongLongLongLongLongName.txt"
+"     "./AhLongLongLongLongLongFile.txt" <- you want :O
+"     Type "AF" and "AhLongLongLongLongLongFile.txt" will be select. :D
+"
+"   Fuzzyfinder has some modes:
+"     - Buffer mode
+"     - File mode
+"     - Directory mode (yet another :cd command)
+"     - MRU-file mode (most recently used files)
+"     - MRU-command mode (most recently used command-lines)
+"     - Favorite-file mode
+"     - Tag mode (yet another :tag command)
+"     - Tagged-file mode (files which are included in current tags)
+"
+"   Fuzzyfinder supports the multibyte.
+"
+"-----------------------------------------------------------------------------
+" Installation:
+"   Drop this file in your plugin directory.
+"
+"-----------------------------------------------------------------------------
+" Usage:
+"   Starting Fuzzyfinder:
+"     You can start Fuzzyfinder by the following commands:
+"
+"       :FuzzyFinderBuffer      - launchs buffer-mode Fuzzyfinder.
+"       :FuzzyFinderFile        - launchs file-mode Fuzzyfinder.
+"       :FuzzyFinderDir         - launchs directory-mode Fuzzyfinder.
+"       :FuzzyFinderMruFile     - launchs MRU-file-mode Fuzzyfinder.
+"       :FuzzyFinderMruCmd      - launchs MRU-command-mode Fuzzyfinder.
+"       :FuzzyFinderFavFile     - launchs favorite-file-mode Fuzzyfinder.
+"       :FuzzyFinderTag         - launchs tag-mode Fuzzyfinder.
+"       :FuzzyFinderTaggedFile  - launchs tagged-file-mode Fuzzyfinder.
+"
+"     It is recommended to map these commands. These commands can take initial
+"     text as a command argument. The text will be entered after Fuzzyfinder
+"     launched. If a command was executed with a ! modifier (e.g.
+"     :FuzzyFinderTag!), it enables the partial matching instead of the fuzzy
+"     matching.
+"
+"
+"   In Fuzzyfinder:
+"     The entered pattern is converted to the fuzzy pattern and buffers/files
+"     which match the pattern is shown in a completion menu.
+"
+"     A completion menu is shown when you type at the end of the line and the
+"     length of entered pattern is more than setting value. By default, it is
+"     shown at the beginning.
+"
+"     If too many items (200, by default) were matched, the completion is
+"     aborted to reduce nonresponse.
+"
+"     If an item were matched with entered pattern exactly, it is shown first.
+"     The item whose file name has longer prefix matching is placed upper.
+"     Also, an item which matched more sequentially is placed upper. The item
+"     whose index were matched with a number suffixed with entered pattern is
+"     placed lower. the first item in the completion menu will be selected
+"     automatically.
+"
+"     You can open a selected item in various ways:
+"       <CR>  - opens in a previous window.
+"       <C-j> - opens in a split window.
+"       <C-k> - opens in a vertical-split window.
+"       <C-]> - opens in a new tab page.
+"     In MRU-command mode, <CR> executes a selected command and others just
+"     put it into a command-line. These key mappings are customizable.
+"
+"     To cancel and return to previous window, leave Insert mode.
+"
+"     To Switch the mode without leaving Insert mode, use <C-l> or <C-o>.
+"     This key mapping is customizable.
+"
+"     If you want to temporarily change whether or not to ignore case, use
+"     <C-t>. This key mapping is customizable.
+"
+"   To Hide The Completion Temporarily Menu In Fuzzyfinder:
+"     You can close it by <C-e> and reopen it by <C-x><C-u>.
+"
+"   About Highlighting:
+"     Fuzzyfinder highlights the buffer with "Error" group when the completion
+"     item was not found or the completion process was aborted.
+"
+"   About Alternative Approach For Tag Jump:
+"     Following mappings are replacements for :tag and <C-]>:
+"
+"       nnoremap <silent> <C-f><C-t> :FuzzyFinderTag!<CR>
+"       nnoremap <silent> <C-]>      :FuzzyFinderTag! <C-r>=expand('<cword>')<CR><CR>
+"
+"     In the tag mode, it is recommended to use partial matching instead of
+"     fuzzy matching.
+"
+"   About Tagged File Mode:
+"     The files which are included in the current tags are the ones which are
+"     related to the current working environment. So this mode is a pseudo
+"     project mode.
+"
+"   About Usage Of Command Argument:
+"     As an example, if you want to launch file-mode Fuzzyfinder with the full
+"     path of current directory, map like below:
+"
+"       nnoremap <C-p> :FuzzyFinderFile <C-r>=fnamemodify(getcwd(), ':p')<CR><CR>
+"
+"     Instead, if you want the directory of current buffer and not current
+"     directory:
+"
+"       nnoremap <C-p> :FuzzyFinderFile <C-r>=expand('%:~:.')[:-1-len(expand('%:~:.:t'))]<CR><CR>
+"
+"   About Abbreviations And Multiple Search:
+"     You can use abbreviations and multiple search in each mode. For example,
+"     set as below:
+"
+"       let g:FuzzyFinderOptions.Base.abbrev_map  = {
+"             \   "^WORK" : [
+"             \     "~/project/**/src/",
+"             \     ".vim/plugin/",
+"             \   ],
+"             \ }
+"
+"     And type "WORKtxt" in file-mode Fuzzyfinder, then it searches by
+"     following patterns:
+"
+"       "~/project/**/src/*t*x*t*"
+"       ".vim/plugin/*t*x*t*"
+"
+"   Adding Favorite Files:
+"     You can add a favorite file by the following commands:
+"
+"       :FuzzyFinderAddFavFile {filename}
+"
+"     If you do not specify the filename, current file name is used.
+"
+"   About Information File:
+"     Fuzzyfinder writes information of the MRU, favorite, etc to the file by
+"     default (~/.vimfuzzyfinder).
+
+"     :FuzzyFinderEditInfo command is helpful in editing your information
+"     file. This command reads the information file in new unnamed buffer.
+"     Write the buffer and the information file will be updated.
+"
+"   About Cache:
+"     Once a cache was created, It is not updated automatically to improve
+"     response by default. To update it, use :FuzzyFinderRemoveCache command.
+"
+"   About Migemo:
+"     Migemo is a search method for Japanese language.
+"
+"-----------------------------------------------------------------------------
+" Options:
+"   You can set options via g:FuzzyFinderOptions which is a dictionary. See
+"   the folded section named "GLOBAL OPTIONS:" for details. To easily set
+"   options for customization, put necessary entries from GLOBAL OPTIONS into
+"   your vimrc file and edit those values.
+"
+"-----------------------------------------------------------------------------
+" Setting Example:
+"   let g:FuzzyFinderOptions = { 'Base':{}, 'Buffer':{}, 'File':{}, 'Dir':{}, 'MruFile':{}, 'MruCmd':{}, 'FavFile':{}, 'Tag':{}, 'TaggedFile':{}}
+"   let g:FuzzyFinderOptions.Base.ignore_case = 1
+"   let g:FuzzyFinderOptions.Base.abbrev_map  = {
+"         \   '\C^VR' : [
+"         \     '$VIMRUNTIME/**',
+"         \     '~/.vim/**',
+"         \     '$VIM/.vim/**',
+"         \     '$VIM/vimfiles/**',
+"         \   ],
+"         \ }
+"   let g:FuzzyFinderOptions.MruFile.max_item = 200
+"   let g:FuzzyFinderOptions.MruCmd.max_item = 200
+"   nnoremap <silent> <C-n>      :FuzzyFinderBuffer<CR>
+"   nnoremap <silent> <C-m>      :FuzzyFinderFile <C-r>=expand('%:~:.')[:-1-len(expand('%:~:.:t'))]<CR><CR>
+"   nnoremap <silent> <C-j>      :FuzzyFinderMruFile<CR>
+"   nnoremap <silent> <C-k>      :FuzzyFinderMruCmd<CR>
+"   nnoremap <silent> <C-p>      :FuzzyFinderDir <C-r>=expand('%:p:~')[:-1-len(expand('%:p:~:t'))]<CR><CR>
+"   nnoremap <silent> <C-f><C-d> :FuzzyFinderDir<CR>
+"   nnoremap <silent> <C-f><C-f> :FuzzyFinderFavFile<CR>
+"   nnoremap <silent> <C-f><C-t> :FuzzyFinderTag!<CR>
+"   nnoremap <silent> <C-f><C-g> :FuzzyFinderTaggedFile<CR>
+"   noremap  <silent> g]         :FuzzyFinderTag! <C-r>=expand('<cword>')<CR><CR>
+"   nnoremap <silent> <C-f>F     :FuzzyFinderAddFavFile<CR>
+"   nnoremap <silent> <C-f><C-e> :FuzzyFinderEditInfo<CR>
+"
+"-----------------------------------------------------------------------------
+" Special Thanks:
+"   Vincent Wang
+"   Ingo Karkat
+"   Nikolay Golubev
+"   Brian Doyle
+"   id:secondlife
+"   Matt Tolton
+"
+"-----------------------------------------------------------------------------
+" ChangeLog:
+"   2.13:
+"     - Fixed a bug that a directory disappeared when a file in that directroy
+"       was being opened in File/Mru-File mode.
+"
+"   2.12:
+"     - Changed to be able to show completion items in the order of recently
+"       used in Buffer mode.
+"     - Added g:FuzzyFinderOptions.Buffer.mru_order option.
+"
+"   2.11:
+"     - Changed that a dot sequence of entered pattern is expanded to parent
+"       directroies in File/Dir mode.
+"       E.g.: "foo/...bar" -> "foo/../../bar"
+"     - Fixed a bug that a prompt string was excessively inserted.
+"
+"   2.10:
+"     - Changed not to show a current buffer in a completion menu.
+"     - Fixed a bug that a filename to open was not been escaped.
+"     - Added 'prompt' option.
+"     - Added 'prompt_highlight' option.
+"     - Removed g:FuzzyFinderOptions.MruFile.no_special_buffer option.
+"
+"   2.9:
+"     - Enhanced <BS> behavior in Fuzzyfinder and added 'smart_bs' option.
+"     - Fixed a bug that entered pattern was not been escaped.
+"     - Fixed not to insert "zv" with "c/pattern<CR>" command in Normal mode.
+"     - Avoid the slow down problem caused by filereadable() check for the MRU
+"       information in BufEnter/BufWritePost.
+"
+"   2.8.1:
+"     - Fixed a bug caused by the non-escaped buffer name "[Fuzzyfinder]".
+"     - Fixed a command to open in a new tab page in Buffer mode.
+"   2.8:
+"     - Added 'trim_length' option.
+"     - Added 'switch_order' option.
+"     - Fixed a bug that entered command did not become the newest in the
+"       history.
+"     - Fixed a bug that folds could not open with <CR> in a command-line when
+"       searching.
+"     - Removed 'excluded_indicator' option. Now a completion list in Buffer
+"       mode is the same as a result of :buffers.
+"
+"   2.7:
+"     - Changed to find an item whose index is matched with the number
+"       suffixed with entered pattern.
+"     - Fixed the cache bug after changing current directroy in File mode.
+"
+"   2.6.2:
+"     - Fixed not to miss changes in options when updates the MRU information.
+"
+"   2.6.1:
+"     - Fixed a bug related to floating-point support.
+"     - Added support for GetLatestVimScripts.
+"
+"   2.6:
+"     - Revived MRU-command mode. The problem with a command-line abbreviation
+"       was solved.
+"     - Changed the specification of the information file.
+"     - Added :FuzzyFinderEditInfo command.
+
+"   2.5.1:
+"     - Fixed to be able to match "foo/./bar" by "foo/**/bar" in File mode.
+"     - Fixed to be able to open a space-containing file in File mode.
+"     - Fixed to honor the current working directory properly in File mode.
+"
+"   2.5:
+"     - Fixed the bug that a wrong initial text is entered after switching to a
+"       next mode.
+"     - Fixed the bug that it does not return to previous window after leaving
+"       Fuzzyfinder one.
+"
+"   2.4:
+"     - Fixed the bug that Fuzzyfinder fails to open a file caused by auto-cd
+"       plugin/script.
+"
+"   2.3:
+"     - Added a key mapping to open items in a new tab page and
+"       g:FuzzyFinderOptions.Base.key_open_tab opton.
+"     - Changed to show Fuzzyfinder window above last window even if
+"       'splitbelow' was set.
+"     - Changed to set nocursorline and nocursorcolumn in Fuzzyfinder.
+"     - Fixed not to push up a buffer number unlimitedly.
+"
+"   2.2:
+"     - Added new feature, which is the partial matching.
+"     - Fixed the bug that an error occurs when "'" was entered.
+"
+"   2.1:
+"     - Restructured the option system AGAIN. Sorry :p
+"     - Changed to inherit a typed text when switching a mode without leaving
+"       Insert mode.
+"     - Changed commands which launch explorers to be able to take a argument
+"       for initial text.
+"     - Changed to complete file names by relative path and not full path in
+"       the buffer/mru-file/tagged-file mode.
+"     - Changed to highlight a typed text when the completion item was not
+"       found or the completion process was aborted.
+"     - Changed to create caches for each tag file and not working directory
+"       in the tag/tagged-file mode.
+"     - Fixed the bug that the buffer mode couldn't open a unnamed buffer.
+"     - Added 'matching_limit' option.
+"     - Removed 'max_match' option. Use 'matching_limit' option instead.
+"     - Removed 'initial_text' option. Use command argument instead.
+"     - Removed the MRU-command mode.
+"
+"   2.0:
+"     - Added the tag mode.
+"     - Added the tagged-file mode.
+"     - Added :FuzzyFinderRemoveCache command.
+"     - Restructured the option system. many options are changed names or
+"       default values of some options.
+"     - Changed to hold and reuse caches of completion lists by default.
+"     - Changed to set filetype 'fuzzyfinder'.
+"     - Disabled the MRU-command mode by default because there are problems.
+"     - Removed FuzzyFinderAddMode command.
+"
+"   1.5:
+"     - Added the directory mode.
+"     - Fixed the bug that it caused an error when switch a mode in Insert
+"       mode.
+"     - Changed g:FuzzyFinder_KeySwitchMode type to a list.
+"
+"   1.4:
+"     - Changed the specification of the information file.
+"     - Added the MRU-commands mode.
+"     - Renamed :FuzzyFinderAddFavorite command to :FuzzyFinderAddFavFile.
+"     - Renamed g:FuzzyFinder_MruModeVars option to
+"       g:FuzzyFinder_MruFileModeVars.
+"     - Renamed g:FuzzyFinder_FavoriteModeVars option to
+"       g:FuzzyFinder_FavFileModeVars.
+"     - Changed to show registered time of each item in MRU/favorite mode.
+"     - Added 'timeFormat' option for MRU/favorite modes.
+"
+"   1.3:
+"     - Fixed a handling of multi-byte characters.
+"
+"   1.2:
+"     - Added support for Migemo. (Migemo is Japanese search method.)
+"
+"   1.1:
+"     - Added the favorite mode.
+"     - Added new features, which are abbreviations and multiple search.
+"     - Added 'abbrevMap' option for each mode.
+"     - Added g:FuzzyFinder_MruModeVars['ignoreSpecialBuffers'] option.
+"     - Fixed the bug that it did not work correctly when a user have mapped
+"       <C-p> or <Down>.
+"
+"   1.0:
+"     - Added the MRU mode.
+"     - Added commands to add and use original mode.
+"     - Improved the sorting algorithm for completion items.
+"     - Added 'initialInput' option to automatically insert a text at the
+"       beginning of a mode.
+"     - Changed that 'excludedPath' option works for the entire path.
+"     - Renamed some options. 
+"     - Changed default values of some options. 
+"     - Packed the mode-specific options to dictionaries.
+"     - Removed some options.
+"
+"   0.6:
+"     - Fixed some bugs.
+
+"   0.5:
+"     - Improved response by aborting processing too many items.
+"     - Changed to be able to open a buffer/file not only in previous window
+"       but also in new window.
+"     - Fixed a bug that recursive searching with '**' does not work.
+"     - Added g:FuzzyFinder_CompletionItemLimit option.
+"     - Added g:FuzzyFinder_KeyOpen option.
+"
+"   0.4:
+"     - Improved response of the input.
+"     - Improved the sorting algorithm for completion items. It is based on
+"       the matching level. 1st is perfect matching, 2nd is prefix matching,
+"       and 3rd is fuzzy matching.
+"     - Added g:FuzzyFinder_ExcludePattern option.
+"     - Removed g:FuzzyFinder_WildIgnore option.
+"     - Removed g:FuzzyFinder_EchoPattern option.
+"     - Removed g:FuzzyFinder_PathSeparator option.
+"     - Changed the default value of g:FuzzyFinder_MinLengthFile from 1 to 0.
+"
+"   0.3:
+"     - Added g:FuzzyFinder_IgnoreCase option.
+"     - Added g:FuzzyFinder_KeyToggleIgnoreCase option.
+"     - Added g:FuzzyFinder_EchoPattern option.
+"     - Changed the open command in a buffer mode from ":edit" to ":buffer" to
+"       avoid being reset cursor position.
+"     - Changed the default value of g:FuzzyFinder_KeyToggleMode from
+"       <C-Space> to <F12> because <C-Space> does not work on some CUI
+"       environments.
+"     - Changed to avoid being loaded by Vim before 7.0.
+"     - Fixed a bug with making a fuzzy pattern which has '\'.
+"
+"   0.2:
+"     - A bug it does not work on Linux is fixed.
+"
+"   0.1:
+"     - First release.
+"
+" }}}1
+"=============================================================================
+" INCLUDE GUARD: {{{1
+if exists('loaded_fuzzyfinder') || v:version < 701
+  finish
+endif
+let loaded_fuzzyfinder = 1
+
+" }}}1
+"=============================================================================
+" FUNCTION: {{{1
+"-----------------------------------------------------------------------------
+" LIST FUNCTIONS:
+
+function! s:Unique(in)
+  let sorted = sort(a:in)
+  if len(sorted) < 2
+    return sorted
+  endif
+  let last = remove(sorted, 0)
+  let result = [last]
+  for item in sorted
+    if item != last
+      call add(result, item)
+      let last = item
+    endif
+  endfor
+  return result
+endfunction
+
+" [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ]
+function! s:Concat(in)
+  let result = []
+  for l in a:in
+    let result += l
+  endfor
+  return result
+endfunction
+
+" [ [ 0, 1 ], [ 2, 3, 4 ], ] -> [ [0,2], [0,3], [0,4], [1,2], [1,3], [1,4] ]
+function! s:CartesianProduct(lists)
+  if empty(a:lists)
+    return []
+  endif
+  "let result = map((a:lists[0]), '[v:val]')
+  let result = [ [] ]
+  for l in a:lists
+    let temp = []
+    for r in result
+      let temp += map(copy(l), 'add(copy(r), v:val)')
+    endfor
+    let result = temp
+  endfor
+  return result
+endfunction
+
+" copy + filter + limit
+function! s:FilterEx(in, expr, limit)
+  if a:limit <= 0
+    return filter(copy(a:in), a:expr)
+  endif
+  let result = []
+  let stride = a:limit * 3 / 2 " x1.5
+  for i in range(0, len(a:in) - 1, stride)
+    let result += filter(a:in[i : i + stride - 1], a:expr)
+    if len(result) >= a:limit
+      return remove(result, 0, a:limit - 1)
+    endif
+  endfor
+  return result
+endfunction
+
+" 
+function! s:FilterMatching(entries, key, pattern, index, limit)
+  return s:FilterEx(a:entries, 'v:val[''' . a:key . '''] =~ ' . string(a:pattern) . ' || v:val.index == ' . a:index, a:limit)
+endfunction
+
+function! s:ExtendIndexToEach(in, offset)
+  for i in range(len(a:in))
+    let a:in[i].index = i + a:offset
+  endfor
+  return a:in
+endfunction
+
+function! s:UpdateMruList(mrulist, new_item, key, max_item, excluded)
+  let result = copy(a:mrulist)
+  let result = filter(result,'v:val[a:key] != a:new_item[a:key]')
+  let result = insert(result, a:new_item)
+  let result = filter(result, 'v:val[a:key] !~ a:excluded')
+  return result[0 : a:max_item - 1]
+endfunction
+
+"-----------------------------------------------------------------------------
+" STRING FUNCTIONS:
+
+" trims a:str and add a:mark if a length of a:str is more than a:len
+function! s:TrimLast(str, len)
+  if a:len <= 0 || len(a:str) <= a:len
+    return a:str
+  endif
+  return a:str[:(a:len - len(s:ABBR_TRIM_MARK) - 1)] . s:ABBR_TRIM_MARK
+endfunction
+
+" takes suffix numer. if no digits, returns -1
+function! s:SuffixNumber(str)
+  let s = matchstr(a:str, '\d\+$')
+  return (len(s) ? str2nr(s) : -1)
+endfunction
+
+function! s:ConvertWildcardToRegexp(expr)
+  let re = escape(a:expr, '\')
+  for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ]
+    let re = substitute(re, pat, sub, 'g')
+  endfor
+  return '\V' . re
+endfunction
+
+" "foo/bar/hoge" -> { head: "foo/bar/", tail: "hoge" }
+function! s:SplitPath(path)
+  let dir = matchstr(a:path, '^.*[/\\]')
+  return  {
+        \   'head' : dir,
+        \   'tail' : a:path[strlen(dir):]
+        \ }
+endfunction
+
+function! s:EscapeFilename(fn)
+  return escape(a:fn, " \t\n*?[{`$%#'\"|!<")
+endfunction
+
+" "foo/.../bar/...hoge" -> "foo/.../bar/../../hoge"
+function! s:ExpandTailDotSequenceToParentDir(base)
+  return substitute(a:base, '^\(.*[/\\]\)\?\zs\.\(\.\+\)\ze[^/\\]*$',
+        \           '\=repeat(".." . s:PATH_SEPARATOR, len(submatch(2)))', '')
+endfunction
+
+"-----------------------------------------------------------------------------
+" FUNCTIONS FOR COMPLETION ITEM:
+
+function! s:FormatCompletionItem(expr, number, abbr, trim_len, time, base_pattern, evals_path_tail)
+  if a:evals_path_tail
+    let rate = s:EvaluateMatchingRate(s:SplitPath(matchstr(a:expr, '^.*[^/\\]')).tail,
+          \                           s:SplitPath(a:base_pattern).tail)
+  else
+    let rate = s:EvaluateMatchingRate(a:expr, a:base_pattern)
+  endif
+  return  {
+        \   'word'  : a:expr,
+        \   'abbr'  : s:TrimLast((a:number >= 0 ? printf('%2d: ', a:number) : '') . a:abbr, a:trim_len),
+        \   'menu'  : printf('%s[%s]', (len(a:time) ? a:time . ' ' : ''), s:MakeRateStar(rate, 5)),
+        \   'ranks' : [-rate, (a:number >= 0 ? a:number : a:expr)]
+        \ }
+endfunction
+
+function! s:EvaluateMatchingRate(expr, pattern)
+  if a:expr == a:pattern
+    return s:MATCHING_RATE_BASE
+  endif
+  let rate = 0
+  let rate_increment = (s:MATCHING_RATE_BASE * 9) / (len(a:pattern) * 10) " zero divide ok
+  let matched = 1
+  let i_pattern = 0
+  for i_expr in range(len(a:expr))
+    if a:expr[i_expr] == a:pattern[i_pattern]
+      let rate += rate_increment
+      let matched = 1
+      let i_pattern += 1
+      if i_pattern >= len(a:pattern)
+        break
+      endif
+    elseif matched
+      let rate_increment = rate_increment / 2
+      let matched = 0
+    endif
+  endfor
+  return rate
+endfunction
+
+function! s:MakeRateStar(rate, base)
+  let len = (a:base * a:rate) / s:MATCHING_RATE_BASE
+  return repeat('*', len) . repeat('.', a:base - len)
+endfunction
+
+"-----------------------------------------------------------------------------
+" MISC FUNCTIONS:
+
+function! s:IsAvailableMode(mode)
+  return exists('a:mode.mode_available') && a:mode.mode_available
+endfunction
+
+function! s:GetAvailableModes()
+  return filter(values(g:FuzzyFinderMode), 's:IsAvailableMode(v:val)')
+endfunction
+
+function! s:GetSortedAvailableModes()
+  let modes = filter(items(g:FuzzyFinderMode), 's:IsAvailableMode(v:val[1])')
+  let modes = map(modes, 'extend(v:val[1], { "ranks" : [v:val[1].switch_order, v:val[0]] })')
+  return sort(modes, 's:CompareRanks')
+endfunction
+
+function! s:GetSidPrefix()
+  return matchstr(expand('<sfile>'), '<SNR>\d\+_')
+endfunction
+
+function! s:OnCmdCR()
+  for m in s:GetAvailableModes()
+    call m.extend_options()
+    call m.on_command_pre(getcmdtype() . getcmdline())
+  endfor
+  " lets last entry become the newest in the history
+  if getcmdtype() =~ '[:/=@]'
+    call histadd(getcmdtype(), getcmdline())
+  endif
+
+  " this is not mapped again (:help recursive_mapping)
+  return "\<CR>"
+endfunction
+
+function! s:ExpandAbbrevMap(base, abbrev_map)
+  let result = [a:base]
+
+  " expand
+  for [pattern, sub_list] in items(a:abbrev_map)
+    let exprs = result
+    let result = []
+    for expr in exprs
+      let result += map(copy(sub_list), 'substitute(expr, pattern, v:val, "g")')
+    endfor
+  endfor
+
+  return s:Unique(result)
+endfunction
+
+" "**" is expanded to ["**", "."]. E.g.: "foo/**/bar" -> [ "foo/./bar", "foo/**/bar" ]
+function! s:ExpandEx(dir)
+  if a:dir !~ '\S'
+    return ['']
+  endif
+
+  " [ ["foo/"], ["**/", "./" ], ["bar/"] ]
+  let lists = []
+  for i in split(a:dir, '[/\\]\zs')
+    let m = matchlist(i, '^\*\{2,}\([/\\]*\)$')
+    call add(lists, (empty(m) ? [i] : [i, '.' . m[1]]))
+  endfor
+
+  " expand wlidcards
+  return split(join(map(s:CartesianProduct(lists), 'expand(join(v:val, ""))'), "\n"), "\n")
+endfunction
+
+function! s:EnumExpandedDirsEntries(dir, excluded)
+  let dirs = s:ExpandEx(a:dir)
+  let entries = s:Concat(map(copy(dirs), 'split(glob(v:val . ".*"), "\n") + ' .
+        \                                'split(glob(v:val . "*" ), "\n")'))
+  if len(dirs) <= 1
+    call map(entries, 'extend(s:SplitPath(v:val), { "suffix" : (isdirectory(v:val) ? s:PATH_SEPARATOR : ""), "head" : a:dir })')
+  else
+    call map(entries, 'extend(s:SplitPath(v:val), { "suffix" : (isdirectory(v:val) ? s:PATH_SEPARATOR : "") })')
+  endif
+  if len(a:excluded)
+    call filter(entries, '(v:val.head . v:val.tail . v:val.suffix) !~ a:excluded')
+  endif
+  return entries
+endfunction
+
+function! s:GetTagList(tagfile)
+  return map(readfile(a:tagfile), 'matchstr(v:val, ''^[^!\t][^\t]*'')')
+endfunction
+
+function! s:GetTaggedFileList(tagfile)
+  execute 'cd ' . fnamemodify(a:tagfile, ':h')
+  let result = map(readfile(a:tagfile), 'fnamemodify(matchstr(v:val, ''^[^!\t][^\t]*\t\zs[^\t]\+''), '':p:~'')')
+  cd -
+  return result
+endfunction
+
+function! s:HighlightPrompt(prompt, highlight)
+  syntax clear
+  execute printf('syntax match %s /^\V%s/', a:highlight, escape(a:prompt, '\'))
+endfunction
+
+function! s:HighlightError()
+  syntax clear
+  syntax match Error  /^.*$/
+endfunction
+
+function! s:CompareTimeDescending(i1, i2)
+      return a:i1.time == a:i2.time ? 0 : a:i1.time > a:i2.time ? -1 : +1
+endfunction
+
+function! s:CompareRanks(i1, i2)
+  if exists('a:i1.ranks') && exists('a:i2.ranks')
+    for i in range(min([len(a:i1.ranks), len(a:i2.ranks)]))
+      if     a:i1.ranks[i] > a:i2.ranks[i]
+        return +1
+      elseif a:i1.ranks[i] < a:i2.ranks[i]
+        return -1
+      endif
+    endfor
+  endif
+  return 0
+endfunction
+
+function! s:GetCurrentTagFiles()
+  return sort(filter(map(tagfiles(), 'fnamemodify(v:val, '':p'')'), 'filereadable(v:val)'))
+endfunction
+
+" }}}1
+"=============================================================================
+" OBJECT: {{{1
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode = { 'Base' : {} }
+
+function! g:FuzzyFinderMode.Base.launch(initial_text, partial_matching, prev_bufnr, tag_files)
+  " initializes this object
+  call self.extend_options()
+  let self.partial_matching = a:partial_matching
+  let self.prev_bufnr = a:prev_bufnr
+  let self.tag_files = a:tag_files " to get local value of current buffer
+  let self.last_col = -1
+  call s:InfoFileManager.load()
+  if !s:IsAvailableMode(self)
+    echo 'This mode is not available: ' . self.to_str()
+    return
+  endif
+
+  call s:WindowManager.activate(self.make_complete_func('CompleteFunc'))
+  call s:OptionManager.set('completeopt', 'menuone')
+  call s:OptionManager.set('ignorecase', self.ignore_case)
+
+  " local autocommands
+  augroup FuzzyfinderLocal
+    autocmd!
+    execute 'autocmd CursorMovedI <buffer>        call ' . self.to_str('on_cursor_moved_i()')
+    execute 'autocmd InsertLeave  <buffer> nested call ' . self.to_str('on_insert_leave()'  )
+  augroup END
+
+  " local mapping
+  for [lhs, rhs] in [
+        \   [ self.key_open       , self.to_str('on_cr(0, 0)'            ) ],
+        \   [ self.key_open_split , self.to_str('on_cr(1, 0)'            ) ],
+        \   [ self.key_open_vsplit, self.to_str('on_cr(2, 0)'            ) ],
+        \   [ self.key_open_tab   , self.to_str('on_cr(3, 0)'            ) ],
+        \   [ '<BS>'              , self.to_str('on_bs()'                ) ],
+        \   [ '<C-h>'             , self.to_str('on_bs()'                ) ],
+        \   [ self.key_next_mode  , self.to_str('on_switch_mode(+1)'     ) ],
+        \   [ self.key_prev_mode  , self.to_str('on_switch_mode(-1)'     ) ],
+        \   [ self.key_ignore_case, self.to_str('on_switch_ignore_case()') ],
+        \ ]
+    " hacks to be able to use feedkeys().
+    execute printf('inoremap <buffer> <silent> %s <C-r>=%s ? "" : ""<CR>', lhs, rhs)
+  endfor
+
+  call self.on_mode_enter()
+
+  " Starts Insert mode and makes CursorMovedI event now. Command prompt is
+  " needed to forces a completion menu to update every typing.
+  call setline(1, self.prompt . a:initial_text)
+  call feedkeys("A", 'n') " startinsert! does not work in InsertLeave handler
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_cursor_moved_i()
+  let ln = getline('.')
+  let cl = col('.')
+  if !self.exists_prompt(ln)
+    " if command prompt is removed
+    "call setline('.', self.prompt . ln)
+    call setline('.', self.restore_prompt(ln))
+    call feedkeys(repeat("\<Right>", len(getline('.')) - len(ln)), 'n')
+  elseif cl <= len(self.prompt)
+    " if the cursor is moved before command prompt
+    call feedkeys(repeat("\<Right>", len(self.prompt) - cl + 1), 'n')
+  elseif cl > strlen(ln) && cl != self.last_col
+    " if the cursor is placed on the end of the line and has been actually moved.
+    let self.last_col = cl
+    call feedkeys("\<C-x>\<C-u>", 'n')
+  endif
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_insert_leave()
+  let text = getline('.')
+  call self.on_mode_leave()
+  call self.empty_cache_if_existed(0)
+  call s:OptionManager.restore_all()
+  call s:WindowManager.deactivate()
+
+  " switchs to next mode, or finishes fuzzyfinder.
+  if exists('s:reserved_switch_mode')
+    let m = self.next_mode(s:reserved_switch_mode < 0)
+    call m.launch(self.remove_prompt(text), self.partial_matching, self.prev_bufnr, self.tag_files)
+    unlet s:reserved_switch_mode
+  else
+    if exists('s:reserved_command')
+      call feedkeys(self.on_open(s:reserved_command[0], s:reserved_command[1]), 'n')
+      unlet s:reserved_command
+    endif
+  endif
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_buf_enter()
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_buf_write_post()
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_command_pre(cmd)
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_cr(index, check_dir)
+  if pumvisible()
+    call feedkeys(printf("\<C-y>\<C-r>=%s(%d, 1) ? '' : ''\<CR>", self.to_str('on_cr'), a:index), 'n')
+  elseif !a:check_dir || getline('.') !~ '[/\\]$'
+    let s:reserved_command = [self.remove_prompt(getline('.')), a:index]
+    call feedkeys("\<Esc>", 'n')
+  endif
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_bs()
+  let bs_count = 1
+  if self.smart_bs && col('.') > 2 && getline('.')[col('.') - 2] =~ '[/\\]'
+    let bs_count = len(matchstr(getline('.')[:col('.') - 3], '[^/\\]*$')) + 1
+  endif
+  call feedkeys((pumvisible() ? "\<C-e>" : "") . repeat("\<BS>", bs_count), 'n')
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_mode_enter()
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_mode_leave()
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_open(expr, mode)
+  return [
+        \   ':edit ',
+        \   ':split ',
+        \   ':vsplit ',
+        \   ':tabedit ',
+        \ ][a:mode] . s:EscapeFilename(a:expr) . "\<CR>"
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_switch_mode(next_prev)
+  let s:reserved_switch_mode = a:next_prev
+  call feedkeys("\<Esc>", 'n')
+endfunction
+
+function! g:FuzzyFinderMode.Base.on_switch_ignore_case()
+  let &ignorecase = !&ignorecase
+  echo "ignorecase = " . &ignorecase
+  let self.last_col = -1
+  call self.on_cursor_moved_i()
+endfunction
+
+" export string list
+function! g:FuzzyFinderMode.Base.serialize_info()
+  let header = self.to_key() . "\t"
+  return map(copy(self.info), 'header . string(v:val)')
+endfunction
+
+" import related items from string list
+function! g:FuzzyFinderMode.Base.deserialize_info(lines)
+  let header = self.to_key() . "\t"
+  let self.info = map(filter(copy(a:lines), 'v:val[: len(header) - 1] ==# header'),
+        \             'eval(v:val[len(header) :])')
+endfunction
+
+function! g:FuzzyFinderMode.Base.complete(findstart, base)
+  if a:findstart
+    return 0
+  elseif  !self.exists_prompt(a:base) || len(self.remove_prompt(a:base)) < self.min_length
+    return []
+  endif
+  call s:HighlightPrompt(self.prompt, self.prompt_highlight)
+  " FIXME: ExpandAbbrevMap duplicates index
+  let result = []
+  for expanded_base in s:ExpandAbbrevMap(self.remove_prompt(a:base), self.abbrev_map)
+    let result += self.on_complete(expanded_base)
+  endfor
+  call sort(result, 's:CompareRanks')
+  if empty(result)
+    call s:HighlightError()
+  else
+    call feedkeys("\<C-p>\<Down>", 'n')
+  endif
+  return result
+endfunction
+
+" This function is set to 'completefunc' which doesn't accept dictionary-functions.
+function! g:FuzzyFinderMode.Base.make_complete_func(name)
+  execute printf("function! s:%s(findstart, base)\n" .
+        \        "  return %s.complete(a:findstart, a:base)\n" .
+        \        "endfunction", a:name, self.to_str())
+  return s:GetSidPrefix() . a:name
+endfunction
+
+" fuzzy  : 'str' -> {'base':'str', 'wi':'*s*t*r*', 're':'\V\.\*s\.\*t\.\*r\.\*'}
+" partial: 'str' -> {'base':'str', 'wi':'*str*', 're':'\V\.\*str\.\*'}
+function! g:FuzzyFinderMode.Base.make_pattern(base)
+  if self.partial_matching
+    let wi = (a:base !~ '^[*?]'  ? '*' : '') . a:base .
+          \  (a:base =~ '[^*?]$' ? '*' : '')
+    let re = s:ConvertWildcardToRegexp(wi)
+    return { 'base': a:base, 'wi':wi, 're': re }
+  else
+    let wi = ''
+    for char in split(a:base, '\zs')
+      if wi !~ '[*?]$' && char !~ '[*?]'
+        let wi .= '*'. char
+      else
+        let wi .= char
+      endif
+    endfor
+
+    if wi !~ '[*?]$'
+      let wi .= '*'
+    endif
+
+    let re = s:ConvertWildcardToRegexp(wi)
+
+    if self.migemo_support && a:base !~ '[^\x01-\x7e]'
+      let re .= '\|\m.*' . substitute(migemo(a:base), '\\_s\*', '.*', 'g') . '.*'
+    endif
+
+    return { 'base': a:base, 'wi':wi, 're': re }
+  endif
+endfunction
+
+" glob with caching-feature, etc.
+function! g:FuzzyFinderMode.Base.glob_ex(dir, file, excluded, index, matching_limit)
+  let key = fnamemodify(a:dir, ':p')
+  call extend(self, { 'cache' : {} }, 'keep')
+  if !exists('self.cache[key]')
+    echo 'Caching file list...'
+    let self.cache[key] = s:EnumExpandedDirsEntries(key, a:excluded)
+    call s:ExtendIndexToEach(self.cache[key], 1)
+  endif
+  echo 'Filtering file list...'
+  "return map(s:FilterEx(self.cache[key], 'v:val.tail =~ ' . string(a:file), a:matching_limit),
+  return map(s:FilterMatching(self.cache[key], 'tail', a:file, a:index, a:matching_limit),
+        \ '{ "index" : v:val.index, "path" : (v:val.head == key ? a:dir : v:val.head) . v:val.tail . v:val.suffix }')
+endfunction
+
+function! g:FuzzyFinderMode.Base.glob_dir_ex(dir, file, excluded, index, matching_limit)
+  let key = fnamemodify(a:dir, ':p')
+  call extend(self, { 'cache' : {} }, 'keep')
+  if !exists('self.cache[key]')
+    echo 'Caching file list...'
+    let self.cache[key] = filter(s:EnumExpandedDirsEntries(key, a:excluded), 'len(v:val.suffix)')
+    call insert(self.cache[key], { 'head' : key, 'tail' : '..', 'suffix' : s:PATH_SEPARATOR })
+    call insert(self.cache[key], { 'head' : key, 'tail' : '.' , 'suffix' : '' })
+    call s:ExtendIndexToEach(self.cache[key], 1)
+  endif
+  echo 'Filtering file list...'
+  "return map(s:FilterEx(self.cache[key], 'v:val.tail =~ ' . string(a:file), a:matching_limit),
+  return map(s:FilterMatching(self.cache[key], 'tail', a:file, a:index, a:matching_limit),
+        \ '{ "index" : v:val.index, "path" : (v:val.head == key ? a:dir : v:val.head) . v:val.tail . v:val.suffix }')
+endfunction
+
+function! g:FuzzyFinderMode.Base.empty_cache_if_existed(force)
+  if exists('self.cache') && (a:force || !exists('self.lasting_cache') || !self.lasting_cache)
+    unlet self.cache
+    "let self.cache = (type(self.cache) == type({}) ? {} :
+    "      \           type(self.cache) == type([]) ? [] :
+    "      \           type(self.cache) == type('') ? '' : 0)
+  endif
+endfunction
+
+function! g:FuzzyFinderMode.Base.to_key()
+  return filter(keys(g:FuzzyFinderMode), 'g:FuzzyFinderMode[v:val] is self')[0]
+endfunction
+
+" returns 'g:FuzzyFinderMode.{key}{.argument}'
+function! g:FuzzyFinderMode.Base.to_str(...)
+  return 'g:FuzzyFinderMode.' . self.to_key() . (a:0 > 0 ? '.' . a:1 : '')
+endfunction
+
+" takes in g:FuzzyFinderOptions
+function! g:FuzzyFinderMode.Base.extend_options()
+  let n = filter(keys(g:FuzzyFinderMode), 'g:FuzzyFinderMode[v:val] is self')[0]
+  call extend(self, g:FuzzyFinderOptions.Base, 'force')
+  call extend(self, g:FuzzyFinderOptions[self.to_key()], 'force')
+endfunction
+
+function! g:FuzzyFinderMode.Base.next_mode(rev)
+  let modes = (a:rev ? s:GetSortedAvailableModes() : reverse(s:GetSortedAvailableModes()))
+  let m_last = modes[-1]
+  for m in modes
+    if m is self
+      break
+    endif
+    let m_last = m
+  endfor
+  return m_last
+  " vim crashed using map()
+endfunction
+
+function! g:FuzzyFinderMode.Base.exists_prompt(in)
+  return  strlen(a:in) >= strlen(self.prompt) && a:in[:strlen(self.prompt) -1] ==# self.prompt
+endfunction
+
+function! g:FuzzyFinderMode.Base.remove_prompt(in)
+  return a:in[(self.exists_prompt(a:in) ? strlen(self.prompt) : 0):]
+endfunction
+
+function! g:FuzzyFinderMode.Base.restore_prompt(in)
+  let i = 0
+  while i < len(self.prompt) && i < len(a:in) && self.prompt[i] ==# a:in[i]
+    let i += 1
+  endwhile
+  return self.prompt . a:in[i : ]
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.Buffer = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.Buffer.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
+  return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.on_open(expr, mode)
+  " attempts to convert the path to the number for handling unnamed buffer
+  return printf([
+        \   ':%sbuffer',
+        \   ':%ssbuffer',
+        \   ':vertical :%ssbuffer',
+        \   ':tab :%ssbuffer',
+        \ ][a:mode] . "\<CR>", filter(self.cache, 'v:val.path == a:expr')[0].buf_nr)
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.on_mode_enter()
+  let self.cache = map(filter(range(1, bufnr('$')), 'buflisted(v:val) && v:val != self.prev_bufnr'),
+        \              'self.make_item(v:val)')
+  if self.mru_order
+    call s:ExtendIndexToEach(sort(self.cache, 's:CompareTimeDescending'), 1)
+  endif
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.on_buf_enter()
+  call self.update_buf_times()
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.on_buf_write_post()
+  call self.update_buf_times()
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.update_buf_times()
+  if !exists('self.buf_times')
+    let self.buf_times = {}
+  endif
+  let self.buf_times[bufnr('%')] = localtime()
+endfunction
+
+function! g:FuzzyFinderMode.Buffer.make_item(nr)
+  return  {
+        \   'index'  : a:nr,
+        \   'buf_nr' : a:nr,
+        \   'path'   : empty(bufname(a:nr)) ? '[No Name]' : fnamemodify(bufname(a:nr), ':~:.'),
+        \   'time'   : (exists('self.buf_times[a:nr]') ? strftime(self.time_format, self.buf_times[a:nr]) : ''),
+        \ }
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.File = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.File.on_complete(base)
+  let base = s:ExpandTailDotSequenceToParentDir(a:base)
+  let patterns = map(s:SplitPath(base), 'self.make_pattern(v:val)')
+  let result = self.glob_ex(patterns.head.base, patterns.tail.re, self.excluded_path, s:SuffixNumber(patterns.tail.base), self.matching_limit)
+  let result = filter(result, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
+  if len(result) >= self.matching_limit
+    call s:HighlightError()
+  endif
+  return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, "", base, 1)')
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.Dir = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.Dir.on_complete(base)
+  let base = s:ExpandTailDotSequenceToParentDir(a:base)
+  let patterns = map(s:SplitPath(base), 'self.make_pattern(v:val)')
+  let result = self.glob_dir_ex(patterns.head.base, patterns.tail.re, self.excluded_path, s:SuffixNumber(patterns.tail.base), 0)
+  return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, "", base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.Dir.on_open(expr, mode)
+  return ':cd ' . escape(a:expr, ' ') . [
+        \   "\<CR>",
+        \   "",
+        \   "",
+        \   "",
+        \ ][a:mode]
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.MruFile = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.MruFile.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
+  return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.MruFile.on_mode_enter()
+  let self.cache = copy(self.info)
+  let self.cache = filter(self.cache, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
+  let self.cache = filter(self.cache, 'filereadable(v:val.path)')
+  let self.cache = map(self.cache, '{ "path" : fnamemodify(v:val.path, ":~:."), "time" : strftime(self.time_format, v:val.time) }')
+  let self.cache = s:ExtendIndexToEach(self.cache, 1)
+endfunction
+
+function! g:FuzzyFinderMode.MruFile.on_buf_enter()
+  call self.update_info()
+endfunction
+
+function! g:FuzzyFinderMode.MruFile.on_buf_write_post()
+  call self.update_info()
+endfunction
+
+function! g:FuzzyFinderMode.MruFile.update_info()
+  "if !empty(&buftype) || !filereadable(expand('%'))
+  if !empty(&buftype)
+    return
+  endif
+  call s:InfoFileManager.load()
+  let self.info = s:UpdateMruList(self.info, { 'path' : expand('%:p'), 'time' : localtime() },
+        \                         'path', self.max_item, self.excluded_path)
+  call s:InfoFileManager.save()
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.MruCmd = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.MruCmd.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  let result = s:FilterMatching(self.cache, 'command', patterns.re, s:SuffixNumber(patterns.base), 0)
+  return map(result, 's:FormatCompletionItem(v:val.command, v:val.index, v:val.command, self.trim_length, v:val.time, a:base, 0)')
+endfunction
+
+function! g:FuzzyFinderMode.MruCmd.on_open(expr, mode)
+  redraw
+  " use feedkeys to remap <CR>
+  return a:expr . [
+        \   "\<C-r>=feedkeys(\"\\<CR>\", 'm')?'':''\<CR>",
+        \   "",
+        \   "",
+        \   "",
+        \ ][a:mode]
+endfunction
+
+function! g:FuzzyFinderMode.MruCmd.on_mode_enter()
+  let self.cache = s:ExtendIndexToEach(map(copy(self.info),
+        \ '{ "command" : v:val.command, "time" : strftime(self.time_format, v:val.time) }'), 1)
+endfunction
+
+function! g:FuzzyFinderMode.MruCmd.on_command_pre(cmd)
+  call self.update_info(a:cmd)
+endfunction
+
+function! g:FuzzyFinderMode.MruCmd.update_info(cmd)
+  call s:InfoFileManager.load()
+  let self.info = s:UpdateMruList(self.info, { 'command' : a:cmd, 'time' : localtime() },
+        \                         'command', self.max_item, self.excluded_command)
+  call s:InfoFileManager.save()
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.FavFile = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.FavFile.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  let result = s:FilterMatching(self.cache, 'path', patterns.re, s:SuffixNumber(patterns.base), 0)
+  return map(result, 's:FormatCompletionItem(v:val.path, v:val.index, v:val.path, self.trim_length, v:val.time, a:base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.FavFile.on_mode_enter()
+  let self.cache = copy(self.info)
+  let self.cache = filter(self.cache, 'bufnr("^" . v:val.path . "$") != self.prev_bufnr')
+  let self.cache = map(self.cache, '{ "path" : fnamemodify(v:val.path, ":~:."), "time" : strftime(self.time_format, v:val.time) }')
+  let self.cache = s:ExtendIndexToEach(self.cache, 1)
+endfunction
+
+function! g:FuzzyFinderMode.FavFile.add(in_file, adds)
+  call s:InfoFileManager.load()
+
+  let file = fnamemodify((empty(a:in_file) ? expand('%') : a:in_file), ':p:~')
+
+  call filter(self.info, 'v:val.path != file')
+  if a:adds
+    call add(self.info, { 'path' : file, 'time' : localtime() })
+  endif
+
+  call s:InfoFileManager.save()
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.Tag = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.Tag.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  let result = self.find_tag(patterns.re, self.matching_limit)
+  if len(result) >= self.matching_limit
+    call s:HighlightError()
+  endif
+  return map(result, 's:FormatCompletionItem(v:val, -1, v:val, self.trim_length, "", a:base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.Tag.on_open(expr, mode)
+  return [
+        \   ':tjump ',
+        \   ':stjump ',
+        \   ':vertical :stjump ',
+        \   ':tab :stjump ',
+        \ ][a:mode] . a:expr . "\<CR>"
+endfunction
+
+function! g:FuzzyFinderMode.Tag.find_tag(pattern, matching_limit)
+  if !len(self.tag_files)
+    return []
+  endif
+
+  let key = join(self.tag_files, "\n")
+
+  " cache not created or tags file updated? 
+  call extend(self, { 'cache' : {} }, 'keep')
+  if !exists('self.cache[key]') || max(map(copy(self.tag_files), 'getftime(v:val) >= self.cache[key].time'))
+    echo 'Caching tag list...'
+    let self.cache[key] = {
+          \   'time' : localtime(),
+          \   'data' : s:Unique(s:Concat(map(copy(self.tag_files), 's:GetTagList(v:val)'))),
+          \ }
+  endif
+
+  echo 'Filtering tag list...'
+  return s:FilterEx(self.cache[key].data, 'v:val =~ ' . string(a:pattern), a:matching_limit)
+endfunction
+
+"-----------------------------------------------------------------------------
+let g:FuzzyFinderMode.TaggedFile = copy(g:FuzzyFinderMode.Base)
+
+function! g:FuzzyFinderMode.TaggedFile.on_complete(base)
+  let patterns = self.make_pattern(a:base)
+  echo 'Making tagged file list...'
+  let result = self.find_tagged_file(patterns.re, self.matching_limit)
+  if len(result) >= self.matching_limit
+    call s:HighlightError()
+  endif
+  return map(result, 's:FormatCompletionItem(v:val, -1, v:val, self.trim_length, "", a:base, 1)')
+endfunction
+
+function! g:FuzzyFinderMode.TaggedFile.find_tagged_file(pattern, matching_limit)
+  if !len(self.tag_files)
+    return []
+  endif
+
+  let key = join(self.tag_files, "\n")
+
+  " cache not created or tags file updated? 
+  call extend(self, { 'cache' : {} }, 'keep')
+  if !exists('self.cache[key]') || max(map(copy(self.tag_files), 'getftime(v:val) >= self.cache[key].time'))
+    echo 'Caching tagged-file list...'
+    let self.cache[key] = {
+          \   'time' : localtime(),
+          \   'data' : s:Unique(s:Concat(map(copy(self.tag_files), 's:GetTaggedFileList(v:val)'))),
+          \ }
+  endif
+
+  echo 'Filtering tagged-file list...'
+  return s:FilterEx(map(self.cache[key].data, 'fnamemodify(v:val, '':.'')'),
+        \               'v:val =~ ' . string(a:pattern),
+        \           a:matching_limit)
+
+endfunction
+
+"-----------------------------------------------------------------------------
+" sets or restores temporary options
+let s:OptionManager = { 'originals' : {} }
+
+function! s:OptionManager.set(name, value)
+  call extend(self.originals, { a:name : eval('&' . a:name) }, 'keep')
+  execute printf('let &%s = a:value', a:name)
+endfunction
+
+function! s:OptionManager.restore_all()
+  for [name, value] in items(self.originals)
+    execute printf('let &%s = value', name)
+  endfor
+  let self.originals = {}
+endfunction
+
+"-----------------------------------------------------------------------------
+" manages buffer/window for fuzzyfinder
+let s:WindowManager = { 'buf_nr' : -1 }
+
+function! s:WindowManager.activate(complete_func)
+  let self.prev_winnr = winnr()
+  let cwd = getcwd()
+
+  if !bufexists(self.buf_nr)
+    leftabove 1new
+    file `='[Fuzzyfinder]'`
+    let self.buf_nr = bufnr('%')
+  elseif bufwinnr(self.buf_nr) == -1
+    leftabove 1split
+    execute self.buf_nr . 'buffer'
+    delete _
+  elseif bufwinnr(self.buf_nr) != bufwinnr('%')
+    execute bufwinnr(self.buf_nr) . 'wincmd w'
+  endif
+
+  " countermeasure for auto-cd script
+  execute ':lcd ' . cwd
+
+  setlocal filetype=fuzzyfinder
+  setlocal bufhidden=delete
+  setlocal buftype=nofile
+  setlocal noswapfile
+  setlocal nobuflisted
+  setlocal modifiable
+  setlocal nocursorline   " for highlighting
+  setlocal nocursorcolumn " for highlighting
+  let &l:completefunc = a:complete_func
+
+  redraw " for 'lazyredraw'
+
+  " suspend autocomplpop.vim
+  if exists(':AutoComplPopLock')
+    :AutoComplPopLock
+  endif
+endfunction
+
+function! s:WindowManager.deactivate()
+  " resume autocomplpop.vim
+  if exists(':AutoComplPopUnlock')
+    :AutoComplPopUnlock
+  endif
+
+  close
+  execute self.prev_winnr . 'wincmd w'
+endfunction
+
+"-----------------------------------------------------------------------------
+let s:InfoFileManager = { 'originals' : {} }
+
+function! s:InfoFileManager.load()
+  for m in s:GetAvailableModes()
+    let m.info = []
+  endfor
+
+  try
+    let lines = readfile(expand(self.get_info_file()))
+  catch /.*/ 
+    return
+  endtry
+
+  " compatibility check
+  if !count(lines, self.get_info_version_line())
+      call self.warn_old_info()
+      let g:FuzzyFinderOptions.Base.info_file = ''
+      return
+  endif
+
+  for m in s:GetAvailableModes()
+    call m.deserialize_info(lines)
+  endfor
+endfunction
+
+function! s:InfoFileManager.save()
+  let lines = [ self.get_info_version_line() ]
+  for m in s:GetAvailableModes()
+    let lines += m.serialize_info()
+  endfor
+
+  try
+    call writefile(lines, expand(self.get_info_file()))
+  catch /.*/ 
+  endtry
+endfunction
+
+function! s:InfoFileManager.edit()
+
+  new
+  file `='[FuzzyfinderInfo]'`
+  let self.bufnr = bufnr('%')
+
+  setlocal filetype=vim
+  setlocal bufhidden=delete
+  setlocal buftype=acwrite
+  setlocal noswapfile
+
+  augroup FuzzyfinderInfo
+    autocmd!
+    autocmd BufWriteCmd <buffer> call s:InfoFileManager.on_buf_write_cmd()
+  augroup END
+
+  execute '0read ' . expand(self.get_info_file())
+  setlocal nomodified
+
+endfunction
+
+function! s:InfoFileManager.on_buf_write_cmd()
+  for m in s:GetAvailableModes()
+    call m.deserialize_info(getline(1, '$'))
+  endfor
+  call self.save()
+  setlocal nomodified
+  execute printf('%dbdelete! ', self.bufnr)
+  echo "Information file updated"
+endfunction
+
+function! s:InfoFileManager.get_info_version_line()
+  return "VERSION\t206"
+endfunction
+
+function! s:InfoFileManager.get_info_file()
+  return g:FuzzyFinderOptions.Base.info_file
+endfunction
+
+function! s:InfoFileManager.warn_old_info()
+  echohl WarningMsg
+  echo printf("==================================================\n" .
+      \       "  Your Fuzzyfinder information file is no longer  \n" .
+      \       "  supported. Please remove                        \n" .
+      \       "  %-48s\n" .
+      \       "==================================================\n" ,
+      \       '"' . expand(self.get_info_file()) . '".')
+  echohl None
+endfunction
+
+" }}}1
+"=============================================================================
+" GLOBAL OPTIONS: {{{1
+" stores user-defined g:FuzzyFinderOptions ------------------------------ {{{2
+let user_options = (exists('g:FuzzyFinderOptions') ? g:FuzzyFinderOptions : {})
+" }}}2
+
+" Initializes g:FuzzyFinderOptions.
+let g:FuzzyFinderOptions = { 'Base':{}, 'Buffer':{}, 'File':{}, 'Dir':{}, 'MruFile':{}, 'MruCmd':{}, 'FavFile':{}, 'Tag':{}, 'TaggedFile':{}}
+"-----------------------------------------------------------------------------
+" [All Mode] This is mapped to select completion item or finish input and
+" open a buffer/file in previous window.
+let g:FuzzyFinderOptions.Base.key_open = '<CR>'
+" [All Mode] This is mapped to select completion item or finish input and
+" open a buffer/file in split new window
+let g:FuzzyFinderOptions.Base.key_open_split = '<C-j>'
+" [All Mode] This is mapped to select completion item or finish input and
+" open a buffer/file in vertical-split new window.
+let g:FuzzyFinderOptions.Base.key_open_vsplit = '<C-k>'
+" [All Mode] This is mapped to select completion item or finish input and
+" open a buffer/file in a new tab page.
+let g:FuzzyFinderOptions.Base.key_open_tab = '<C-]>'
+" [All Mode] This is mapped to switch to the next mode.
+let g:FuzzyFinderOptions.Base.key_next_mode = '<C-l>'
+" [All Mode] This is mapped to switch to the previous mode.
+let g:FuzzyFinderOptions.Base.key_prev_mode = '<C-o>'
+" [All Mode] This is mapped to temporarily switch whether or not to ignore
+" case.
+let g:FuzzyFinderOptions.Base.key_ignore_case = '<C-t>'
+" [All Mode] This is the file name to write information of the MRU, etc. If
+" "" was set, Fuzzyfinder does not write to the file.
+let g:FuzzyFinderOptions.Base.info_file = '~/.vimfuzzyfinder'
+" [All Mode] Fuzzyfinder does not start a completion if a length of entered
+" text is less than this.
+let g:FuzzyFinderOptions.Base.min_length = 0
+" [All Mode] This is a dictionary. Each value must be a list. All matchs of a
+" key in entered text is expanded with the value.
+let g:FuzzyFinderOptions.Base.abbrev_map = {}
+" [All Mode] Fuzzyfinder ignores case in search patterns if non-zero is set.
+let g:FuzzyFinderOptions.Base.ignore_case = 1
+" [All Mode] This is a string to format time string. See :help strftime() for
+" details.
+let g:FuzzyFinderOptions.Base.time_format = '(%x %H:%M:%S)'
+" [All Mode] If a length of completion item is more than this, it is trimmed
+" when shown in completion menu.
+let g:FuzzyFinderOptions.Base.trim_length = 80
+" [All Mode] Fuzzyfinder does not remove caches of completion lists at the end
+" of explorer to reuse at the next time if non-zero was set.
+let g:FuzzyFinderOptions.Base.lasting_cache = 1
+" [All Mode] Fuzzyfinder uses Migemo if non-zero is set.
+let g:FuzzyFinderOptions.Base.migemo_support = 0
+"-----------------------------------------------------------------------------
+" [Buffer Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.Buffer.mode_available = 1
+" [Buffer Mode] The prompt string.
+let g:FuzzyFinderOptions.Buffer.prompt = '>Buffer>'
+" [Buffer Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.Buffer.prompt_highlight = 'Question'
+" [Buffer Mode] Pressing <BS> after a path separator deletes one directory
+" name if non-zero is set.
+let g:FuzzyFinderOptions.Buffer.smart_bs = 1
+" [Buffer Mode] The completion items is sorted in the order of recently used
+" if non-zero is set.
+let g:FuzzyFinderOptions.Buffer.mru_order = 1
+" [Buffer Mode] This is used to sort modes for switching to the next/previous
+" mode.
+let g:FuzzyFinderOptions.Buffer.switch_order = 10
+"-----------------------------------------------------------------------------
+" [File Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.File.mode_available = 1
+" [File Mode] The prompt string.
+let g:FuzzyFinderOptions.File.prompt = '>File>'
+" [File Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.File.prompt_highlight = 'Question'
+" [File Mode] Pressing <BS> after a path separator deletes one directory name
+" if non-zero is set.
+let g:FuzzyFinderOptions.File.smart_bs = 1
+" [File Mode] This is used to sort modes for switching to the next/previous
+" mode.
+let g:FuzzyFinderOptions.File.switch_order = 20
+" [File Mode] The items matching this are excluded from the completion list.
+let g:FuzzyFinderOptions.File.excluded_path = '\v\~$|\.o$|\.exe$|\.bak$|\.swp$|((^|[/\\])\.[/\\]$)'
+" [File Mode] If a number of matched items was over this, the completion
+" process is aborted.
+let g:FuzzyFinderOptions.File.matching_limit = 200
+"-----------------------------------------------------------------------------
+" [Directory Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.Dir.mode_available = 1
+" [Directory Mode] The prompt string.
+let g:FuzzyFinderOptions.Dir.prompt = '>Dir>'
+" [Directory Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.Dir.prompt_highlight = 'Question'
+" [Directory Mode] Pressing <BS> after a path separator deletes one directory
+" name if non-zero is set.
+let g:FuzzyFinderOptions.Dir.smart_bs = 1
+" [Directory Mode] This is used to sort modes for switching to the
+" next/previous mode.
+let g:FuzzyFinderOptions.Dir.switch_order = 30
+" [Directory Mode] The items matching this are excluded from the completion
+" list.
+let g:FuzzyFinderOptions.Dir.excluded_path = '\v(^|[/\\])\.{1,2}[/\\]$'
+"-----------------------------------------------------------------------------
+" [Mru-File Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.MruFile.mode_available = 1
+" [Mru-File Mode] The prompt string.
+let g:FuzzyFinderOptions.MruFile.prompt = '>MruFile>'
+" [Mru-File Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.MruFile.prompt_highlight = 'Question'
+" [Mru-File Mode] Pressing <BS> after a path separator deletes one directory
+" name if non-zero is set.
+let g:FuzzyFinderOptions.MruFile.smart_bs = 1
+" [Mru-File Mode] This is used to sort modes for switching to the
+" next/previous mode.
+let g:FuzzyFinderOptions.MruFile.switch_order = 40
+" [Mru-File Mode] The items matching this are excluded from the completion
+" list.
+let g:FuzzyFinderOptions.MruFile.excluded_path = '\v\~$|\.bak$|\.swp$'
+" [Mru-File Mode] This is an upper limit of MRU items to be stored.
+let g:FuzzyFinderOptions.MruFile.max_item = 99
+"-----------------------------------------------------------------------------
+" [Mru-Cmd Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.MruCmd.mode_available = 1
+" [Mru-Cmd Mode] The prompt string.
+let g:FuzzyFinderOptions.MruCmd.prompt = '>MruCmd>'
+" [Mru-Cmd Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.MruCmd.prompt_highlight = 'Question'
+" [Mru-Cmd Mode] Pressing <BS> after a path separator deletes one directory
+" name if non-zero is set.
+let g:FuzzyFinderOptions.MruCmd.smart_bs = 0
+" [Mru-Cmd Mode] This is used to sort modes for switching to the next/previous
+" mode.
+let g:FuzzyFinderOptions.MruCmd.switch_order = 50
+" [Mru-Cmd Mode] The items matching this are excluded from the completion
+" list.
+let g:FuzzyFinderOptions.MruCmd.excluded_command = '^$'
+" [Mru-Cmd Mode] This is an upper limit of MRU items to be stored.
+let g:FuzzyFinderOptions.MruCmd.max_item = 99
+"-----------------------------------------------------------------------------
+" [Favorite-File Mode] This disables all functions of this mode if zero was
+" set.
+let g:FuzzyFinderOptions.FavFile.mode_available = 1
+" [Favorite-File Mode] The prompt string.
+let g:FuzzyFinderOptions.FavFile.prompt = '>FavFile>'
+" [Favorite-File Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.FavFile.prompt_highlight = 'Question'
+" [Favorite-File Mode] Pressing <BS> after a path separator deletes one
+" directory name if non-zero is set.
+let g:FuzzyFinderOptions.FavFile.smart_bs = 1
+" [Favorite-File Mode] This is used to sort modes for switching to the
+" next/previous mode.
+let g:FuzzyFinderOptions.FavFile.switch_order = 60
+"-----------------------------------------------------------------------------
+" [Tag Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.Tag.mode_available = 1
+" [Tag Mode] The prompt string.
+let g:FuzzyFinderOptions.Tag.prompt = '>Tag>'
+" [Tag Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.Tag.prompt_highlight = 'Question'
+" [Tag Mode] Pressing <BS> after a path separator deletes one directory name
+" if non-zero is set.
+let g:FuzzyFinderOptions.Tag.smart_bs = 0
+" [Tag Mode] This is used to sort modes for switching to the next/previous
+" mode.
+let g:FuzzyFinderOptions.Tag.switch_order = 70
+" [Tag Mode] The items matching this are excluded from the completion list.
+let g:FuzzyFinderOptions.Tag.excluded_path = '\v\~$|\.bak$|\.swp$'
+" [Tag Mode] If a number of matched items was over this, the completion
+" process is aborted.
+let g:FuzzyFinderOptions.Tag.matching_limit = 200
+"-----------------------------------------------------------------------------
+" [Tagged-File Mode] This disables all functions of this mode if zero was set.
+let g:FuzzyFinderOptions.TaggedFile.mode_available = 1
+" [Tagged-File Mode] The prompt string.
+let g:FuzzyFinderOptions.TaggedFile.prompt = '>TaggedFile>'
+" [Tagged-File Mode] The highlight group name for a prompt string.
+let g:FuzzyFinderOptions.TaggedFile.prompt_highlight = 'Question'
+" [Tagged-File Mode] Pressing <BS> after a path separator deletes one
+" directory name if non-zero is set.
+let g:FuzzyFinderOptions.TaggedFile.smart_bs = 0
+" [Tagged-File Mode] This is used to sort modes for switching to the
+" next/previous mode.
+let g:FuzzyFinderOptions.TaggedFile.switch_order = 80
+" [Tagged-File Mode] If a number of matched items was over this, the
+" completion process is aborted.
+let g:FuzzyFinderOptions.TaggedFile.matching_limit = 200
+
+" overwrites default values of g:FuzzyFinderOptions with user-defined values - {{{2
+call map(user_options, 'extend(g:FuzzyFinderOptions[v:key], v:val, ''force'')')
+call map(copy(g:FuzzyFinderMode), 'v:val.extend_options()')
+" }}}2
+
+" }}}1
+"=============================================================================
+" COMMANDS/AUTOCOMMANDS/MAPPINGS/ETC.: {{{1
+
+let s:PATH_SEPARATOR = (has('win32') || has('win64') ? '\' : '/')
+let s:MATCHING_RATE_BASE = 10000000
+let s:ABBR_TRIM_MARK = '...'
+
+augroup FuzzyfinderGlobal
+  autocmd!
+  autocmd BufEnter     * for m in s:GetAvailableModes() | call m.extend_options() | call m.on_buf_enter() | endfor
+  autocmd BufWritePost * for m in s:GetAvailableModes() | call m.extend_options() | call m.on_buf_write_post() | endfor
+augroup END
+
+" cnoremap has a problem, which doesn't expand cabbrev.
+cmap <silent> <expr> <CR> <SID>OnCmdCR()
+
+command! -bang -narg=? -complete=buffer FuzzyFinderBuffer      call g:FuzzyFinderMode.Buffer.launch    (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderFile        call g:FuzzyFinderMode.File.launch      (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=dir    FuzzyFinderDir         call g:FuzzyFinderMode.Dir.launch       (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderMruFile     call g:FuzzyFinderMode.MruFile.launch   (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderMruCmd      call g:FuzzyFinderMode.MruCmd.launch    (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderFavFile     call g:FuzzyFinderMode.FavFile.launch   (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=tag    FuzzyFinderTag         call g:FuzzyFinderMode.Tag.launch       (<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderTaggedFile  call g:FuzzyFinderMode.TaggedFile.launch(<q-args>, len(<q-bang>), bufnr('%'), s:GetCurrentTagFiles())
+command! -bang -narg=? -complete=file   FuzzyFinderEditInfo    call s:InfoFileManager.edit()
+command! -bang -narg=? -complete=file   FuzzyFinderAddFavFile  call g:FuzzyFinderMode.FavFile.add(<q-args>, 1)
+command! -bang -narg=0                  FuzzyFinderRemoveCache for m in s:GetAvailableModes() | call m.empty_cache_if_existed(1) | endfor
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker: