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.

984 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
10 years ago
  1. " File: mru.vim
  2. " Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
  3. " Version: 3.6
  4. " Last Modified: December 22, 2013
  5. " Copyright: Copyright (C) 2003-2013 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. " 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. return escape(a:fname, s:esc_filename_chars)
  395. endfunction
  396. " MRU_Edit_File {{{1
  397. " Edit the specified file
  398. " filename - Name of the file to edit
  399. " sanitized - Specifies whether the filename is already escaped for special
  400. " characters or not.
  401. function! s:MRU_Edit_File(filename, sanitized)
  402. if !a:sanitized
  403. let esc_fname = s:MRU_escape_filename(a:filename)
  404. else
  405. let esc_fname = a:filename
  406. endif
  407. " If the user wants to always open the file in a tab, then open the file
  408. " in a tab. If it is already opened in a tab, then the cursor will be
  409. " moved to that tab.
  410. if g:MRU_Open_File_Use_Tabs
  411. call s:MRU_Open_File_In_Tab(a:filename, esc_fname)
  412. return
  413. endif
  414. " If the file is already open in one of the windows, jump to it
  415. let winnum = bufwinnr('^' . a:filename . '$')
  416. if winnum != -1
  417. if winnum != winnr()
  418. exe winnum . 'wincmd w'
  419. endif
  420. else
  421. if &modified || &buftype != '' || &previewwindow
  422. " Current buffer has unsaved changes or is a special buffer or is
  423. " the preview window. So open the file in a new window
  424. exe 'split ' . esc_fname
  425. else
  426. exe 'edit ' . esc_fname
  427. endif
  428. endif
  429. endfunction
  430. " MRU_Open_File_In_Tab
  431. " Open a file in a tab. If the file is already opened in a tab, jump to the
  432. " tab. Otherwise, create a new tab and open the file.
  433. " fname : Name of the file to open
  434. " esc_fname : File name with special characters escaped
  435. function! s:MRU_Open_File_In_Tab(fname, esc_fname)
  436. " If the selected file is already open in the current tab or in
  437. " another tab, jump to it. Otherwise open it in a new tab
  438. if bufwinnr('^' . a:fname . '$') == -1
  439. let tabnum = -1
  440. let i = 1
  441. let bnum = bufnr('^' . a:fname . '$')
  442. while i <= tabpagenr('$')
  443. if index(tabpagebuflist(i), bnum) != -1
  444. let tabnum = i
  445. break
  446. endif
  447. let i += 1
  448. endwhile
  449. if tabnum != -1
  450. " Goto the tab containing the file
  451. exe 'tabnext ' . i
  452. else
  453. " Open a new tab as the last tab page
  454. exe '999tabnew ' . a:esc_fname
  455. endif
  456. endif
  457. " Jump to the window containing the file
  458. let winnum = bufwinnr('^' . a:fname . '$')
  459. if winnum != winnr()
  460. exe winnum . 'wincmd w'
  461. endif
  462. endfunction
  463. " MRU_Window_Edit_File {{{1
  464. " fname : Name of the file to edit. May specify single or multiple
  465. " files.
  466. " edit_type : Specifies how to edit the file. Can be one of 'edit' or 'view'.
  467. " 'view' - Open the file as a read-only file
  468. " 'edit' - Edit the file as a regular file
  469. " multi : Specifies whether a single file or multiple files need to be
  470. " opened.
  471. " open_type : Specifies where to open the file. Can be one of 'useopen' or
  472. " 'newwin' or 'newtab'.
  473. " useopen - If the file is already present in a window, then
  474. " jump to that window. Otherwise, open the file in
  475. " the previous window.
  476. " newwin_horiz - Open the file in a new horizontal window.
  477. " newwin_vert - Open the file in a new vertical window.
  478. " newtab - Open the file in a new tab. If the file is already
  479. " opened in a tab, then jump to that tab.
  480. function! s:MRU_Window_Edit_File(fname, multi, edit_type, open_type)
  481. let esc_fname = s:MRU_escape_filename(a:fname)
  482. if a:open_type ==# 'newwin_horiz'
  483. " Edit the file in a new horizontally split window above the previous
  484. " window
  485. wincmd p
  486. exe 'belowright new ' . esc_fname
  487. elseif a:open_type ==# 'newwin_vert'
  488. " Edit the file in a new vertically split window above the previous
  489. " window
  490. wincmd p
  491. exe 'belowright vnew ' . esc_fname
  492. elseif a:open_type ==# 'newtab' || g:MRU_Open_File_Use_Tabs
  493. call s:MRU_Open_File_In_Tab(a:fname, esc_fname)
  494. else
  495. " If the selected file is already open in one of the windows,
  496. " jump to it
  497. let winnum = bufwinnr('^' . a:fname . '$')
  498. if winnum != -1
  499. exe winnum . 'wincmd w'
  500. else
  501. if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
  502. " Jump to the window from which the MRU window was opened
  503. if exists('s:MRU_last_buffer')
  504. let last_winnr = bufwinnr(s:MRU_last_buffer)
  505. if last_winnr != -1 && last_winnr != winnr()
  506. exe last_winnr . 'wincmd w'
  507. endif
  508. endif
  509. else
  510. if g:MRU_Use_Current_Window == 0
  511. " Goto the previous window
  512. " If MRU_Use_Current_Window is set to one, then the
  513. " current window is used to open the file
  514. wincmd p
  515. endif
  516. endif
  517. let split_window = 0
  518. if &modified || &previewwindow || a:multi
  519. " Current buffer has unsaved changes or is the preview window
  520. " or the user is opening multiple files
  521. " So open the file in a new window
  522. let split_window = 1
  523. endif
  524. if &buftype != ''
  525. " Current buffer is a special buffer (maybe used by a plugin)
  526. if g:MRU_Use_Current_Window == 0 ||
  527. \ bufnr('%') != bufnr('__MRU_Files__')
  528. let split_window = 1
  529. endif
  530. endif
  531. " Edit the file
  532. if split_window
  533. " Current buffer has unsaved changes or is a special buffer or
  534. " is the preview window. So open the file in a new window
  535. if a:edit_type ==# 'edit'
  536. exe 'split ' . esc_fname
  537. else
  538. exe 'sview ' . esc_fname
  539. endif
  540. else
  541. if a:edit_type ==# 'edit'
  542. exe 'edit ' . esc_fname
  543. else
  544. exe 'view ' . esc_fname
  545. endif
  546. endif
  547. endif
  548. endif
  549. endfunction
  550. " MRU_Select_File_Cmd {{{1
  551. " Open a file selected from the MRU window
  552. "
  553. " 'opt' has two values separated by comma. The first value specifies how to
  554. " edit the file and can be either 'edit' or 'view'. The second value
  555. " specifies where to open the file. It can take one of the following values:
  556. " 'useopen' to open file in the previous window
  557. " 'newwin_horiz' to open the file in a new horizontal split window
  558. " 'newwin_vert' to open the file in a new vertical split window.
  559. " 'newtab' to open the file in a new tab.
  560. " If multiple file names are selected using visual mode, then open multiple
  561. " files (either in split windows or tabs)
  562. function! s:MRU_Select_File_Cmd(opt) range
  563. let [edit_type, open_type] = split(a:opt, ',')
  564. let fnames = getline(a:firstline, a:lastline)
  565. if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
  566. " Automatically close the window if the file window is
  567. " not used to display the MRU list.
  568. silent! close
  569. endif
  570. let multi = 0
  571. for f in fnames
  572. if f == ''
  573. continue
  574. endif
  575. " The text in the MRU window contains the filename in parenthesis
  576. let file = matchstr(f, '(\zs.*\ze)')
  577. call s:MRU_Window_Edit_File(file, multi, edit_type, open_type)
  578. if a:firstline != a:lastline
  579. " Opening multiple files
  580. let multi = 1
  581. endif
  582. endfor
  583. endfunction
  584. " MRU_Warn_Msg {{{1
  585. " Display a warning message
  586. function! s:MRU_Warn_Msg(msg)
  587. echohl WarningMsg
  588. echo a:msg
  589. echohl None
  590. endfunction
  591. " MRU_Open_Window {{{1
  592. " Display the Most Recently Used file list in a temporary window.
  593. " If the optional argument is supplied, then it specifies the pattern of files
  594. " to selectively display in the MRU window.
  595. function! s:MRU_Open_Window(...)
  596. " Load the latest MRU file list
  597. call s:MRU_LoadList()
  598. " Check for empty MRU list
  599. if empty(s:MRU_files)
  600. call s:MRU_Warn_Msg('MRU file list is empty')
  601. return
  602. endif
  603. " Save the current buffer number. This is used later to open a file when a
  604. " entry is selected from the MRU window. The window number is not saved,
  605. " as the window number will change when new windows are opened.
  606. let s:MRU_last_buffer = bufnr('%')
  607. let bname = '__MRU_Files__'
  608. " If the window is already open, jump to it
  609. let winnum = bufwinnr(bname)
  610. if winnum != -1
  611. if winnr() != winnum
  612. " If not already in the window, jump to it
  613. exe winnum . 'wincmd w'
  614. endif
  615. setlocal modifiable
  616. " Delete the contents of the buffer to the black-hole register
  617. silent! %delete _
  618. else
  619. if g:MRU_Use_Current_Window
  620. " Reuse the current window
  621. "
  622. " If the __MRU_Files__ buffer exists, then reuse it. Otherwise open
  623. " a new buffer
  624. let bufnum = bufnr(bname)
  625. if bufnum == -1
  626. let cmd = 'edit ' . bname
  627. else
  628. let cmd = 'buffer ' . bufnum
  629. endif
  630. exe cmd
  631. if bufnr('%') != bufnr(bname)
  632. " Failed to edit the MRU buffer
  633. return
  634. endif
  635. else
  636. " Open a new window at the bottom
  637. " If the __MRU_Files__ buffer exists, then reuse it. Otherwise open
  638. " a new buffer
  639. let bufnum = bufnr(bname)
  640. if bufnum == -1
  641. let wcmd = bname
  642. else
  643. let wcmd = '+buffer' . bufnum
  644. endif
  645. exe 'silent! botright ' . g:MRU_Window_Height . 'split ' . wcmd
  646. endif
  647. endif
  648. " Mark the buffer as scratch
  649. setlocal buftype=nofile
  650. setlocal bufhidden=delete
  651. setlocal noswapfile
  652. setlocal nowrap
  653. setlocal nobuflisted
  654. " Set the 'filetype' to 'mru'. This allows the user to apply custom
  655. " syntax highlighting or other changes to the MRU bufer.
  656. setlocal filetype=mru
  657. " Use fixed height for the MRU window
  658. setlocal winfixheight
  659. " Setup the cpoptions properly for the maps to work
  660. let old_cpoptions = &cpoptions
  661. set cpoptions&vim
  662. " Create mappings to select and edit a file from the MRU list
  663. nnoremap <buffer> <silent> <CR>
  664. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  665. vnoremap <buffer> <silent> <CR>
  666. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  667. nnoremap <buffer> <silent> o
  668. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_horiz')<CR>
  669. vnoremap <buffer> <silent> o
  670. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_horiz')<CR>
  671. nnoremap <buffer> <silent> O
  672. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_vert')<CR>
  673. vnoremap <buffer> <silent> O
  674. \ :call <SID>MRU_Select_File_Cmd('edit,newwin_vert')<CR>
  675. nnoremap <buffer> <silent> t
  676. \ :call <SID>MRU_Select_File_Cmd('edit,newtab')<CR>
  677. vnoremap <buffer> <silent> t
  678. \ :call <SID>MRU_Select_File_Cmd('edit,newtab')<CR>
  679. nnoremap <buffer> <silent> v
  680. \ :call <SID>MRU_Select_File_Cmd('view,useopen')<CR>
  681. nnoremap <buffer> <silent> u :MRU<CR>
  682. nnoremap <buffer> <silent> <2-LeftMouse>
  683. \ :call <SID>MRU_Select_File_Cmd('edit,useopen')<CR>
  684. nnoremap <buffer> <silent> q :close<CR>
  685. " Restore the previous cpoptions settings
  686. let &cpoptions = old_cpoptions
  687. " Display the MRU list
  688. if a:0 == 0
  689. " No search pattern specified. Display the complete list
  690. let m = copy(s:MRU_files)
  691. else
  692. " Display only the entries matching the specified pattern
  693. " First try using it as a literal pattern
  694. let m = filter(copy(s:MRU_files), 'stridx(v:val, a:1) != -1')
  695. if len(m) == 0
  696. " No match. Try using it as a regular expression
  697. let m = filter(copy(s:MRU_files), 'v:val =~# a:1')
  698. endif
  699. endif
  700. " Get the tail part of the file name (without the directory) and display
  701. " it along with the full path
  702. let output = map(m, 'fnamemodify(v:val, ":t") . " (" . v:val . ")"')
  703. silent! 0put =output
  704. " Delete the empty line at the end of the buffer
  705. silent! $delete _
  706. " Move the cursor to the beginning of the file
  707. normal! gg
  708. setlocal nomodifiable
  709. endfunction
  710. " MRU_Complete {{{1
  711. " Command-line completion function used by :MRU command
  712. function! s:MRU_Complete(ArgLead, CmdLine, CursorPos)
  713. if a:ArgLead == ''
  714. " Return the complete list of MRU files
  715. return s:MRU_files
  716. else
  717. " Return only the files matching the specified pattern
  718. return filter(copy(s:MRU_files), 'v:val =~? a:ArgLead')
  719. endif
  720. endfunction
  721. " MRU_Cmd {{{1
  722. " Function to handle the MRU command
  723. " pat - File name pattern passed to the MRU command
  724. function! s:MRU_Cmd(pat)
  725. if a:pat == ''
  726. " No arguments specified. Open the MRU window
  727. call s:MRU_Open_Window()
  728. return
  729. endif
  730. " Load the latest MRU file
  731. call s:MRU_LoadList()
  732. " Empty MRU list
  733. if empty(s:MRU_files)
  734. call s:MRU_Warn_Msg('MRU file list is empty')
  735. return
  736. endif
  737. " First use the specified string as a literal string and search for
  738. " filenames containing the string. If only one filename is found,
  739. " then edit it (unless the user wants to open the MRU window always)
  740. let m = filter(copy(s:MRU_files), 'stridx(v:val, a:pat) != -1')
  741. if len(m) > 0
  742. if len(m) == 1 && !g:MRU_Window_Open_Always
  743. call s:MRU_Edit_File(m[0], 0)
  744. return
  745. endif
  746. " More than one file matches. Try find an accurate match
  747. let new_m = filter(m, 'v:val ==# a:pat')
  748. if len(new_m) == 1 && !g:MRU_Window_Open_Always
  749. call s:MRU_Edit_File(new_m[0], 0)
  750. return
  751. endif
  752. " Couldn't find an exact match, open the MRU window with all the
  753. " files matching the pattern.
  754. call s:MRU_Open_Window(a:pat)
  755. return
  756. endif
  757. " Use the specified string as a regular expression pattern and search
  758. " for filenames matching the pattern
  759. let m = filter(copy(s:MRU_files), 'v:val =~? a:pat')
  760. if len(m) == 0
  761. " If an existing file (not present in the MRU list) is specified,
  762. " then open the file.
  763. if filereadable(a:pat)
  764. call s:MRU_Edit_File(a:pat, 0)
  765. return
  766. endif
  767. " No filenames matching the specified pattern are found
  768. call s:MRU_Warn_Msg("MRU file list doesn't contain " .
  769. \ "files matching " . a:pat)
  770. return
  771. endif
  772. if len(m) == 1 && !g:MRU_Window_Open_Always
  773. call s:MRU_Edit_File(m[0], 0)
  774. return
  775. endif
  776. call s:MRU_Open_Window(a:pat)
  777. endfunction
  778. " MRU_add_files_to_menu {{{1
  779. " Adds a list of files to the "Recent Files" sub menu under the "File" menu.
  780. " prefix - Prefix to use for each of the menu entries
  781. " file_list - List of file names to add to the menu
  782. function! s:MRU_add_files_to_menu(prefix, file_list)
  783. for fname in a:file_list
  784. " Escape special characters in the filename
  785. let esc_fname = escape(fnamemodify(fname, ':t'), ".\\" .
  786. \ s:esc_filename_chars)
  787. let esc_fname = substitute(esc_fname, '&', '&&', 'g')
  788. " Truncate the directory name if it is long
  789. let dir_name = fnamemodify(fname, ':h')
  790. let len = strlen(dir_name)
  791. " Shorten long file names by adding only few characters from
  792. " the beginning and end.
  793. if len > 30
  794. let dir_name = strpart(dir_name, 0, 10) .
  795. \ '...' .
  796. \ strpart(dir_name, len - 20)
  797. endif
  798. let esc_dir_name = escape(dir_name, ".\\" . s:esc_filename_chars)
  799. let esc_dir_name = substitute(esc_dir_name, '&', '&&', 'g')
  800. let menu_path = '&File.&Recent\ Files.' . a:prefix . esc_fname .
  801. \ '\ (' . esc_dir_name . ')'
  802. let esc_mfname = s:MRU_escape_filename(fname)
  803. exe 'anoremenu <silent> ' . menu_path .
  804. \ " :call <SID>MRU_Edit_File('" . esc_mfname . "', 1)<CR>"
  805. exe 'tmenu ' . menu_path . ' Edit file ' . esc_mfname
  806. endfor
  807. endfunction
  808. " MRU_Refresh_Menu {{{1
  809. " Refresh the MRU menu
  810. function! s:MRU_Refresh_Menu()
  811. if !has('menu') || !g:MRU_Add_Menu
  812. " No support for menus
  813. return
  814. endif
  815. " Setup the cpoptions properly for the maps to work
  816. let old_cpoptions = &cpoptions
  817. set cpoptions&vim
  818. " Remove the MRU menu
  819. " To retain the teared-off MRU menu, we need to add a dummy entry
  820. silent! unmenu &File.&Recent\ Files
  821. " The menu priority of the File menu is 10. If the MRU plugin runs
  822. " first before menu.vim, the File menu order may not be correct.
  823. " So specify the priority of the File menu here.
  824. 10noremenu &File.&Recent\ Files.Dummy <Nop>
  825. silent! unmenu! &File.&Recent\ Files
  826. anoremenu <silent> &File.&Recent\ Files.Refresh\ list
  827. \ :call <SID>MRU_LoadList()<CR>
  828. exe 'tmenu File.&Recent\ Files.Refresh\ list Reload the MRU file list from '
  829. \ . s:MRU_escape_filename(g:MRU_File)
  830. anoremenu File.&Recent\ Files.-SEP1- :
  831. " Add the filenames in the MRU list to the menu
  832. let entry_cnt = len(s:MRU_files)
  833. if entry_cnt > g:MRU_Max_Menu_Entries
  834. " Show only MRU_Max_Menu_Entries file names in the menu
  835. let mru_list = s:MRU_files[0 : g:MRU_Max_Menu_Entries - 1]
  836. let entry_cnt = g:MRU_Max_Menu_Entries
  837. else
  838. let mru_list = s:MRU_files
  839. endif
  840. if entry_cnt > g:MRU_Max_Submenu_Entries
  841. " Split the MRU menu into sub-menus
  842. for start_idx in range(0, entry_cnt, g:MRU_Max_Submenu_Entries)
  843. let last_idx = start_idx + g:MRU_Max_Submenu_Entries - 1
  844. if last_idx >= entry_cnt
  845. let last_idx = entry_cnt - 1
  846. endif
  847. let prefix = 'Files\ (' . (start_idx + 1) . '\.\.\.' .
  848. \ (last_idx + 1) . ').'
  849. call s:MRU_add_files_to_menu(prefix,
  850. \ mru_list[start_idx : last_idx])
  851. endfor
  852. else
  853. call s:MRU_add_files_to_menu('', mru_list)
  854. endif
  855. " Remove the dummy menu entry
  856. unmenu &File.&Recent\ Files.Dummy
  857. " Restore the previous cpoptions settings
  858. let &cpoptions = old_cpoptions
  859. endfunction
  860. " Load the MRU list on plugin startup
  861. call s:MRU_LoadList()
  862. " MRU autocommands {{{1
  863. " Autocommands to detect the most recently used files
  864. autocmd BufRead * call s:MRU_AddFile(expand('<abuf>'))
  865. autocmd BufNewFile * call s:MRU_AddFile(expand('<abuf>'))
  866. autocmd BufWritePost * call s:MRU_AddFile(expand('<abuf>'))
  867. " The ':vimgrep' command adds all the files searched to the buffer list.
  868. " This also modifies the MRU list, even though the user didn't edit the
  869. " files. Use the following autocmds to prevent this.
  870. autocmd QuickFixCmdPre *vimgrep* let s:mru_list_locked = 1
  871. autocmd QuickFixCmdPost *vimgrep* let s:mru_list_locked = 0
  872. " Command to open the MRU window
  873. command! -nargs=? -complete=customlist,s:MRU_Complete MRU
  874. \ call s:MRU_Cmd(<q-args>)
  875. command! -nargs=? -complete=customlist,s:MRU_Complete Mru
  876. \ call s:MRU_Cmd(<q-args>)
  877. " }}}
  878. " restore 'cpo'
  879. let &cpo = s:cpo_save
  880. unlet s:cpo_save
  881. " vim:set foldenable foldmethod=marker: