Skip to content

Commit b6b622f

Browse files
committed
Version 3.2 (Sep 23, 2008)
1 parent 4018cd6 commit b6b622f

File tree

1 file changed

+127
-41
lines changed

1 file changed

+127
-41
lines changed

plugin/mru.vim

+127-41
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
" File: mru.vim
22
" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
3-
" Version: 3.1
4-
" Last Modified: February 17, 2008
3+
" Version: 3.2
4+
" Last Modified: September 22, 2008
55
"
66
" Overview
77
" --------
@@ -47,10 +47,10 @@
4747
"
4848
" Usage
4949
" -----
50-
" You can use the ":MRU" command to list all the most recently edited file
51-
" names. The file names will be listed in a temporary Vim window. If the MRU
52-
" window is already opened, then the MRU list displayed in the window will be
53-
" refreshed.
50+
" To list and edit files from the MRU list, you have to use the ":MRU"
51+
" command. The ":MRU" command displays the MRU file list in a temporary Vim
52+
" window. If the MRU window is already opened, then the MRU list displayed in
53+
" the window is refreshed.
5454
"
5555
" If you are using GUI Vim, then the names of the recently edited files are
5656
" added to the "File->Recent Files" menu. You can select the name of a file
@@ -99,11 +99,11 @@
9999
" plugin. Set the following variables in your .vimrc file using the 'let'
100100
" command.
101101
"
102-
" The list of recently edit file names is stored in the file specified by the
102+
" The list of recently edited file names is stored in the file specified by the
103103
" MRU_File variable. The default setting for this variable is
104-
" $HOME/.vim_mru_files for Unix systems and $VIM/_vim_mru_files for non-Unix
105-
" systems. You can change this variable to point to a file by adding the
106-
" following line to the .vimrc file:
104+
" $HOME/.vim_mru_files for Unix-like systems and $USERPROFILE/_vim_mru_files
105+
" for MS-Windows systems. You can change this variable to point to a file by
106+
" adding the following line to the .vimrc file:
107107
"
108108
" let MRU_File = 'd:\myhome\_vim_mru_files'
109109
"
@@ -126,6 +126,16 @@
126126
"
127127
" The specified pattern should be a Vim regular expression pattern.
128128
"
129+
" If you want to add only file names matching a set of patterns to the MRU
130+
" list, then you can set the MRU_Include_Files variable. This variable should
131+
" be set to a Vim regular expression pattern. For example, to add only .c and
132+
" .h files to the MRU list, you can set this variable as below:
133+
"
134+
" let MRU_Include_Files = '\.c$\|\.h$'
135+
"
136+
" By default, MRU_Include_Files is set to an empty string and all the edited
137+
" filenames are added to the MRU list.
138+
"
129139
" The default height of the MRU window is 8. You can set the MRU_Window_Height
130140
" variable to change the window height.
131141
"
@@ -177,6 +187,11 @@ if !exists('MRU_Exclude_Files')
177187
let MRU_Exclude_Files = ''
178188
endif
179189

190+
" Files to include in the MRU list
191+
if !exists('MRU_Include_Files')
192+
let MRU_Include_Files = ''
193+
endif
194+
180195
" Height of the MRU window
181196
" Default height is 8
182197
if !exists('MRU_Window_Height')
@@ -192,10 +207,16 @@ if !exists('MRU_Auto_Close')
192207
endif
193208

194209
if !exists('MRU_File')
195-
if has('unix')
196-
let MRU_File = $HOME . "/.vim_mru_files"
210+
if has('unix') || has('macunix')
211+
let MRU_File = $HOME . '/.vim_mru_files'
197212
else
198-
let MRU_File = $VIM . "/_vim_mru_files"
213+
let MRU_File = $VIM . '/_vim_mru_files'
214+
if has('win32')
215+
" MS-Windows
216+
if $USERPROFILE != ''
217+
let MRU_File = $USERPROFILE . '\_vim_mru_files'
218+
endif
219+
endif
199220
endif
200221
endif
201222

@@ -204,19 +225,26 @@ if !exists('MRU_Add_Menu')
204225
let MRU_Add_Menu = 1
205226
endif
206227

228+
" Control to temporarily lock the MRU list. Used to prevent files from
229+
" getting added to the MRU list when the ':vimgrep' command is executed.
230+
let s:mru_list_locked = 0
231+
207232
" MRU_LoadList
208233
" Load the latest MRU file list from the MRU file
209234
function! s:MRU_LoadList()
210235
" Read the list from the MRU file.
211236
if filereadable(g:MRU_File)
212237
let s:MRU_files = readfile(g:MRU_File)
213-
if s:MRU_files[0] =~# '^" Most recently edited files in Vim'
214-
" Generated by the previous version of the MRU plugin. Ignore the
215-
" list
238+
if s:MRU_files[0] =~# '^\s*" Most recently edited files in Vim'
239+
" Generated by the previous version of the MRU plugin.
240+
" Discard the list.
216241
let s:MRU_files = []
217242
elseif s:MRU_files[0] =~# '^#'
218243
" Remove the comment line
219244
call remove(s:MRU_files, 0)
245+
else
246+
" Unsupported format
247+
let s:MRU_files = []
220248
endif
221249
else
222250
let s:MRU_files = []
@@ -238,6 +266,11 @@ endfunction
238266
" MRU_AddFile
239267
" Add a file to the MRU file list
240268
function! s:MRU_AddFile(acmd_bufnr)
269+
if s:mru_list_locked
270+
" MRU list is currently locked
271+
return
272+
endif
273+
241274
" Get the full path to the filename
242275
let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
243276
if fname == ''
@@ -249,16 +282,24 @@ function! s:MRU_AddFile(acmd_bufnr)
249282
return
250283
endif
251284

285+
if g:MRU_Include_Files != ''
286+
" If MRU_Include_Files is set, include only files matching the
287+
" specified pattern
288+
if fname !~# g:MRU_Include_Files
289+
return
290+
endif
291+
endif
292+
252293
if g:MRU_Exclude_Files != ''
253294
" Do not add files matching the pattern specified in the
254295
" MRU_Exclude_Files to the MRU list
255-
if fname =~? g:MRU_Exclude_Files
296+
if fname =~# g:MRU_Exclude_Files
256297
return
257298
endif
258299
endif
259300

260-
" If the filename is already present in the MRU list, then move
261-
" it to the beginning of the list
301+
" If the filename is not already present in the MRU list and is not
302+
" readable then ignore it
262303
let idx = index(s:MRU_files, fname)
263304
if idx == -1
264305
if !filereadable(fname)
@@ -276,7 +317,7 @@ function! s:MRU_AddFile(acmd_bufnr)
276317
" Add the new file list to the beginning of the updated old file list
277318
call insert(s:MRU_files, fname, 0)
278319

279-
" Return the trimmed list
320+
" Trim the list
280321
if len(s:MRU_files) > g:MRU_Max_Entries
281322
call remove(s:MRU_files, g:MRU_Max_Entries, -1)
282323
endif
@@ -299,12 +340,23 @@ function! s:MRU_AddFile(acmd_bufnr)
299340
endif
300341
endfunction
301342

