Most Recently Used (MRU) Vim Plugin
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

977 lines
34 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. " File: mru.vim
  2. " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
  3. " Version: 3.4
  4. " Last Modified: April 13, 2012
  5. " Copyright: Copyright (C) 2003-2012 Yegappan Lakshmanan
  6. " Permission is hereby granted to use and distribute this code,
  7. " with or without modifications, provided that this copyright
  8. " notice is copied with it. Like anything else that's free,
  9. " mru.vim is provided *as is* and comes with no warranty of any
  10. " kind, either expressed or implied. In no event will the copyright
  11. " holder be liable for any damamges resulting from the use of this
  12. " software.
  13. "
  14. " Overview
  15. " --------
  16. " The Most Recently Used (MRU) plugin provides an easy access to a list of
  17. " recently opened/edited files in Vim. This plugin automatically stores the
  18. " file names as you open/edit them in Vim.
  19. "
  20. " This plugin will work on all the platforms where Vim is supported. This
  21. " plugin will work in both console and GUI Vim. This version of the MRU
  22. " plugin needs Vim 7.0 and above. If you are using an earlier version of
  23. " Vim, then you should use an older version of the MRU plugin.
  24. "
  25. " The recently used filenames are stored in a file specified by the Vim
  26. " MRU_File variable.
  27. "
  28. " Installation
  29. " ------------
  30. " 1. Copy the mru.vim file to one of the following directories:
  31. "
  32. " $HOME/.vim/plugin - Unix like systems
  33. " $HOME/vimfiles/plugin - MS-Windows
  34. " $VIM:vimfiles:plugin - Macintosh
  35. " $VIM/vimfiles/plugin - All
  36. "
  37. " Refer to the following Vim help topics for more information about Vim
  38. " plugins:
  39. "
  40. " :help add-plugin
  41. " :help add-global-plugin
  42. " :help runtimepath
  43. "
  44. " 2. Set the MRU_File Vim variable in the .vimrc file to the location of a
  45. " file to store the most recently edited file names. This step is needed
  46. " only if you want to change the default MRU filename.
  47. " 3. Restart Vim.
  48. " 4. You can use the ":MRU" command to list and edit the recently used files.
  49. " In GUI Vim, you can use the 'File->Recent Files' menu to access the
  50. " recently used files.
  51. "
  52. " To uninstall this plugin, remove this file (mru.vim) from the
  53. " $HOME/.vim/plugin or $HOME/vimfiles/plugin or the $VIM/vimfile/plugin
  54. " directory.
  55. "
  56. " Usage
  57. " -----
  58. " To list and edit files from the MRU list, you can use the ":MRU" command.
  59. " The ":MRU" command displays the MRU file list in a temporary Vim window. If
  60. " the MRU window is already opened, then the MRU list displayed in the window
  61. " is refreshed.
  62. "
  63. " If you are using GUI Vim, then the names of the recently edited files are
  64. " added to the "File->Recent Files" menu. You can select the name of a file
  65. " from this sub-menu to edit the file.
  66. "
  67. " You can use the normal Vim commands to move around in the MRU window. You
  68. " cannot make changes in the MRU window.
  69. "
  70. " You can select a file name to edit by pressing the <Enter> key or by double
  71. " clicking the left mouse button on a file name. The selected file will be
  72. " opened. If the file is already opened in a window, the cursor will be moved
  73. " to that window. Otherwise, the file is opened in the previous window. If the
  74. " previous window has a modified buffer or is the preview window or is used by
  75. " some other plugin, then the file is opened in a new window.
  76. "
  77. " You can press the 'o' key to open the file name under the cursor in the
  78. " MRU window in a new window.
  79. "
  80. " To open a file from the MRU window in read-only mode (view), press the 'v'
  81. " key.
  82. "
  83. " To open a file from the MRU window in a new tab, press the 't' key. If the
  84. " file is already opened in a window in the current or in another tab, then
  85. " the cursor is moved to that tab. Otherwise, a new tab is opened.
  86. "
  87. " You can open multiple files from the MRU window by specifying a count before
  88. " pressing '<Enter>' or 'v' or 'o' or 't'. You can also visually select
  89. " multiple filenames and invoke the commands to open the files. Each selected
  90. " file will be opened in a separate window or tab.
  91. "
  92. " You can press the 'u' key in the MRU window to update the file list. This is
  93. " useful if you keep the MRU window open always.
  94. "
  95. " You can close the MRU window by pressing the 'q' key or using one of the Vim
  96. " window commands.
  97. "
  98. " To display only files matching a pattern from the MRU list in the MRU
  99. " window, you can specify a pattern to the ":MRU" command. For example, to
  100. " display only file names matching "vim" in them, you can use the following
  101. " command ":MRU vim". When you specify a partial file name and only one
  102. " matching filename is found, then the ":MRU" command will edit that file.
  103. "
  104. " The ":MRU" command supports command-line completion of file names from
  105. " the MRU list. You can enter a partial file name and then press <Tab>
  106. " or <Ctrl-D> to complete or list all the matching file names. Note that
  107. " after typing the ":MRU" command, you have to enter a space before completing
  108. " the file names with <Tab>.
  109. "
  110. " When a file supplied to the ":MRU" command is not present in the MRU list,
  111. " but it is a readable file, then the file will be opened (even though it is
  112. " not present in the MRU list). This is useful if you want to open a file
  113. " present in the same directory as a file in the MRU list. You can use the
  114. " command-line completion of the ":MRU" command to complete the full path of a
  115. " file and then modify the path to open another file present in the same path.
  116. "
  117. " Whenever the MRU list changes, the MRU file is updated with the latest MRU
  118. " list. When you have multiple instances of Vim running at the same time, the
  119. " latest MRU list will show up in all the instances of Vim.
  120. "
  121. " Configuration
  122. " -------------
  123. " By changing the following variables you can configure the behavior of this
  124. " plugin. Set the following variables in your .vimrc file using the 'let'
  125. " command.
  126. "
  127. " The list of recently edited file names is stored in the file specified by the
  128. " MRU_File variable. The default setting for this variable is
  129. " $HOME/.vim_mru_files for Unix-like systems and $USERPROFILE/_vim_mru_files
  130. " for MS-Windows systems. You can change this variable to point to a file by
  131. " adding the following line to the .vimrc file:
  132. "
  133. " let MRU_File = 'd:\myhome\_vim_mru_files'
  134. "
  135. " By default, the plugin will remember the names of the last 100 used files.
  136. " As you edit more files, old file names will be removed from the MRU list.
  137. " You can set the 'MRU_Max_Entries' variable to remember more file names. For
  138. " example, to remember 1000 most recently used file names, you can use
  139. "
  140. " let MRU_Max_Entries = 1000
  141. "
  142. " By default, all the edited file names will be added to the MRU list. If you
  143. " want to exclude file names matching a list of patterns, you can set the
  144. " MRU_Exclude_Files variable to a list of Vim regular expressions. By default,
  145. " this variable is set to an empty string. For example, to not include files
  146. " in the temporary (/tmp, /var/tmp and d:\temp) directories, you can set the
  147. " MRU_Exclude_Files variable to
  148. "
  149. " let MRU_Exclude_Files = '^/tmp/.*\|^/var/tmp/.*' " For Unix
  150. " let MRU_Exclude_Files = '^c:\\temp\\.*' " For MS-Windows
  151. "
  152. " The specified pattern should be a Vim regular expression pattern.
  153. "
  154. " If you want to add only file names matching a set of patterns to the MRU
  155. " list, then you can set the MRU_Include_Files variable. This variable should
  156. " be set to a Vim regular expression pattern. For example, to add only .c and
  157. " .h files to the MRU list, you can set this variable as below:
  158. "
  159. " let MRU_Include_Files = '\.c$\|\.h$'
  160. "
  161. " By default, MRU_Include_Files is set to an empty string and all the edited
  162. " filenames are added to the MRU list.
  163. "
  164. " The default height of the MRU window is 8. You can set the MRU_Window_Height
  165. " variable to change the window height.
  166. "
  167. " let MRU_Window_Height = 15
  168. "
  169. " By default, when the :MRU command is invoked, the MRU list will be displayed
  170. " in a new window. Instead, if you want the MRU plugin to reuse the current
  171. " window, then you can set the 'MRU_Use_Current_Window' variable to one.
  172. "
  173. " let MRU_Use_Current_Window = 1
  174. "
  175. " The MRU plugin will reuse the current window. When a file name is selected,
  176. " the file is also opened in the current window.
  177. "
  178. " When you select a file from the MRU window, the MRU window will be
  179. " automatically closed and the selected file will be opened in the previous
  180. " window. You can set the 'MRU_Auto_Close' variable to zero to keep the MRU
  181. " window open.
  182. "
  183. " let MRU_Auto_Close = 0
  184. "
  185. " If you don't use the "File->Recent Files" menu and want to disable it,
  186. " then you can set the 'MRU_Add_Menu' variable to zero. By default, the
  187. " menu is enabled.
  188. "
  189. " let MRU_Add_Menu = 0
  190. "
  191. " If too many file names are present in the MRU list, then updating the MRU
  192. " menu to list all the file names makes Vim slow. To avoid this, the
  193. " MRU_Max_Menu_Entries variable controls the number of file names to show in
  194. " the MRU menu. By default, this is set to 10. You can change this to show
  195. " more entries in the menu.
  196. "
  197. " let MRU_Max_Menu_Entries = 20
  198. "
  199. " If many file names are present in the MRU list, then the MRU menu is split
  200. " into sub-menus. Each sub-menu contains MRU_Max_Submenu_Entries file names.
  201. " The default setting for this is 10. You can change this to increase the
  202. " number of file names displayed in a single sub-menu:
  203. "
  204. " let MRU_Max_Submenu_Entries = 15
  205. "
  206. " ****************** Do not modify after this line ************************
  207. if exists('loaded_mru')
  208. finish
  209. endif
  210. let loaded_mru=1
  211. if v:version < 700
  212. finish
  213. endif
  214. " Line continuation used here
  215. let s:cpo_save = &cpo
  216. set cpo&vim
  217. " MRU configuration variables {{{1
  218. " Maximum number of entries allowed in the MRU list
  219. if !exists('MRU_Max_Entries')
  220. let MRU_Max_Entries = 100
  221. endif
  222. " Files to exclude from the MRU list
  223. if !exists('MRU_Exclude_Files')
  224. let MRU_Exclude_Files = ''
  225. endif
  226. " Files to include in the MRU list
  227. if !exists('MRU_Include_Files')
  228. let MRU_Include_Files = ''
  229. endif
  230. " Height of the MRU window
  231. " Default height is 8
  232. if !exists('MRU_Window_Height')
  233. let MRU_Window_Height = 8
  234. endif
  235. if !exists('MRU_Use_Current_Window')
  236. let MRU_Use_Current_Window = 0
  237. endif
  238. if !exists('MRU_Auto_Close')
  239. let MRU_Auto_Close = 1
  240. endif
  241. if !exists('MRU_File')
  242. if has('unix') || has('macunix')
  243. let MRU_File = $HOME . '/.vim_mru_files'
  244. else
  245. let MRU_File = $VIM . '/_vim_mru_files'
  246. if has('win32')
  247. " MS-Windows
  248. if $USERPROFILE != ''
  249. let MRU_File = $USERPROFILE . '\_vim_mru_files'
  250. endif
  251. endif
  252. endif
  253. endif
  254. " Option for enabling or disabling the MRU menu
  255. if !exists('MRU_Add_Menu')
  256. let MRU_Add_Menu = 1
  257. endif
  258. " Maximum number of file names to show in the MRU menu. If too many files are
  259. " listed in the menu, then Vim becomes slow when updating the menu. So set
  260. " this to a low value.
  261. if !exists('MRU_Max_Menu_Entries')
  262. let MRU_Max_Menu_Entries = 10
  263. endif
  264. " Maximum number of file names to show in a MRU sub-menu. If the MRU list
  265. " contains more file names than this setting, then the MRU menu is split into
  266. " one or more sub-menus.
  267. if !exists('MRU_Max_Submenu_Entries')
  268. let MRU_Max_Submenu_Entries = 10
  269. endif
  270. " When only a single matching filename is found in the MRU list, the following
  271. " option controls whether the file name is displayed in the MRU window or the
  272. " file is directly opened. When this variable is set to 0 and a single
  273. " matching file name is found, then the file is directly opened.
  274. if !exists('MRU_Window_Open_Always')
  275. let MRU_Window_Open_Always = 0
  276. endif
  277. " When opening a file from the MRU list, the file is opened in the current
  278. " tab. If the selected file has to be opened in a tab always, then set the
  279. " following variable to 1. If the file is already opened in a tab, then the
  280. " cursor will be moved to that tab.
  281. if !exists('MRU_Open_File_Use_Tabs')
  282. let MRU_Open_File_Use_Tabs = 0
  283. endif
  284. " Control to temporarily lock the MRU list. Used to prevent files from
  285. " getting added to the MRU list when the ':vimgrep' command is executed.
  286. let s:mru_list_locked = 0
  287. " MRU_LoadList {{{1
  288. " Loads the latest list of file names from the MRU file
  289. function! s:MRU_LoadList()
  290. " If the MRU file is present, then load the list of filenames. Otherwise
  291. " start with an empty list.
  292. if filereadable(g:MRU_File)
  293. let s:MRU_files = readfile(g:MRU_File)
  294. if s:MRU_files[0] =~# '^\s*" Most recently edited files in Vim'
  295. " Generated by the previous version of the MRU plugin.
  296. " Discard the list.
  297. let s:MRU_files = []
  298. elseif s:MRU_files[0] =~# '^#'
  299. " Remove the comment line
  300. call remove(s:MRU_files, 0)
  301. else
  302. " Unsupported format
  303. let s:MRU_files = []
  304. endif
  305. else
  306. let s:MRU_files = []
  307. endif
  308. " Refresh the MRU menu with the latest list of filenames
  309. call s:MRU_Refresh_Menu()
  310. endfunction
  311. " MRU_SaveList {{{1
  312. " Saves the MRU file names to the MRU file
  313. function! s:MRU_SaveList()
  314. let l = []
  315. call add(l, '# Most recently edited files in Vim (version 3.0)')
  316. call extend(l, s:MRU_files)
  317. call writefile(l, g:MRU_File)
  318. endfunction
  319. " MRU_AddFile {{{1
  320. " Adds a file to the MRU file list
  321. " acmd_bufnr - Buffer number of the file to add
  322. function! s:MRU_AddFile(acmd_bufnr)
  323. if s:mru_list_locked
  324. " MRU list is currently locked
  325. return
  326. endif
  327. " Get the full path to the filename
  328. let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
  329. if fname == ''
  330. return
  331. endif
  332. " Skip temporary buffers with buftype set. The buftype is set for buffers
  333. " used by plugins.
  334. if &buftype != ''
  335. return
  336. endif
  337. if g:MRU_Include_Files != ''
  338. " If MRU_Include_Files is set, include only files matching the
  339. " specified pattern
  340. if fname !~# g:MRU_Include_Files
  341. return
  342. endif
  343. endif
  344. if g:MRU_Exclude_Files != ''
  345. " Do not add files matching the pattern specified in the
  346. " MRU_Exclude_Files to the MRU list
  347. if fname =~# g:MRU_Exclude_Files
  348. return
  349. endif
  350. endif
  351. " If the filename is not already present in the MRU list and is not
  352. " readable then ignore it
  353. let idx = index(s:MRU_files, fname)
  354. if idx == -1
  355. if !filereadable(fname)
  356. " File is not readable and is not in the MRU list
  357. return
  358. endif
  359. endif
  360. " Load the latest MRU file list
  361. call s:MRU_LoadList()
  362. " Remove the new file name from the existing MRU list (if already present)
  363. call filter(s:MRU_files, 'v:val !=# fname')
  364. " Add the new file list to the beginning of the updated old file list
  365. call insert(s:MRU_files, fname, 0)
  366. " Trim the list
  367. if len(s:MRU_files) > g:MRU_Max_Entries
  368. call remove(s:MRU_files, g:MRU_Max_Entries, -1)
  369. endif
  370. " Save the updated MRU list
  371. call s:MRU_SaveList()
  372. " Refresh the MRU menu
  373. call s:MRU_Refresh_Menu()
  374. " If the MRU window is open, update the displayed MRU list
  375. let bname = '__MRU_Files__'
  376. let winnum = bufwinnr(bname)
  377. if winnum != -1
  378. let cur_winnr = winnr()
  379. call s:MRU_Open_Window()
  380. if winnr() != cur_winnr
  381. exe cur_winnr . 'wincmd w'
  382. endif
  383. endif
  384. endfunction
  385. " MRU_escape_filename {{{1
  386. " Escape special characters in a filename. Special characters in file names
  387. " that should be escaped (for security reasons)
  388. let s:esc_filename_chars = ' *?[{`$%#"|!<>();&' . "'\t\n"
  389. function! s:MRU_escape_filename(fname)
  390. return escape(a:fname, s:esc_filename_chars)
  391. endfunction
  392. " MRU_Edit_File {{{1
  393. " Edit the specified file
  394. " filename - Name of the file to edit
  395. " sanitized - Specifies whether the filename is already escaped for special
  396. " characters or not.
  397. function! s:MRU_Edit_File(filename, sanitized)
  398. if !a:sanitized
  399. let esc_fname = s:MRU_escape_filename(a:filename)
  400. else
  401. let esc_fname = a:filename
  402. endif
  403. " If the user wants to always open the file in a tab, then open the file
  404. " in a tab. If it is already opened in a tab, then the cursor will be
  405. " moved to that tab.
  406. if g:MRU_Open_File_Use_Tabs
  407. call s:MRU_Open_File_In_Tab(a:filename, esc_fname)
  408. return
  409. endif
  410. " If the file is already open in one of the windows, jump to it
  411. let winnum = bufwinnr('^' . a:filename . '$')
  412. if winnum != -1
  413. if winnum != winnr()
  414. exe winnum . 'wincmd w'
  415. endif
  416. else
  417. if &modified || &buftype != '' || &previewwindow
  418. " Current buffer has unsaved changes or is a special buffer or is
  419. " the preview window. So open the file in a new window
  420. exe 'split ' . esc_fname
  421. else
  422. exe 'edit ' . esc_fname
  423. endif
  424. endif
  425. endfunction
  426. " MRU_Open_File_In_Tab
  427. " Open a file in a tab. If the file is already opened in a tab, jump to the
  428. " tab. Otherwise, create a new tab and open the file.
  429. " fname : Name of the file to open
  430. " esc_fname : File name with special characters escaped
  431. function! s:MRU_Open_File_In_Tab(fname, esc_fname)
  432. " If the selected file is already open in the current tab or in
  433. " another tab, jump to it. Otherwise open it in a new tab
  434. if bufwinnr('^' . a:fname . '$') == -1
  435. let tabnum = -1
  436. let i = 1
  437. let bnum = bufnr('^' . a:fname . '$')
  438. while i <= tabpagenr('$')
  439. if index(tabpagebuflist(i), bnum) != -1
  440. let tabnum = i
  441. break
  442. endif
  443. let i += 1
  444. endwhile
  445. if tabnum != -1
  446. " Goto the tab containing the file
  447. exe 'tabnext ' . i
  448. else
  449. " Open a new tab as the last tab page
  450. exe '999tabnew ' . a:esc_fname
  451. endif
  452. endif
  453. " Jump to the window containing the file
  454. let winnum = bufwinnr('^' . a:fname . '$')
  455. if winnum != winnr()
  456. exe winnum . 'wincmd w'
  457. endif
  458. endfunction
  459. " MRU_Window_Edit_File {{{1
  460. " fname : Name of the file to edit. May specify single or multiple
  461. " files.
  462. " edit_type : Specifies how to edit the file. Can be one of 'edit' or 'view'.
  463. " 'view' - Open the file as a read-only file
  464. " 'edit' - Edit the file as a regular file
  465. " multi : Specifies whether a single file or multiple files need to be
  466. " opened.
  467. " open_type : Specifies where to open the file. Can be one of 'useopen' or
  468. " 'newwin' or 'newtab'.
  469. " useopen - If the file is already present in a window, then
  470. " jump to that window. Otherwise, open the file in
  471. " the previous window.
  472. " newwin_horiz - Open the file in a new horizontal window.
  473. " newwin_vert - Open the file in a new vertical window.
  474. " newtab - Open the file in a new tab. If the file is already
  475. " opened in a tab, then jump to that tab.
  476. function! s:MRU_Window_Edit_File(fname, multi, edit_type, open_type)
  477. let esc_fname = s:MRU_escape_filename(a:fname)
  478. if a:open_type == 'newwin_horiz'
  479. " Edit the file in a new horizontally split window above the previous
  480. " window
  481. wincmd p
  482. exe 'belowright new ' . esc_fname
  483. elseif a:open_type == 'newwin_vert'
  484. " Edit the file in a new vertically split window above the previous
  485. " window
  486. wincmd p
  487. exe 'belowright vnew ' . esc_fname
  488. elseif a:open_type == 'newtab' || g:MRU_Open_File_Use_Tabs
  489. call s:MRU_Open_File_In_Tab(a:fname, esc_fname)
  490. else
  491. " If the selected file is already open in one of the windows,
  492. " jump to it
  493. let winnum = bufwinnr('^' . a:fname . '$')
  494. if winnum != -1
  495. exe winnum . 'wincmd w'
  496. else
  497. if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
  498. " Jump to the window from which the MRU window was opened
  499. if exists('s:MRU_last_buffer')
  500. let last_winnr = bufwinnr(s:MRU_last_buffer)
  501. if last_winnr != -1 && last_winnr != winnr()
  502. exe last_winnr . 'wincmd w'
  503. endif
  504. endif
  505. else
  506. if g:MRU_Use_Current_Window == 0
  507. " Goto the previous window
  508. " If MRU_Use_Current_Window is set to one, then the
  509. " current window is used to open the file
  510. wincmd p
  511. endif
  512. endif
  513. let split_window = 0
  514. if &modified || &previewwindow || a:multi
  515. " Current buffer has unsaved changes or is the preview window
  516. " or the user is opening multiple files
  517. " So open the file in a new window
  518. let split_window = 1
  519. endif
  520. if &buftype != ''
  521. " Current buffer is a special buffer (maybe used by a plugin)
  522. if g:MRU_Use_Current_Window == 0 ||
  523. \ bufnr('%') != bufnr('__MRU_Files__')
  524. let split_window = 1
  525. endif
  526. endif
  527. " Edit the file
  528. if split_window
  529. " Current buffer has unsaved changes or is a special buffer or
  530. " is the preview window. So open the file in a new window
  531. if a:edit_type == 'edit'
  532. exe 'split ' . esc_fname
  533. else
  534. exe 'sview ' . esc_fname
  535. endif
  536. else
  537. if a:edit_type == 'edit'
  538. exe 'edit ' . esc_fname
  539. else
  540. exe 'view ' . esc_fname
  541. endif
  542. endif
  543. endif
  544. endif
  545. endfunction
  546. " MRU_Select_File_Cmd {{{1
  547. " Open a file selected from the MRU window
  548. "
  549. " 'opt' has two values separated by comma. The first value specifies how to
  550. " edit the file and can be either 'edit' or 'view'. The second value
  551. " specifies where to open the file. It can take one of the following values:
  552. " 'useopen' to open file in the previous window
  553. " 'newwin_horiz' to open the file in a new horizontal split window
  554. " 'newwin_vert' to open the file in a new vertical split window.
  555. " 'newtab' to open the file in a new tab.
  556. " If multiple file names are selected using visual mode, then open multiple
  557. " files (either in split windows or tabs)
  558. function! s:MRU_Select_File_Cmd(opt) range
  559. let [edit_type, open_type] = split(a:opt, ',')
  560. let fnames = getline(a:firstline, a:lastline)
  561. if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
  562. " Automatically close the window if the file window is
  563. " not used to display the MRU list.
  564. silent! close
  565. endif
  566. let multi = 0
  567. for f in fnames
  568. if f == ''
  569. continue
  570. endif
  571. " The text in the MRU window contains the filename in parenthesis
  572. let file = matchstr(f, '(\zs.*\ze)')
  573. call s:MRU_Window_Edit_File(file, multi, edit_type, open_type)
  574. if a:firstline != a:lastline
  575. " Opening multiple files
  576. let multi = 1
  577. endif
  578. endfor
  579. endfunction
  580. " MRU_Warn_Msg {{{1
  581. " Display a warning message
  582. function! s:MRU_Warn_Msg(msg)
  583. echohl WarningMsg
  584. echo a:msg
  585. echohl None
  586. endfunction
  587. " MRU_Open_Window {{{1
  588. " Display the Most Recently Used file list in a temporary window.
  589. " If the optional argument is supplied, then it specifies the pattern of files
  590. " to selectively display in the MRU window.
  591. function! s:MRU_Open_Window(...)
  592. " Load the latest MRU file list
  593. call s:MRU_LoadList()
  594. " Check for empty MRU list
  595. if empty(s:MRU_files)
  596. call s:MRU_Warn_Msg('MRU file list is empty')
  597. return
  598. endif
  599. " Save the current buffer number. This is used later to open a file when a
  600. " entry is selected from the MRU window. The window number is not saved,
  601. " as the window number will change when new windows are opened.
  602. let s:MRU_last_buffer = bufnr('%')
  603. let bname = '__MRU_Files__'
  604. " If the window is already open, jump to it
  605. let winnum = bufwinnr(bname)
  606. if winnum != -1
  607. if winnr() != winnum
  608. " If not already in the window, jump to it
  609. exe winnum . 'wincmd w'
  610. endif
  611. setlocal modifiable
  612. " Delete the contents of the buffer to the black-hole register
  613. silent! %delete _
  614. else
  615. if g:MRU_Use_Current_Window
  616. " Reuse the current window
  617. "
  618. " If the __MRU_Files__ buffer exists, then reuse it. Otherwise open
  619. " a new buffer
  620. let bufnum = bufnr(bname)
  621. if bufnum == -1
  622. let cmd = 'edit ' . bname
  623. else
  624. let cmd = 'buffer ' . bufnum
  625. endif
  626. exe cmd
  627. if bufnr('%') != bufnr(bname)
  628. " Failed to edit the MRU buffer
  629. return
  630. endif
  631. else
  632. " Open a new window at the bottom
  633. " If the __MRU_Files__ buffer exists, then reuse it. Otherwise open
  634. " a new buffer
  635. let bufnum = bufnr(bname)
  636. if bufnum == -1
  637. let wcmd = bname
  638. else
  639. let wcmd = '+buffer' . bufnum
  640. endif
  641. exe 'silent! botright ' . g:MRU_Window_Height . 'split ' . wcmd
  642. endif
  643. endif
  644. " Mark the buffer as scratch
  645. setlocal buftype=nofile
  646. setlocal bufhidden=delete
  647. setlocal noswapfile
  648. setlocal nowrap
  649. setlocal nobuflisted
  650. " Use fixed height for the MRU window
  651. setlocal winfixheight
  652. " Setup the cpoptions properly for the maps to work
  653. let old_cpoptions = &cpoptions
  654. set cpoptions&vim
  655. " Create mappings to select and edit a file from the MRU list
  656. nnoremap <buffer> <silent> <CR>
  657. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  658. vnoremap <buffer> <silent> <CR>
  659. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  660. nnoremap <buffer> <silent> o
  661. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_horiz')<CR>
  662. vnoremap <buffer> <silent> o
  663. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_horiz')<CR>
  664. nnoremap <buffer> <silent> O
  665. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_vert')<CR>
  666. vnoremap <buffer> <silent> O
  667. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_vert')<CR>
  668. nnoremap <buffer> <silent> t
  669. \ :call <SID>MRU_Select_File_Cmd('edit,newtab')<CR>
  670. vnoremap <buffer> <silent> t
  671. \ :call <SID>MRU_Select_File_Cmd('edit,newtab')<CR>
  672. nnoremap <buffer> <silent> v
  673. \ :call <SID>MRU_Select_File_Cmd('view,useopen')<CR>
  674. nnoremap <buffer> <silent> u :MRU<CR>
  675. nnoremap <buffer> <silent> <2-LeftMouse>
  676. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  677. nnoremap <buffer> <silent> q :close<CR>
  678. " Restore the previous cpoptions settings
  679. let &cpoptions = old_cpoptions
  680. " Display the MRU list
  681. if a:0 == 0
  682. " No search pattern specified. Display the complete list
  683. let m = copy(s:MRU_files)
  684. else
  685. " Display only the entries matching the specified pattern
  686. " First try using it as a literal pattern
  687. let m = filter(copy(s:MRU_files), 'stridx(v:val, a:1) != -1')
  688. if len(m) == 0
  689. " No match. Try using it as a regular expression
  690. let m = filter(copy(s:MRU_files), 'v:val =~# a:1')
  691. endif
  692. endif
  693. " Get the tail part of the file name (without the directory) and display
  694. " it along with the full path
  695. let output = map(m, 'fnamemodify(v:val, ":t") . " (" . v:val . ")"')
  696. silent! 0put =output
  697. " Delete the empty line at the end of the buffer
  698. $delete
  699. " Move the cursor to the beginning of the file
  700. normal! gg
  701. setlocal nomodifiable
  702. endfunction
  703. " MRU_Complete {{{1
  704. " Command-line completion function used by :MRU command
  705. function! s:MRU_Complete(ArgLead, CmdLine, CursorPos)
  706. if a:ArgLead == ''
  707. " Return the complete list of MRU files
  708. return s:MRU_files
  709. else
  710. " Return only the files matching the specified pattern
  711. return filter(copy(s:MRU_files), 'v:val =~? a:ArgLead')
  712. endif
  713. endfunction
  714. " MRU_Cmd {{{1
  715. " Function to handle the MRU command
  716. " pat - File name pattern passed to the MRU command
  717. function! s:MRU_Cmd(pat)
  718. if a:pat == ''
  719. " No arguments specified. Open the MRU window
  720. call s:MRU_Open_Window()
  721. return
  722. endif
  723. " Load the latest MRU file
  724. call s:MRU_LoadList()
  725. " Empty MRU list
  726. if empty(s:MRU_files)
  727. call s:MRU_Warn_Msg('MRU file list is empty')
  728. return
  729. endif
  730. " First use the specified string as a literal string and search for
  731. " filenames containing the string. If only one filename is found,
  732. " then edit it (unless the user wants to open the MRU window always)
  733. let m = filter(copy(s:MRU_files), 'stridx(v:val, a:pat) != -1')
  734. if len(m) > 0
  735. if len(m) == 1 && !g:MRU_Window_Open_Always
  736. call s:MRU_Edit_File(m[0], 0)
  737. return
  738. endif
  739. " More than one file matches. Try find an accurate match
  740. let new_m = filter(m, 'v:val ==# a:pat')
  741. if len(new_m) == 1 && !g:MRU_Window_Open_Always
  742. call s:MRU_Edit_File(new_m[0], 0)
  743. return
  744. endif
  745. " Couldn't find an exact match, open the MRU window with all the
  746. " files matching the pattern.
  747. call s:MRU_Open_Window(a:pat)
  748. return
  749. endif
  750. " Use the specified string as a regular expression pattern and search
  751. " for filenames matching the pattern
  752. let m = filter(copy(s:MRU_files), 'v:val =~? a:pat')
  753. if len(m) == 0
  754. " If an existing file (not present in the MRU list) is specified,
  755. " then open the file.
  756. if filereadable(a:pat)
  757. call s:MRU_Edit_File(a:pat, 0)
  758. return
  759. endif
  760. " No filenames matching the specified pattern are found
  761. call s:MRU_Warn_Msg("MRU file list doesn't contain " .
  762. \ "files matching " . a:pat)
  763. return
  764. endif
  765. if len(m) == 1 && !g:MRU_Window_Open_Always
  766. call s:MRU_Edit_File(m[0], 0)
  767. return
  768. endif
  769. call s:MRU_Open_Window(a:pat)
  770. endfunction
  771. " MRU_add_files_to_menu {{{1
  772. " Adds a list of files to the "Recent Files" sub menu under the "File" menu.
  773. " prefix - Prefix to use for each of the menu entries
  774. " file_list - List of file names to add to the menu
  775. function! s:MRU_add_files_to_menu(prefix, file_list)
  776. for fname in a:file_list
  777. " Escape special characters in the filename
  778. let esc_fname = escape(fnamemodify(fname, ':t'), ".\\" .
  779. \ s:esc_filename_chars)
  780. let esc_fname = substitute(esc_fname, '&', '&&', 'g')
  781. " Truncate the directory name if it is long
  782. let dir_name = fnamemodify(fname, ':h')
  783. let len = strlen(dir_name)
  784. " Shorten long file names by adding only few characters from
  785. " the beginning and end.
  786. if len > 30
  787. let dir_name = strpart(dir_name, 0, 10) .
  788. \ '...' .
  789. \ strpart(dir_name, len - 20)
  790. endif
  791. let esc_dir_name = escape(dir_name, ".\\" . s:esc_filename_chars)
  792. let esc_dir_name = substitute(esc_dir_name, '&', '&&', 'g')
  793. let menu_path = '&File.&Recent\ Files.' . a:prefix . esc_fname .
  794. \ '\ (' . esc_dir_name . ')'
  795. let esc_mfname = s:MRU_escape_filename(fname)
  796. exe 'anoremenu <silent> ' . menu_path .
  797. \ " :call <SID>MRU_Edit_File('" . esc_mfname . "', 1)<CR>"
  798. exe 'tmenu ' . menu_path . ' Edit file ' . esc_mfname
  799. endfor
  800. endfunction
  801. " MRU_Refresh_Menu {{{1
  802. " Refresh the MRU menu
  803. function! s:MRU_Refresh_Menu()
  804. if !has('menu') || !g:MRU_Add_Menu
  805. " No support for menus
  806. return
  807. endif
  808. " Setup the cpoptions properly for the maps to work
  809. let old_cpoptions = &cpoptions
  810. set cpoptions&vim
  811. " Remove the MRU menu
  812. " To retain the teared-off MRU menu, we need to add a dummy entry
  813. silent! unmenu &File.&Recent\ Files
  814. " The menu priority of the File menu is 10. If the MRU plugin runs
  815. " first before menu.vim, the File menu order may not be correct.
  816. " So specify the priority of the File menu here.
  817. 10noremenu &File.&Recent\ Files.Dummy <Nop>
  818. silent! unmenu! &File.&Recent\ Files
  819. anoremenu <silent> &File.&Recent\ Files.Refresh\ list
  820. \ :call <SID>MRU_LoadList()<CR>
  821. exe 'tmenu File.&Recent\ Files.Refresh\ list Reload the MRU file list from '
  822. \ . s:MRU_escape_filename(g:MRU_File)
  823. anoremenu File.&Recent\ Files.-SEP1- :
  824. " Add the filenames in the MRU list to the menu
  825. let entry_cnt = len(s:MRU_files)
  826. if entry_cnt > g:MRU_Max_Menu_Entries
  827. " Show only MRU_Max_Menu_Entries file names in the menu
  828. let mru_list = s:MRU_files[1 : g:MRU_Max_Menu_Entries]
  829. let entry_cnt = g:MRU_Max_Menu_Entries
  830. else
  831. let mru_list = s:MRU_files
  832. endif
  833. if entry_cnt > g:MRU_Max_Submenu_Entries
  834. " Split the MRU menu into sub-menus
  835. for start_idx in range(0, entry_cnt, g:MRU_Max_Submenu_Entries)
  836. let last_idx = start_idx + g:MRU_Max_Submenu_Entries - 1
  837. if last_idx >= entry_cnt
  838. let last_idx = entry_cnt - 1
  839. endif
  840. let prefix = 'Files\ (' . (start_idx + 1) . '\.\.\.' .
  841. \ (last_idx + 1) . ').'
  842. call s:MRU_add_files_to_menu(prefix,
  843. \ mru_list[start_idx : last_idx])
  844. endfor
  845. else
  846. call s:MRU_add_files_to_menu('', mru_list)
  847. endif
  848. " Remove the dummy menu entry
  849. unmenu &File.&Recent\ Files.Dummy
  850. " Restore the previous cpoptions settings
  851. let &cpoptions = old_cpoptions
  852. endfunction
  853. " Load the MRU list on plugin startup
  854. call s:MRU_LoadList()
  855. " MRU autocommands {{{1
  856. " Autocommands to detect the most recently used files
  857. autocmd BufRead * call s:MRU_AddFile(expand('<abuf>'))
  858. autocmd BufNewFile * call s:MRU_AddFile(expand('<abuf>'))
  859. autocmd BufWritePost * call s:MRU_AddFile(expand('<abuf>'))
  860. " The ':vimgrep' command adds all the files searched to the buffer list.
  861. " This also modifies the MRU list, even though the user didn't edit the
  862. " files. Use the following autocmds to prevent this.
  863. autocmd QuickFixCmdPre *vimgrep* let s:mru_list_locked = 1
  864. autocmd QuickFixCmdPost *vimgrep* let s:mru_list_locked = 0
  865. " Command to open the MRU window
  866. command! -nargs=? -complete=customlist,s:MRU_Complete MRU
  867. \ call s:MRU_Cmd(<q-args>)
  868. command! -nargs=? -complete=customlist,s:MRU_Complete Mru
  869. \ call s:MRU_Cmd(<q-args>)
  870. " }}}
  871. " restore 'cpo'
  872. let &cpo = s:cpo_save
  873. unlet s:cpo_save
  874. " vim:set foldenable foldmethod=marker: