Commits

Takeshi NISHIDA committed 34f99db

Added :FufEditDataFile command and removed :FufEditInfo command. Improved the way to add modes.

Comments (0)

Files changed (13)

 endfunction
 
 "
+function s:onCommandPre()
+  for m in filter(copy(fuf#getModeNames()), 'fuf#{v:val}#requiresOnCommandPre()')
+      call fuf#{m}#onCommandPre(getcmdtype() . getcmdline())
+  endfor
+  " lets last entry become the newest in the history
+  call histadd(getcmdtype(), getcmdline())
+  " this is not mapped again (:help recursive_mapping)
+  return "\<CR>"
+endfunction
+
+"
+let s:modeNames = []
+
+"
+function fuf#addMode(modeName)
+  if count(g:fuf_modesDisable, a:modeName) > 0
+    return
+  endif
+  call add(s:modeNames, a:modeName)
+  call fuf#{a:modeName}#renewCache()
+  call fuf#{a:modeName}#onInit()
+  if fuf#{a:modeName}#requiresOnCommandPre()
+    " cnoremap has a problem, which doesn't expand cabbrev.
+    cmap <silent> <expr> <CR> <SID>onCommandPre()
+  endif
+endfunction
+
+"
+function fuf#getModeNames()
+  return s:modeNames
+endfunction
+
+"
 function fuf#defineLaunchCommand(CmdName, modeName, prefixInitialPattern)
   execute printf('command! -bang -narg=? %s call fuf#launch(%s, %s . <q-args>, len(<q-bang>))',
         \        a:CmdName, string(a:modeName), a:prefixInitialPattern)
   if exists('s:runningHandler')
     call fuf#echoWarning('FuzzyFinder is running.')
   endif
-  if count(g:fuf_modes, a:modeName) == 0
+  if count(fuf#getModeNames(), a:modeName) == 0
     echoerr 'This mode is not available: ' . a:modeName
     return
   endif
   let s:runningHandler = fuf#{a:modeName}#createHandler(copy(s:handlerBase))
-  let s:runningHandler.stats = fuf#loadStats(s:runningHandler.getModeName())
+  let s:runningHandler.stats = fuf#loadDataFile(s:runningHandler.getModeName(), 'stats')
   let s:runningHandler.partialMatching = a:partialMatching
   let s:runningHandler.bufNrPrev = bufnr('%')
   let s:runningHandler.lastCol = -1
 endfunction
 
 "
-function fuf#loadDataLines(pathSuffixes)
+function fuf#loadDataFile(modeName, dataName)
   if !s:dataFileAvailable
     return []
   endif
-  return l9#readFile(l9#concatPaths([g:fuf_dataDir] + a:pathSuffixes))
-endfunction
-
-" 
-function fuf#saveDataLines(pathSuffixes, lines)
-  if !s:dataFileAvailable
-    return
-  endif
-  call l9#writeFile(a:lines, l9#concatPaths([g:fuf_dataDir] + a:pathSuffixes))
-endfunction
-
-"
-function fuf#loadItems(modeName)
-  let lines = fuf#loadDataLines([a:modeName, 'items'])
+  let lines = l9#readFile(l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName]))
   return map(lines, 'eval(v:val)')
 endfunction
 
 " 
-function fuf#saveItems(modeName, items)
+function fuf#saveDataFile(modeName, dataName, items)
+  if !s:dataFileAvailable
+    return -1
+  endif
   let lines = map(copy(a:items), 'string(v:val)')
-  call fuf#saveDataLines([a:modeName, 'items'], lines)
+  return l9#writeFile(lines, l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName]))
+endfunction
+
+" 
+function fuf#getDataFileTime(modeName, dataName)
+  if !s:dataFileAvailable
+    return -1
+  endif
+  return getftime(expand(l9#concatPaths([g:fuf_dataDir, a:modeName, a:dataName])))
 endfunction
 
 "
-function fuf#loadStats(modeName)
-  let lines = fuf#loadDataLines([a:modeName, 'stats'])
-  return map(lines, 'eval(v:val)')
-endfunction
+function s:createDataBufferListener(modeName)
+  let listener = { 'modeName': a:modeName }
 
-" 
-function fuf#saveStats(modeName, stats)
-  let lines = map(copy(a:stats), 'string(v:val)')
-  call fuf#saveDataLines([a:modeName, 'stats'], lines)
+  function listener.onWrite(lines)
+    call fuf#saveDataFile(self.modeName, 'items', map(a:lines, 'eval(v:val)'))
+    echo "Data files updated"
+    return 1
+  endfunction
+
+  return listener
 endfunction
 
 "
-function fuf#editInfoFile()
-  "TODO
-  throw 'TODO'
-  "let lines = l9#readFile(g:fuf_infoFile)
-  "call l9#tempbuffer#open('[fuf-info]', 'vim', lines, 0, 0, 0, 1,
-  "      \                 s:infoBufferListener)
+function s:createEditDataListener()
+  let listener = {}
+
+  function listener.onComplete(modeName, method)
+    let bufName = '[fuf-info-' . a:modeName . ']'
+    let lines = l9#readFile(l9#concatPaths([g:fuf_dataDir, a:modeName, 'items']))
+    call l9#tempbuffer#open(bufName, 'vim', lines, 0, 0, 0, 1,
+          \                 s:createDataBufferListener(a:modeName))
+  endfunction
+
+  return listener
+endfunction
+
+"
+function fuf#editDataFile()
+  let modes = filter(copy(fuf#getModeNames()), 'fuf#getDataFileTime(v:val, "items") != -1')
+  call fuf#callbackitem#launch('', 0, '>Mode>', s:createEditDataListener(), modes, 0)
 endfunction
 
 " 
   unlet s:runningHandler
   call l9#tempvariables#swap(s:TEMP_VARIABLES_GROUP)
   call s:deactivateFufBuffer()
-  call fuf#saveStats(self.getModeName(), self.stats)
+  call fuf#saveDataFile(self.getModeName(), 'stats', self.stats)
   execute self.windowRestoringCommand
   let fOpen = exists('s:reservedCommand')
   if fOpen
 
 "
 function s:handlerBase.onSwitchMode(shift)
-  let modes = copy(g:fuf_modes)
+  let modes = copy(fuf#getModeNames())
   call map(modes, '{ "ranks": [ fuf#{v:val}#getSwitchOrder(), v:val ] }')
   call filter(modes, 'v:val.ranks[0] >= 0')
   call sort(modes, 'fuf#compareRanks')
 
 " }}}1
 "=============================================================================
-" s:infoBufferListener {{{1
-
-"
-let s:infoBufferListener = {}
-
-"
-function s:infoBufferListener.onWrite(lines)
-  "TODO
-  throw 'TODO'
-  "call fuf#saveInfoFile('', s:deserializeInfoMap(a:lines))
-  "echo "Information file updated"
-  "return 1
-endfunction
-
-
-" }}}1
-"=============================================================================
 " INITIALIZATION {{{1
 
 augroup FufGlobal
     let s:dataFileAvailable = 1
   else
     call fuf#echoWarning(printf(
-          \ "==============================================================\n" .
-          \ "  Existing data files for FuzzyFinder is no longer            \n" .
-          \ "  compatible with this version of FuzzyFinder. Please remove  \n" .
-          \ "  %-60s\n" .
-          \ "==============================================================\n" ,
+          \ "=======================================================\n" .
+          \ "  Existing data files for FuzzyFinder is no longer     \n" .
+          \ "  compatible with this version of FuzzyFinder. Remove  \n" .
+          \ "  %-53s\n" .
+          \ "=======================================================\n" ,
           \ string(g:fuf_dataDir)))
     call l9#inputHl('Question', 'Press Enter')
     let s:dataFileAvailable = 0

autoload/fuf/aroundmrufile.vim

   if !empty(&buftype) || !filereadable(expand('%'))
     return
   endif
-  let items = fuf#loadItems(s:MODE_NAME)
+  let items = fuf#loadDataFile(s:MODE_NAME, 'items')
   let items = fuf#updateMruList(
         \ items, { 'word' : expand('%:p:h') },
         \ g:fuf_aroundmrufile_maxDir, g:fuf_aroundmrufile_exclude)
-  call fuf#saveItems(s:MODE_NAME, items)
+  call fuf#saveDataFile(s:MODE_NAME, 'items', items)
 endfunction
 
 "
 function s:handler.onModeEnterPost()
   " NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
   let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~')
-  let self.items = fuf#loadItems(s:MODE_NAME)
+  let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
   call map(self.items, 's:listFilesUsingCache(v:val.word)')
   let self.items = l9#concat(self.items)
   call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')

autoload/fuf/bookmark.vim

     call fuf#echoWarning('Canceled')
     return
   endif
-  let items = fuf#loadItems(s:MODE_NAME)
+  let items = fuf#loadDataFile(s:MODE_NAME, 'items')
   call insert(items, item)
-  call fuf#saveItems(s:MODE_NAME, items)
+  call fuf#saveDataFile(s:MODE_NAME, 'items', items)
 endfunction
 
 "
 
 "
 function s:handler.makePreviewLines(word, count)
-  let item = s:findItem(fuf#loadItems(s:MODE_NAME), a:word)
+  let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
   let lines = fuf#getFileLines(item.path)
   if empty(lines)
     return []
 "
 function s:handler.onOpen(word, mode)
   if a:mode ==# s:OPEN_TYPE_DELETE
-    let items = fuf#loadItems(s:MODE_NAME)
+    let items = fuf#loadDataFile(s:MODE_NAME, 'items')
     call filter(items, 'v:val.word !=# a:word')
-    call fuf#saveItems(s:MODE_NAME, items)
+    call fuf#saveDataFile(s:MODE_NAME, 'items', items)
     let self.reservedMode = self.getModeName()
     return
   else
-    let item = s:findItem(fuf#loadItems(s:MODE_NAME), a:word)
+    let item = s:findItem(fuf#loadDataFile(s:MODE_NAME, 'items'), a:word)
     if !empty(item)
         call s:jumpToBookmark(item.path, a:mode, item.pattern, item.lnum)
     endif
 function s:handler.onModeEnterPost()
   call fuf#defineKeyMappingInHandler(g:fuf_bookmark_keyDelete,
         \                            'onCr(' . s:OPEN_TYPE_DELETE . ', 0)')
-  let self.items = fuf#loadItems(s:MODE_NAME)
+  let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
   call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
   call fuf#mapToSetSerialIndex(self.items, 1)
   call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')

autoload/fuf/callbackfile.vim

 
 "
 function s:handler.onModeLeavePost(opened)
-  if !a:opened
+  if !a:opened && exists('s:listener.onAbort()')
     call s:listener.onAbort()
   endif
 endfunction

autoload/fuf/callbackitem.vim

 
 "
 function s:handler.onModeLeavePost(opened)
-  if !a:opened
+  if !a:opened && exists('s:listener.onAbort()')
     call s:listener.onAbort()
   endif
 endfunction

autoload/fuf/help.vim

 
 "
 function s:parseHelpTagFiles(tagFiles, key)
-  if !empty(g:fuf_help_cache_dir)
-    " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists.
-    let cacheFile = fnamemodify(g:fuf_help_cache_dir, ':p') . l9#hash224(a:key)
-    if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0
-      return map(l9#readFile(cacheFile), 'eval(v:val)')
-    endif
+  let cacheName = 'cache-' . l9#hash224(a:key)
+  let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
+  if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
+    return fuf#loadDataFile(s:MODE_NAME, cacheName)
   endif
   let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getHelpTagEntries(v:val)')))
   let items = map(items, 'extend(v:val, fuf#makeNonPathItem(v:val.word, ""))')
   call fuf#mapToSetSerialIndex(items, 1)
   let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
-  if !empty(g:fuf_help_cache_dir)
-    call l9#writeFile(map(copy(items), 'string(v:val)'), cacheFile)
-  endif
+  call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
   return items
 endfunction
 

autoload/fuf/mrucmd.vim

 
 "
 function s:updateInfo(cmd)
-  let items = fuf#loadItems(s:MODE_NAME)
+  let items = fuf#loadDataFile(s:MODE_NAME, 'items')
   let items = fuf#updateMruList(
         \ items, { 'word' : a:cmd, 'time' : localtime() },
         \ g:fuf_mrucmd_maxItem, g:fuf_mrucmd_exclude)
-  call fuf#saveItems(s:MODE_NAME, items)
+  call fuf#saveDataFile(s:MODE_NAME, 'items', items)
 endfunction
 
 " }}}1
 
 "
 function s:handler.onModeEnterPost()
-  let self.items = fuf#loadItems(s:MODE_NAME)
+  let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
   call map(self.items, 'fuf#makeNonPathItem(v:val.word, strftime(g:fuf_timeFormat, v:val.time))')
   call fuf#mapToSetSerialIndex(self.items, 1)
   call map(self.items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')

autoload/fuf/mrufile.vim

   if !empty(&buftype) || !filereadable(expand('%'))
     return
   endif
-  let items = fuf#loadItems(s:MODE_NAME)
+  let items = fuf#loadDataFile(s:MODE_NAME, 'items')
   let items = fuf#updateMruList(
         \ items, { 'word' : expand('%:p'), 'time' : localtime() },
         \ g:fuf_mrufile_maxItem, g:fuf_mrufile_exclude)
-  call fuf#saveItems(s:MODE_NAME, items)
+  call fuf#saveDataFile(s:MODE_NAME, 'items', items)
   call s:removeItemFromCache(expand('%:p'))
 endfunction
 
 function s:handler.onModeEnterPost()
   " NOTE: Comparing filenames is faster than bufnr('^' . fname . '$')
   let bufNamePrev = fnamemodify(bufname(self.bufNrPrev), ':p:~')
-  let self.items = fuf#loadItems(s:MODE_NAME)
+  let self.items = fuf#loadDataFile(s:MODE_NAME, 'items')
   call map(self.items, 's:formatItemUsingCache(v:val)')
   call filter(self.items, '!empty(v:val) && v:val.word !=# bufNamePrev')
   call fuf#mapToSetSerialIndex(self.items, 1)

autoload/fuf/tag.vim

 
 "
 function s:parseTagFiles(tagFiles, key)
-  if !empty(g:fuf_tag_cache_dir)
-    " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists.
-    let cacheFile = fnamemodify(g:fuf_tag_cache_dir, ':p') . l9#hash224(a:key)
-    if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0
-      return map(l9#readFile(cacheFile), 'eval(v:val)')
-    endif
+  let cacheName = 'cache-' . l9#hash224(a:key)
+  let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
+  if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
+    return fuf#loadDataFile(s:MODE_NAME, cacheName)
   endif
   let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getTagNames(v:val)')))
   let items = map(items, 'fuf#makeNonPathItem(v:val, "")')
   call fuf#mapToSetSerialIndex(items, 1)
   let items = map(items, 'fuf#setAbbrWithFormattedWord(v:val, 1)')
-  if !empty(g:fuf_tag_cache_dir)
-    call l9#writeFile(map(copy(items), 'string(v:val)'), cacheFile)
-  endif
+  call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
   return items
 endfunction
 

autoload/fuf/taggedfile.vim

 
 "
 function s:parseTagFiles(tagFiles, key)
-  if !empty(g:fuf_taggedfile_cache_dir)
-    " NOTE: fnamemodify('a/b', ':p') returns 'a/b/' if the directory exists.
-    let cacheFile = fnamemodify(g:fuf_taggedfile_cache_dir, ':p') . l9#hash224(a:key)
-    if filereadable(cacheFile) && fuf#countModifiedFiles(a:tagFiles, getftime(cacheFile)) == 0
-      return map(l9#readFile(cacheFile), 'eval(v:val)')
-    endif
+  let cacheName = 'cache-' . l9#hash224(a:key)
+  let cacheTime = fuf#getDataFileTime(s:MODE_NAME, cacheName)
+  if cacheTime != -1 && fuf#countModifiedFiles(a:tagFiles, cacheTime) == 0
+    return fuf#loadDataFile(s:MODE_NAME, cacheName)
   endif
   let items = l9#unique(l9#concat(map(copy(a:tagFiles), 's:getTaggedFileList(v:val)')))
   call map(items, 'fuf#makePathItem(v:val, "", 0)')
   call fuf#mapToSetSerialIndex(items, 1)
   call fuf#mapToSetAbbrWithSnippedWordAsPath(items)
-  if !empty(g:fuf_taggedfile_cache_dir)
-    call l9#writeFile(map(copy(items), 'string(v:val)'), cacheFile)
-  endif
+  call fuf#saveDataFile(s:MODE_NAME, cacheName, items)
   return items
 endfunction
 
         "~/project/**/doc/*t*x*t*"
         ".vim/doc/*t*x*t*"
 
-                                                        *fuf-information-file*
-情報ファイル ~
+                                                               *fuf-data-file*
+データファイル ~
 
-FuzzyFinder は補完統計、MRUデータ、ブックマークなどを
-|g:fuf_infoFile|に書き込みます。
+FuzzyFinder は補完統計、MRUデータ、ブックマークなどを|g:fuf_dataDir|以下のファ
+イルに書き込みます。
 
-:FufEditInfo コマンドは情報ファイルの編集を補助します。このコマンドを
-実行すると、情報ファイルを無名バッファに読み込みます。:write などで書き込みを
-行うと、情報ファイルを更新します。
+|:FufEditDataFile|コマンドはデータファイルの編集を補助します。このコマンドを実
+行すると、データファイルを無名バッファに読み込みます。:write などで書き込みを
+行うと、データファイルを更新します。
 
                                                                    *fuf-cache*
 キャッシュ ~
         /...            /../../
         /....           /../../../
 
+                                                         *fuf-how-to-add-mode*
+モードの追加方法 ~
+
+"mymode" モードを追加するには、ソースファイルを autoload/fuf/mymode.vim に置き
+、 fuf#addMode('mymode') を呼びます。
+
                                                                   *fuf-migemo*
 Migemo とは ~
 
 
         FuzzyFinder 起動後に {pattern} が挿入されます。
 
-                                                                *:FufEditInfo*
-:FufEditInfo
-        情報ファイルを編集するためのバッファを開きます。詳しくは
-        |fuf-information-file|を参照してください。
+                                                            *:FufEditDataFile*
+:FufEditDataFile
+        データファイルを編集するためのバッファを開きます。詳しくは
+        |fuf-data-file|を参照してください。
 
                                                              *:FufAddBookmark*
 :FufAddBookmark [{name}]
 <
         あいまいマッチングと部分一致マッチングを切り替えるキー。
 
-                                                           *g:fuf_infoFile*  >
-  let g:fuf_infoFile = '~/.vim-fuf'
+                                                            *g:fuf_dataDir*  >
+  let g:fuf_dataDir = '~/.vim-fuf-data'
 <
-        補完統計、MRUデータ、ブックマークなどを書き込むファイル。空文字列を設
-        定するとファイルへの書き込みは行われなくなります。
+        データファイルを置くディレクトリのパス。空文字列を設定するとファイルへ
+        の書き込みは行われなくなります。
 
                                                           *g:fuf_abbrevMap*  >
   let g:fuf_abbrevMap = {}
         長い補完アイテムは、この長さに収まるよう省略して表示します。
 
                                                       *g:fuf_previewHeight*  >
-  let g:fuf_previewHeight = 5
+  let g:fuf_previewHeight = 10
 <
         プレビューをサポートするモードを起動したとき、'cmdheight'がこの値に設
         定されます。選択されている補完アイテムの情報がコマンドライン領域に表示
                                                         *g:fuf_autoPreview*  >
   let g:fuf_autoPreview = 0
 <
-        TODO
+        真ならプレビューを自動的に表示します。
 
                                                           *g:fuf_useMigemo*  >
   let g:fuf_useMigemo = 0
         には切り替えません。
 
                                                        *g:fuf_file_exclude*  >
-  let g:fuf_file_exclude = '\v\~$|\.(o|exe|bak|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+  let g:fuf_file_exclude = '\v\~$|\.(o|exe|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
 <
         補完リストから除外したいアイテムの正規表現パターン。
 
         には切り替えません。
 
                                                     *g:fuf_mrufile_exclude*  >
-  let g:fuf_mrufile_exclude = '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+  let g:fuf_mrufile_exclude = '\v\~$|\.(bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
 <
         補完リストから除外したいアイテムの正規表現パターン。
 
         には切り替えません。
 
                                               *g:fuf_aroundmrufile_exclude*  >
-  let g:fuf_aroundmrufile_exclude = '\v\~$|\.(o|exe|dll|bak|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+  let g:fuf_aroundmrufile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)'
 <
         補完リストから除外したいアイテムの正規表現パターン。
 
         次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
         には切り替えません。
 
-                                                      *g:fuf_tag_cache_dir*  >
-  let g:fuf_tag_cache_dir = '~/.vim-fuf-cache/tag'
-<
-        このディレクトリ内にキャッシュファイルが作成されます。空文字列なら作成
-        されません。
-
                                              *fuf-options-for-taggedfile-mode*
 Tagged-File モード用 ~
 
         次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
         には切り替えません。
 
-                                               *g:fuf_taggedfile_cache_dir*  >
-  let g:fuf_taggedfile_cache_dir = '~/.vim-fuf-cache/taggedfile'
-<
-        このディレクトリ内にキャッシュファイルが作成されます。空文字列なら作成
-        されません。
-
                                                *fuf-options-for-jumplist-mode*
 Jump-List モード用 ~
 
         次/前のモードに切り替えるときの、モードの順位です。負数ならこのモード
         には切り替えません。
 
-                                                     *g:fuf_help_cache_dir*  >
-  let g:fuf_help_cache_dir = '~/.vim-fuf-cache/help'
-<
-        このディレクトリ内にキャッシュファイルが作成されます。空文字列なら作成
-        されません。
-
 
 ==============================================================================
 vimrc の例                                                 *fuf-vimrc-example*
   nnoremap <silent> <C-f><C-h> :FufHelp<CR>
   nnoremap <silent> <C-f><C-b> :FufAddBookmark<CR>
   vnoremap <silent> <C-f><C-b> :FufAddBookmarkAsSelectedText<CR>
-  nnoremap <silent> <C-f><C-e> :FufEditInfo<CR>
+  nnoremap <silent> <C-f><C-e> :FufEditDataFile<CR>
   nnoremap <silent> <C-f><C-r> :FufRenewCache<CR>
 <
 
 
 and show concatenated search results.
 
-                                                        *fuf-information-file*
-Information File ~
+                                                               *fuf-data-file*
+Data File ~
 
-FuzzyFinder writes completion statistics, MRU data, bookmark, etc to
-|g:fuf_infoFile|.
+FuzzyFinder writes completion statistics, MRU data, bookmark, etc to files
+under |g:fuf_dataDir|.
 
-|:FufEditInfo| 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.
+|:FufEditDataFile| command is helpful in editing your data files. This command
+reads the data file in new unnamed buffer. Write the buffer and the data file
+will be updated.
 
                                                                    *fuf-cache*
 Cache ~
         /...            /../../
         /....           /../../../
 
+                                                         *fuf-how-to-add-mode*
+How To Add Mode ~
+
+To add "mymode" mode, put the source file at autoload/fuf/mymode.vim and call
+fuf#addMode("mymode") .
+
                                                                   *fuf-migemo*
 What Is Migemo ~
 
 
         {pattern} will be inserted after launching FuzzyFinder.
 
-                                                                *:FufEditInfo*
-:FufEditInfo
-        Opens a buffer for editing your information file. See
-        |fuf-information-file| for details.
+                                                            *:FufEditDataFile*
+:FufEditDataFile
+        Opens a buffer for editing your data files. See |fuf-data-file| for
+        details.
 
                                                              *:FufAddBookmark*
 :FufAddBookmark [{name}]
 <
         Key mapped to switch between fuzzy matching and partial matching.
 
-                                                           *g:fuf_infoFile*  >
-  let g:fuf_infoFile = '~/.vim-fuf'
+                                                           *g:fuf_dataDir*  >
+  let g:fuf_dataDir = '~/.vim-fuf-data'
 <
-        Filename to write completion statistics, MRU data, bookmark, etc. If
-        empty string, FuzzyFinder does not write to a file.
+        Directory path to which data files is put. If empty string,
+        FuzzyFinder does not write data files.
 
                                                           *g:fuf_abbrevMap*  >
   let g:fuf_abbrevMap = {}
         completion menu.
 
                                                       *g:fuf_previewHeight*  >
-  let g:fuf_previewHeight = 5
+  let g:fuf_previewHeight = 10
 <
         'cmdheight' is set to this when a mode supporting preview is launched.
         Information of selected completion item will be shown on command-line
                                                         *g:fuf_autoPreview*  >
   let g:fuf_autoPreview = 0
 <
-        TODO
+        If non-zero, previews will be shown automatically.
 
                                                           *g:fuf_useMigemo*  >
   let g:fuf_useMigemo = 0
         number, Fuzzyfinder never switches to this mode.
 
                                                        *g:fuf_file_exclude*  >
-  let g:fuf_file_exclude = '\v\~$|\.(o|exe|dll|bak|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
+  let g:fuf_file_exclude = '\v\~$|\.(o|exe|dll|bak|orig|swp)$|(^|[/\\])\.(hg|git|bzr)($|[/\\])'
 <
         Regexp pattern for items which you want to exclude from completion
         list.
         number, Fuzzyfinder never switches to this mode.
 
                                                     *g:fuf_mrufile_exclude*  >
-  let g:fuf_mrufile_exclude = '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+  let g:fuf_mrufile_exclude = '\v\~$|\.(bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
 <
         Regexp pattern for items which you want to exclude from completion
         list.
         number, Fuzzyfinder never switches to this mode.
 
                                               *g:fuf_aroundmrufile_exclude*  >
-  let g:fuf_aroundmrufile_exclude = '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)'
-  let g:fuf_aroundmrufile_exclude = '\v\~$|\.(o|exe|dll|bak|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)'
+  let g:fuf_aroundmrufile_exclude = '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)'
 <
         Regexp pattern for items which you want to exclude from completion
         list.
         Number of order for switching to the next/previous mode. If negative
         number, Fuzzyfinder never switches to this mode.
 
-                                                      *g:fuf_tag_cache_dir*  >
-  let g:fuf_tag_cache_dir = '~/.vim-fuf-cache/tag'
-<
-        Cache files are created in this directory. If empty, they are not
-        created.
-
                                              *fuf-options-for-taggedfile-mode*
 For Tagged-File Mode ~
 
         Number of order for switching to the next/previous mode. If negative
         number, Fuzzyfinder never switches to this mode.
 
-                                               *g:fuf_taggedfile_cache_dir*  >
-  let g:fuf_taggedfile_cache_dir = '~/.vim-fuf-cache/taggedfile'
-<
-        Cache files are created in this directory. If empty, they are not
-        created.
-
                                                *fuf-options-for-jumplist-mode*
 For Jump-List Mode ~
 
         Number of order for switching to the next/previous mode. If negative
         number, Fuzzyfinder never switches to this mode.
 
-                                                     *g:fuf_help_cache_dir*  >
-  let g:fuf_help_cache_dir = '~/.vim-fuf-cache/help'
-<
-        Cache files are created in this directory. If empty, they are not
-        created.
-
 
 ==============================================================================
 VIMRC EXAMPLE                                              *fuf-vimrc-example*
   nnoremap <silent> <C-f><C-h> :FufHelp<CR>
   nnoremap <silent> <C-f><C-b> :FufAddBookmark<CR>
   vnoremap <silent> <C-f><C-b> :FufAddBookmarkAsSelectedText<CR>
-  nnoremap <silent> <C-f><C-e> :FufEditInfo<CR>
+  nnoremap <silent> <C-f><C-e> :FufEditDataFile<CR>
   nnoremap <silent> <C-f><C-r> :FufRenewCache<CR>
 <
 
   - Added g:fuf_dataDir option and removed g:fuf_infoFile,
     g:g:fuf_tag_cache_dir, g:fuf_taggedfile_cache_dir, and
     g:fuf_help_cache_dir options.
+  - Added :FufEditDataFile command and removed :FufEditInfo command.
   - Fixed a bug that FuzzyFinder caused reseting window layout.
+  - Improved speed of changing buffers.
+  - Improved the way to add modes.
 
 3.5:
   - Added Line mode.
 "
 function s:initialize()
   "---------------------------------------------------------------------------
-  call l9#defineVariableDefault('g:fuf_modes'  , [
-        \   'buffer', 'file', 'dir', 'mrufile', 'aroundmrufile', 'mrucmd',
-        \   'bookmark', 'tag', 'taggedfile',
-        \   'jumplist', 'changelist', 'quickfix', 'line', 'help',
-        \   'givenfile', 'givendir', 'givencmd',
-        \   'callbackfile', 'callbackitem',
-        \ ])
   call l9#defineVariableDefault('g:fuf_modesDisable'     , [ 'mrufile', 'aroundmrufile', 'mrucmd', ])
   call l9#defineVariableDefault('g:fuf_keyOpen'          , '<CR>')
   call l9#defineVariableDefault('g:fuf_keyOpenSplit'     , '<C-j>')
   call l9#defineVariableDefault('g:fuf_keyPrevPattern'   , '<C-s>')
   call l9#defineVariableDefault('g:fuf_keyNextPattern'   , '<C-_>')
   call l9#defineVariableDefault('g:fuf_keySwitchMatching', '<C-\><C-\>')
-  call l9#defineVariableDefault('g:fuf_infoFile'         , '~/.vim-fuf') " TODO
   call l9#defineVariableDefault('g:fuf_dataDir'          , '~/.vim-fuf-data')
   call l9#defineVariableDefault('g:fuf_abbrevMap'        , {})
   call l9#defineVariableDefault('g:fuf_patternSeparator' , ';')
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_file_prompt'     , '>File[]>')
   call l9#defineVariableDefault('g:fuf_file_switchOrder', 20)
-  call l9#defineVariableDefault('g:fuf_file_exclude'    , '\v\~$|\.(o|exe|dll|bak|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])')
+  call l9#defineVariableDefault('g:fuf_file_exclude'    , '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])')
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_dir_prompt'     , '>Dir[]>')
   call l9#defineVariableDefault('g:fuf_dir_switchOrder', 30)
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_mrufile_prompt'     , '>MRU-File[]>')
   call l9#defineVariableDefault('g:fuf_mrufile_switchOrder', 40)
-  call l9#defineVariableDefault('g:fuf_mrufile_exclude'    , '\v\~$|\.(bak|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)')
+  call l9#defineVariableDefault('g:fuf_mrufile_exclude'    , '\v\~$|\.(bak|orig|sw[po])$|^(\/\/|\\\\|\/mnt\/|\/media\/)')
   call l9#defineVariableDefault('g:fuf_mrufile_maxItem'    , 200)
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_aroundmrufile_prompt'     , '>Around-MRU-File[]>')
   call l9#defineVariableDefault('g:fuf_aroundmrufile_switchOrder', 50)
-  call l9#defineVariableDefault('g:fuf_aroundmrufile_exclude'    , '\v\~$|\.(o|exe|dll|bak|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)')
+  call l9#defineVariableDefault('g:fuf_aroundmrufile_exclude'    , '\v\~$|\.(o|exe|dll|bak|orig|sw[po])$|(^|[/\\])\.(hg|git|bzr)($|[/\\])|^(\/\/|\\\\|\/mnt\/|\/media\/)')
   call l9#defineVariableDefault('g:fuf_aroundmrufile_maxDir'    , 100)
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_mrucmd_prompt'     , '>MRU-Cmd[]>')
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_tag_prompt'     , '>Tag[]>')
   call l9#defineVariableDefault('g:fuf_tag_switchOrder', 80)
-  call l9#defineVariableDefault('g:fuf_tag_cache_dir'  , '~/.vim-fuf-cache/tag') " TODO
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_taggedfile_prompt'     , '>Tagged-File[]>')
   call l9#defineVariableDefault('g:fuf_taggedfile_switchOrder', 90)
-  call l9#defineVariableDefault('g:fuf_taggedfile_cache_dir'  , '~/.vim-fuf-cache/taggedfile') " TODO
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_jumplist_prompt'     , '>Jump-List[]>')
   call l9#defineVariableDefault('g:fuf_jumplist_switchOrder', 100)
   "---------------------------------------------------------------------------
   call l9#defineVariableDefault('g:fuf_help_prompt'     , '>Help[]>')
   call l9#defineVariableDefault('g:fuf_help_switchOrder', 140)
-  call l9#defineVariableDefault('g:fuf_help_cache_dir'  , '~/.vim-fuf-cache/help') " TODO
   "---------------------------------------------------------------------------
-  call filter(g:fuf_modes, 'count(g:fuf_modesDisable, v:val) == 0')
-  for m in g:fuf_modes
-    call fuf#{m}#renewCache()
-    call fuf#{m}#onInit()
-  endfor
+  command! -bang -narg=0 FufEditDataFile call fuf#editDataFile()
+  command! -bang -narg=0 FufRenewCache   call s:renewCachesOfAllModes()
   "---------------------------------------------------------------------------
-  command! -bang -narg=0 FufEditInfo   call fuf#editInfoFile()
-  command! -bang -narg=0 FufRenewCache call s:renewCachesOfAllModes()
-  "---------------------------------------------------------------------------
-  for m in g:fuf_modes
-    if fuf#{m}#requiresOnCommandPre()
-      " cnoremap has a problem, which doesn't expand cabbrev.
-      cmap <silent> <expr> <CR> <SID>onCommandPre()
-      break
-    endif
-  endfor
+  call fuf#addMode('buffer')
+  call fuf#addMode('file')
+  call fuf#addMode('dir')
+  call fuf#addMode('mrufile')
+  call fuf#addMode('aroundmrufile')
+  call fuf#addMode('mrucmd')
+  call fuf#addMode('bookmark')
+  call fuf#addMode('tag')
+  call fuf#addMode('taggedfile')
+  call fuf#addMode('jumplist')
+  call fuf#addMode('changelist')
+  call fuf#addMode('quickfix')
+  call fuf#addMode('line')
+  call fuf#addMode('help')
+  call fuf#addMode('givenfile')
+  call fuf#addMode('givendir')
+  call fuf#addMode('givencmd')
+  call fuf#addMode('callbackfile')
+  call fuf#addMode('callbackitem')
   "---------------------------------------------------------------------------
 endfunction
 
 "
 function s:renewCachesOfAllModes()
-  for m in g:fuf_modes 
+  for m in fuf#getModeNames()
     call fuf#{m}#renewCache()
   endfor
 endfunction
 
-"
-function s:onBufEnter()
-  for m in g:fuf_modes 
-    call fuf#{m}#onBufEnter()
-  endfor
-endfunction
-
-"
-function s:onBufWritePost()
-  for m in g:fuf_modes
-    call fuf#{m}#onBufWritePost()
-  endfor
-endfunction
-
-"
-function s:onCommandPre()
-  for m in filter(copy(g:fuf_modes), 'fuf#{v:val}#requiresOnCommandPre()')
-      call fuf#{m}#onCommandPre(getcmdtype() . getcmdline())
-  endfor
-  " lets last entry become the newest in the history
-  call histadd(getcmdtype(), getcmdline())
-  " this is not mapped again (:help recursive_mapping)
-  return "\<CR>"
-endfunction
-
 " }}}1
 "=============================================================================
 " INITIALIZATION {{{1