343+
" Special characters in file names that should be escaped (for security
344+
" reasons)
345+
let s:esc_filename_chars = ' *?[{`$%#"|!<>();&' . "'\t\n"
346+
function! s:MRU_escape_filename(fname)
347+
return escape(a:fname, s:esc_filename_chars)
348+
endfunction
349+
302350
" MRU_Edit_File
303351
" Edit the specified file
304-
function! s:MRU_Edit_File(filename)
305-
let fname = escape(a:filename, ' %#"')
352+
function! s:MRU_Edit_File(filename, sanitized)
353+
if !a:sanitized
354+
let esc_fname = s:MRU_escape_filename(a:filename)
355+
else
356+
let esc_fname = a:filename
357+
endif
306358
" If the file is already open in one of the windows, jump to it
307-
let winnum = bufwinnr('^' . fname . '$')
359+
let winnum = bufwinnr('^' . a:filename . '$')
308360
if winnum != -1
309361
if winnum != winnr()
310362
exe winnum . 'wincmd w'
@@ -313,9 +365,9 @@ function! s:MRU_Edit_File(filename)
313365
if &modified || &buftype != '' || &previewwindow
314366
" Current buffer has unsaved changes or is a special buffer or is
315367
" the preview window. So open the file in a new window
316-
exe 'split ' . fname
368+
exe 'split ' . esc_fname
317369
else
318-
exe 'edit ' . fname
370+
exe 'edit ' . esc_fname
319371
endif
320372
endif
321373
endfunction
@@ -332,11 +384,11 @@ function! s:MRU_Window_Edit_File(win_opt)
332384
return
333385
endif
334386

335-
let fname = escape(fname, ' %#"')
387+
let esc_fname = s:MRU_escape_filename(fname)
336388

337389
if a:win_opt == 'newwin'
338390
" Edit the file in a new window
339-
exe 'leftabove new ' . fname
391+
exe 'leftabove new ' . esc_fname
340392

341393
if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
342394
" Go back to the MRU window and close it
@@ -375,7 +427,7 @@ function! s:MRU_Window_Edit_File(win_opt)
375427
exe 'tabnext ' . i
376428
else
377429
" Open a new tab as the last tab page
378-
exe '999tabnew ' . fname
430+
exe '999tabnew ' . esc_fname
379431
endif
380432
endif
381433

@@ -427,9 +479,9 @@ function! s:MRU_Window_Edit_File(win_opt)
427479
if &modified || &buftype != '' || &previewwindow
428480
" Current buffer has unsaved changes or is a special buffer or
429481
" is the preview window. So open the file in a new window
430-
exe 'split ' . fname
482+
exe 'split ' . esc_fname
431483
else
432-
exe 'edit ' . fname
484+
exe 'edit ' . esc_fname
433485
endif
434486
endif
435487
endif
@@ -546,11 +598,17 @@ function! s:MRU_Open_Window(...)
546598
silent! 0put =s:MRU_files
547599
else
548600
" Display only the entries matching the specified pattern
549-
silent! 0put =filter(copy(s:MRU_files), 'v:val =~? a:1')
601+
" First try using it as a literal pattern
602+
let m = filter(copy(s:MRU_files), 'stridx(v:val, a:1) != -1')
603+
if len(m) == 0
604+
" No match. Try using it as a regular expression
605+
let m = filter(copy(s:MRU_files), 'v:val =~# a:1')
606+
endif
607+
silent! 0put =m
550608
endif
551609

552610
" Move the cursor to the beginning of the file
553-
exe 1
611+
normal! gg
554612

555613
setlocal nomodifiable
556614
endfunction
@@ -588,8 +646,21 @@ function! s:MRU_Cmd(pat)
588646
" filenames containing the string. If only one filename is found,
589647
" then edit it.
590648
let m = filter(copy(s:MRU_files), 'stridx(v:val, a:pat) != -1')
591-
if len(m) == 1
592-
call s:MRU_Edit_File(m[0])
649+
if len(m) > 0
650+
if len(m) == 1
651+
call s:MRU_Edit_File(m[0], 0)
652+
return
653+
endif
654+
655+
" More than one file matches. Try find an accurate match
656+
let new_m = filter(m, 'v:val ==# a:pat')
657+
if len(new_m) == 1
658+
call s:MRU_Edit_File(new_m[0], 0)
659+
return
660+
endif
661+
662+
" Couldn't find an exact match, open the MRU window
663+
call s:MRU_Open_Window(a:pat)
593664
return
594665
endif
595666

