Bläddra i källkod

Version 3.2 (Sep 23, 2008)

Yegappan Lakshmanan 12 år sedan
förälder
incheckning
b6b622fbae
1 ändrade filer med 127 tillägg och 41 borttagningar
  1. 127 41
      plugin/mru.vim

+ 127 - 41
plugin/mru.vim

@@ -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>)