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.

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