@@ -605,7 +676,7 @@ function! s:MRU_Cmd(pat)
605676
endif
606677

607678
if len(m) == 1
608-
call s:MRU_Edit_File(m[0])
679+
call s:MRU_Edit_File(m[0], 0)
609680
return
610681
endif
611682

@@ -615,7 +686,9 @@ endfunction
615686
function! s:MRU_add_files_to_menu(prefix, file_list)
616687
for fname in a:file_list
617688
" Escape special characters in the filename
618-
let esc_fname = escape(fnamemodify(fname, ':t'), ". \\|\t%#")
689+
let esc_fname = escape(fnamemodify(fname, ':t'), ".\\" .
690+
\ s:esc_filename_chars)
691+
let esc_fname = substitute(esc_fname, '&', '&&', 'g')
619692

620693
" Truncate the directory name if it is long
621694
let dir_name = fnamemodify(fname, ':h')
@@ -627,11 +700,15 @@ function! s:MRU_add_files_to_menu(prefix, file_list)
627700
\ '...' .
628701
\ strpart(dir_name, len - 20)
629702
endif
630-
let esc_dir_name = escape(dir_name, ". \\|\t")
631-
632-
exe 'anoremenu <silent> &File.Recent\ Files.' . a:prefix . esc_fname .
633-
\ '\ (' . esc_dir_name . ')' .
634-
\ " :call <SID>MRU_Edit_File('" . fname . "')<CR>"
703+
let esc_dir_name = escape(dir_name, ".\\" . s:esc_filename_chars)
704+
let esc_dir_name = substitute(esc_dir_name, '&', '&&', 'g')
705+
706+
let menu_path = '&File.Recent\ Files.' . a:prefix . esc_fname .
707+
\ '\ (' . esc_dir_name . ')'
708+
let esc_mfname = s:MRU_escape_filename(fname)
709+
exe 'anoremenu <silent> ' . menu_path .
710+
\ " :call <SID>MRU_Edit_File('" . esc_mfname . "', 1)<CR>"
711+
exe 'tmenu ' . menu_path . ' Edit file ' . esc_mfname
635712
endfor
636713
endfunction
637714

@@ -658,11 +735,14 @@ function! s:MRU_Refresh_Menu()
658735

659736
anoremenu <silent> &File.Recent\ Files.Refresh\ list
660737
\ :call <SID>MRU_LoadList()<CR>
738+
exe 'tmenu File.Recent\ Files.Refresh\ list Reload the MRU file list from '
739+
\ . s:MRU_escape_filename(g:MRU_File)
661740
anoremenu File.Recent\ Files.-SEP1- :
662741

663742
" Add the filenames in the MRU list to the menu
664743
let entry_cnt = len(s:MRU_files)
665744
if entry_cnt > 10
745+
" Split the MRU menu into sub-menus
666746
for start_idx in range(0, entry_cnt, 10)
667747
let last_idx = start_idx + 9
668748
if last_idx >= entry_cnt
@@ -692,6 +772,12 @@ autocmd BufRead * call s:MRU_AddFile(expand('<abuf>'))
692772
autocmd BufNewFile * call s:MRU_AddFile(expand('<abuf>'))
693773
autocmd BufWritePost * call s:MRU_AddFile(expand('<abuf>'))
694774

775+
" The ':vimgrep' command adds all the files searched to the buffer list.
776+
" This also modifies the MRU list, even though the user didn't edit the
777+
" files. Use the following autocmds to prevent this.
778+
autocmd QuickFixCmdPre *vimgrep* let s:mru_list_locked = 1
779+
autocmd QuickFixCmdPost *vimgrep* let s:mru_list_locked = 0
780+
695781
" Command to open the MRU window
696782
command! -nargs=? -complete=customlist,s:MRU_Complete MRU
697783
\ call s:MRU_Cmd(<q-args>)

0 commit comments

Comments
 (0)