|
|
@@ -1,7 +1,7 @@
|
|
|
" File: mru.vim
|
|
|
" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
|
|
|
-" Version: 3.1
|
|
|
-" Last Modified: February 17, 2008
|
|
|
+" Version: 3.2
|
|
|
+" Last Modified: September 22, 2008
|
|
|
"
|
|
|
" Overview
|
|
|
" --------
|
|
|
@@ -47,10 +47,10 @@
|
|
|
"
|
|
|
" Usage
|
|
|
" -----
|
|
|
-" You can use the ":MRU" command to list all the most recently edited file
|
|
|
-" names. The file names will be listed in a temporary Vim window. If the MRU
|
|
|
-" window is already opened, then the MRU list displayed in the window will be
|
|
|
-" refreshed.
|
|
|
+" To list and edit files from the MRU list, you have to use the ":MRU"
|
|
|
+" command. The ":MRU" command displays the MRU file list in a temporary Vim
|
|
|
+" window. If the MRU window is already opened, then the MRU list displayed in
|
|
|
+" the window is refreshed.
|
|
|
"
|
|
|
" If you are using GUI Vim, then the names of the recently edited files are
|
|
|
" added to the "File->Recent Files" menu. You can select the name of a file
|
|
|
@@ -99,11 +99,11 @@
|
|
|
" plugin. Set the following variables in your .vimrc file using the 'let'
|
|
|
" command.
|
|
|
"
|
|
|
-" The list of recently edit file names is stored in the file specified by the
|
|
|
+" The list of recently edited file names is stored in the file specified by the
|
|
|
" MRU_File variable. The default setting for this variable is
|
|
|
-" $HOME/.vim_mru_files for Unix systems and $VIM/_vim_mru_files for non-Unix
|
|
|
-" systems. You can change this variable to point to a file by adding the
|
|
|
-" following line to the .vimrc file:
|
|
|
+" $HOME/.vim_mru_files for Unix-like systems and $USERPROFILE/_vim_mru_files
|
|
|
+" for MS-Windows systems. You can change this variable to point to a file by
|
|
|
+" adding the following line to the .vimrc file:
|
|
|
"
|
|
|
" let MRU_File = 'd:\myhome\_vim_mru_files'
|
|
|
"
|
|
|
@@ -126,6 +126,16 @@
|
|
|
"
|
|
|
" The specified pattern should be a Vim regular expression pattern.
|
|
|
"
|
|
|
+" If you want to add only file names matching a set of patterns to the MRU
|
|
|
+" list, then you can set the MRU_Include_Files variable. This variable should
|
|
|
+" be set to a Vim regular expression pattern. For example, to add only .c and
|
|
|
+" .h files to the MRU list, you can set this variable as below:
|
|
|
+"
|
|
|
+" let MRU_Include_Files = '\.c$\|\.h$'
|
|
|
+"
|
|
|
+" By default, MRU_Include_Files is set to an empty string and all the edited
|
|
|
+" filenames are added to the MRU list.
|
|
|
+"
|
|
|
" The default height of the MRU window is 8. You can set the MRU_Window_Height
|
|
|
" variable to change the window height.
|
|
|
"
|
|
|
@@ -177,6 +187,11 @@ if !exists('MRU_Exclude_Files')
|
|
|
let MRU_Exclude_Files = ''
|
|
|
endif
|
|
|
|
|
|
+" Files to include in the MRU list
|
|
|
+if !exists('MRU_Include_Files')
|
|
|
+ let MRU_Include_Files = ''
|
|
|
+endif
|
|
|
+
|
|
|
" Height of the MRU window
|
|
|
" Default height is 8
|
|
|
if !exists('MRU_Window_Height')
|
|
|
@@ -192,10 +207,16 @@ if !exists('MRU_Auto_Close')
|
|
|
endif
|
|
|
|
|
|
if !exists('MRU_File')
|
|
|
- if has('unix')
|
|
|
- let MRU_File = $HOME . "/.vim_mru_files"
|
|
|
+ if has('unix') || has('macunix')
|
|
|
+ let MRU_File = $HOME . '/.vim_mru_files'
|
|
|
else
|
|
|
- let MRU_File = $VIM . "/_vim_mru_files"
|
|
|
+ let MRU_File = $VIM . '/_vim_mru_files'
|
|
|
+ if has('win32')
|
|
|
+ " MS-Windows
|
|
|
+ if $USERPROFILE != ''
|
|
|
+ let MRU_File = $USERPROFILE . '\_vim_mru_files'
|
|
|
+ endif
|
|
|
+ endif
|
|
|
endif
|
|
|
endif
|
|
|
|
|
|
@@ -204,19 +225,26 @@ if !exists('MRU_Add_Menu')
|
|
|
let MRU_Add_Menu = 1
|
|
|
endif
|
|
|
|
|
|
+" Control to temporarily lock the MRU list. Used to prevent files from
|
|
|
+" getting added to the MRU list when the ':vimgrep' command is executed.
|
|
|
+let s:mru_list_locked = 0
|
|
|
+
|
|
|
" MRU_LoadList
|
|
|
" Load the latest MRU file list from the MRU file
|
|
|
function! s:MRU_LoadList()
|
|
|
" Read the list from the MRU file.
|
|
|
if filereadable(g:MRU_File)
|
|
|
let s:MRU_files = readfile(g:MRU_File)
|
|
|
- if s:MRU_files[0] =~# '^" Most recently edited files in Vim'
|
|
|
- " Generated by the previous version of the MRU plugin. Ignore the
|
|
|
- " list
|
|
|
+ if s:MRU_files[0] =~# '^\s*" Most recently edited files in Vim'
|
|
|
+ " Generated by the previous version of the MRU plugin.
|
|
|
+ " Discard the list.
|
|
|
let s:MRU_files = []
|
|
|
elseif s:MRU_files[0] =~# '^#'
|
|
|
" Remove the comment line
|
|
|
call remove(s:MRU_files, 0)
|
|
|
+ else
|
|
|
+ " Unsupported format
|
|
|
+ let s:MRU_files = []
|
|
|
endif
|
|
|
else
|
|
|
let s:MRU_files = []
|
|
|
@@ -238,6 +266,11 @@ endfunction
|
|
|
" MRU_AddFile
|
|
|
" Add a file to the MRU file list
|
|
|
function! s:MRU_AddFile(acmd_bufnr)
|
|
|
+ if s:mru_list_locked
|
|
|
+ " MRU list is currently locked
|
|
|
+ return
|
|
|
+ endif
|
|
|
+
|
|
|
" Get the full path to the filename
|
|
|
let fname = fnamemodify(bufname(a:acmd_bufnr + 0), ':p')
|
|
|
if fname == ''
|
|
|
@@ -249,16 +282,24 @@ function! s:MRU_AddFile(acmd_bufnr)
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
+ if g:MRU_Include_Files != ''
|
|
|
+ " If MRU_Include_Files is set, include only files matching the
|
|
|
+ " specified pattern
|
|
|
+ if fname !~# g:MRU_Include_Files
|
|
|
+ return
|
|
|
+ endif
|
|
|
+ endif
|
|
|
+
|
|
|
if g:MRU_Exclude_Files != ''
|
|
|
" Do not add files matching the pattern specified in the
|
|
|
" MRU_Exclude_Files to the MRU list
|
|
|
- if fname =~? g:MRU_Exclude_Files
|
|
|
+ if fname =~# g:MRU_Exclude_Files
|
|
|
return
|
|
|
endif
|
|
|
endif
|
|
|
|
|
|
- " If the filename is already present in the MRU list, then move
|
|
|
- " it to the beginning of the list
|
|
|
+ " If the filename is not already present in the MRU list and is not
|
|
|
+ " readable then ignore it
|
|
|
let idx = index(s:MRU_files, fname)
|
|
|
if idx == -1
|
|
|
if !filereadable(fname)
|
|
|
@@ -276,7 +317,7 @@ function! s:MRU_AddFile(acmd_bufnr)
|
|
|
" Add the new file list to the beginning of the updated old file list
|
|
|
call insert(s:MRU_files, fname, 0)
|
|
|
|
|
|
- " Return the trimmed list
|
|
|
+ " Trim the list
|
|
|
if len(s:MRU_files) > g:MRU_Max_Entries
|
|
|
call remove(s:MRU_files, g:MRU_Max_Entries, -1)
|
|
|
endif
|
|
|
@@ -299,12 +340,23 @@ function! s:MRU_AddFile(acmd_bufnr)
|
|
|
endif
|
|
|
endfunction
|
|
|
|
|
|
+" Special characters in file names that should be escaped (for security
|
|
|
+" reasons)
|
|
|
+let s:esc_filename_chars = ' *?[{`$%#"|!<>();&' . "'\t\n"
|
|
|
+function! s:MRU_escape_filename(fname)
|
|
|
+ return escape(a:fname, s:esc_filename_chars)
|
|
|
+endfunction
|
|
|
+
|
|
|
" MRU_Edit_File
|
|
|
" Edit the specified file
|
|
|
-function! s:MRU_Edit_File(filename)
|
|
|
- let fname = escape(a:filename, ' %#"')
|
|
|
+function! s:MRU_Edit_File(filename, sanitized)
|
|
|
+ if !a:sanitized
|
|
|
+ let esc_fname = s:MRU_escape_filename(a:filename)
|
|
|
+ else
|
|
|
+ let esc_fname = a:filename
|
|
|
+ endif
|
|
|
" If the file is already open in one of the windows, jump to it
|
|
|
- let winnum = bufwinnr('^' . fname . '$')
|
|
|
+ let winnum = bufwinnr('^' . a:filename . '$')
|
|
|
if winnum != -1
|
|
|
if winnum != winnr()
|
|
|
exe winnum . 'wincmd w'
|
|
|
@@ -313,9 +365,9 @@ function! s:MRU_Edit_File(filename)
|
|
|
if &modified || &buftype != '' || &previewwindow
|
|
|
" Current buffer has unsaved changes or is a special buffer or is
|
|
|
" the preview window. So open the file in a new window
|
|
|
- exe 'split ' . fname
|
|
|
+ exe 'split ' . esc_fname
|
|
|
else
|
|
|
- exe 'edit ' . fname
|
|
|
+ exe 'edit ' . esc_fname
|
|
|
endif
|
|
|
endif
|
|
|
endfunction
|
|
|
@@ -332,11 +384,11 @@ function! s:MRU_Window_Edit_File(win_opt)
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
- let fname = escape(fname, ' %#"')
|
|
|
+ let esc_fname = s:MRU_escape_filename(fname)
|
|
|
|
|
|
if a:win_opt == 'newwin'
|
|
|
" Edit the file in a new window
|
|
|
- exe 'leftabove new ' . fname
|
|
|
+ exe 'leftabove new ' . esc_fname
|
|
|
|
|
|
if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
|
|
|
" Go back to the MRU window and close it
|
|
|
@@ -375,7 +427,7 @@ function! s:MRU_Window_Edit_File(win_opt)
|
|
|
exe 'tabnext ' . i
|
|
|
else
|
|
|
" Open a new tab as the last tab page
|
|
|
- exe '999tabnew ' . fname
|
|
|
+ exe '999tabnew ' . esc_fname
|
|
|
endif
|
|
|
endif
|
|
|
|
|
|
@@ -427,9 +479,9 @@ function! s:MRU_Window_Edit_File(win_opt)
|
|
|
if &modified || &buftype != '' || &previewwindow
|
|
|
" Current buffer has unsaved changes or is a special buffer or
|
|
|
" is the preview window. So open the file in a new window
|
|
|
- exe 'split ' . fname
|
|
|
+ exe 'split ' . esc_fname
|
|
|
else
|
|
|
- exe 'edit ' . fname
|
|
|
+ exe 'edit ' . esc_fname
|
|
|
endif
|
|
|
endif
|
|
|
endif
|
|
|
@@ -546,11 +598,17 @@ function! s:MRU_Open_Window(...)
|
|
|
silent! 0put =s:MRU_files
|
|
|
else
|
|
|
" Display only the entries matching the specified pattern
|
|
|
- silent! 0put =filter(copy(s:MRU_files), 'v:val =~? a:1')
|
|
|
+ " First try using it as a literal pattern
|
|
|
+ let m = filter(copy(s:MRU_files), 'stridx(v:val, a:1) != -1')
|
|
|
+ if len(m) == 0
|
|
|
+ " No match. Try using it as a regular expression
|
|
|
+ let m = filter(copy(s:MRU_files), 'v:val =~# a:1')
|
|
|
+ endif
|
|
|
+ silent! 0put =m
|
|
|
endif
|
|
|
|
|
|
" Move the cursor to the beginning of the file
|
|
|
- exe 1
|
|
|
+ normal! gg
|
|
|
|
|
|
setlocal nomodifiable
|
|
|
endfunction
|
|
|
@@ -588,8 +646,21 @@ function! s:MRU_Cmd(pat)
|
|
|
" filenames containing the string. If only one filename is found,
|
|
|
" then edit it.
|
|
|
let m = filter(copy(s:MRU_files), 'stridx(v:val, a:pat) != -1')
|
|
|
- if len(m) == 1
|
|
|
- call s:MRU_Edit_File(m[0])
|
|
|
+ if len(m) > 0
|
|
|
+ if len(m) == 1
|
|
|
+ call s:MRU_Edit_File(m[0], 0)
|
|
|
+ return
|
|
|
+ endif
|
|
|
+
|
|
|
+ " More than one file matches. Try find an accurate match
|
|
|
+ let new_m = filter(m, 'v:val ==# a:pat')
|
|
|
+ if len(new_m) == 1
|
|
|
+ call s:MRU_Edit_File(new_m[0], 0)
|
|
|
+ return
|
|
|
+ endif
|
|
|
+
|
|
|
+ " Couldn't find an exact match, open the MRU window
|
|
|
+ call s:MRU_Open_Window(a:pat)
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
@@ -605,7 +676,7 @@ function! s:MRU_Cmd(pat)
|
|
|
endif
|
|
|
|
|
|
if len(m) == 1
|
|
|
- call s:MRU_Edit_File(m[0])
|
|
|
+ call s:MRU_Edit_File(m[0], 0)
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
@@ -615,7 +686,9 @@ endfunction
|
|
|
function! s:MRU_add_files_to_menu(prefix, file_list)
|
|
|
for fname in a:file_list
|
|
|
" Escape special characters in the filename
|
|
|
- let esc_fname = escape(fnamemodify(fname, ':t'), ". \\|\t%#")
|
|
|
+ let esc_fname = escape(fnamemodify(fname, ':t'), ".\\" .
|
|
|
+ \ s:esc_filename_chars)
|
|
|
+ let esc_fname = substitute(esc_fname, '&', '&&', 'g')
|
|
|
|
|
|
" Truncate the directory name if it is long
|
|
|
let dir_name = fnamemodify(fname, ':h')
|
|
|
@@ -627,11 +700,15 @@ function! s:MRU_add_files_to_menu(prefix, file_list)
|
|
|
\ '...' .
|
|
|
\ strpart(dir_name, len - 20)
|
|
|
endif
|
|
|
- let esc_dir_name = escape(dir_name, ". \\|\t")
|
|
|
-
|
|
|
- exe 'anoremenu <silent> &File.Recent\ Files.' . a:prefix . esc_fname .
|
|
|
- \ '\ (' . esc_dir_name . ')' .
|
|
|
- \ " :call <SID>MRU_Edit_File('" . fname . "')<CR>"
|
|
|
+ let esc_dir_name = escape(dir_name, ".\\" . s:esc_filename_chars)
|
|
|
+ let esc_dir_name = substitute(esc_dir_name, '&', '&&', 'g')
|
|
|
+
|
|
|
+ let menu_path = '&File.Recent\ Files.' . a:prefix . esc_fname .
|
|
|
+ \ '\ (' . esc_dir_name . ')'
|
|
|
+ let esc_mfname = s:MRU_escape_filename(fname)
|
|
|
+ exe 'anoremenu <silent> ' . menu_path .
|
|
|
+ \ " :call <SID>MRU_Edit_File('" . esc_mfname . "', 1)<CR>"
|
|
|
+ exe 'tmenu ' . menu_path . ' Edit file ' . esc_mfname
|
|
|
endfor
|
|
|
endfunction
|
|
|
|
|
|
@@ -658,11 +735,14 @@ function! s:MRU_Refresh_Menu()
|
|
|
|
|
|
anoremenu <silent> &File.Recent\ Files.Refresh\ list
|
|
|
\ :call <SID>MRU_LoadList()<CR>
|
|
|
+ exe 'tmenu File.Recent\ Files.Refresh\ list Reload the MRU file list from '
|
|
|
+ \ . s:MRU_escape_filename(g:MRU_File)
|
|
|
anoremenu File.Recent\ Files.-SEP1- :
|
|
|
|
|
|
" Add the filenames in the MRU list to the menu
|
|
|
let entry_cnt = len(s:MRU_files)
|
|
|
if entry_cnt > 10
|
|
|
+ " Split the MRU menu into sub-menus
|
|
|
for start_idx in range(0, entry_cnt, 10)
|
|
|
let last_idx = start_idx + 9
|
|
|
if last_idx >= entry_cnt
|
|
|
@@ -692,6 +772,12 @@ autocmd BufRead * call s:MRU_AddFile(expand('<abuf>'))
|
|
|
autocmd BufNewFile * call s:MRU_AddFile(expand('<abuf>'))
|
|
|
autocmd BufWritePost * call s:MRU_AddFile(expand('<abuf>'))
|
|
|
|
|
|
+" The ':vimgrep' command adds all the files searched to the buffer list.
|
|
|
+" This also modifies the MRU list, even though the user didn't edit the
|
|
|
+" files. Use the following autocmds to prevent this.
|
|
|
+autocmd QuickFixCmdPre *vimgrep* let s:mru_list_locked = 1
|
|
|
+autocmd QuickFixCmdPost *vimgrep* let s:mru_list_locked = 0
|
|
|
+
|
|
|
" Command to open the MRU window
|
|
|
command! -nargs=? -complete=customlist,s:MRU_Complete MRU
|
|
|
\ call s:MRU_Cmd(<q-args>)
|