|
|
@@ -1,7 +1,7 @@
|
|
|
" File: mru.vim
|
|
|
" Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
|
|
|
-" Version: 2.5
|
|
|
-" Last Modified: October 30, 2007
|
|
|
+" Version: 3.0
|
|
|
+" Last Modified: January 12, 2008
|
|
|
"
|
|
|
" Overview
|
|
|
" --------
|
|
|
@@ -10,7 +10,9 @@
|
|
|
" file names as you open/edit them in Vim.
|
|
|
"
|
|
|
" This plugin will work on all the platforms where Vim is supported. This
|
|
|
-" plugin will work in both console and GUI Vim.
|
|
|
+" plugin will work in both console and GUI Vim. This version of the MRU
|
|
|
+" plugin needs Vim 7.0 and above. If you are using an earlier version of
|
|
|
+" Vim, then you should use an older version of the MRU plugin.
|
|
|
"
|
|
|
" The recently used filenames are stored in a file specified by the Vim
|
|
|
" MRU_File variable.
|
|
|
@@ -53,15 +55,24 @@
|
|
|
" You can press the 'o' key to open the file name under the cursor in the
|
|
|
" MRU window in a new window.
|
|
|
"
|
|
|
+" To open a file from the MRU window in a new tab, press the 't' key. If the
|
|
|
+" file is already opened in a window in the current or in another tab, then
|
|
|
+" the cursor is moved to that tab. Othewrise, a new tab is opened.
|
|
|
+"
|
|
|
" You can press the 'u' key in the MRU window to update the file list. This is
|
|
|
-" useful if you keep the MRU window open.
|
|
|
+" useful if you keep the MRU window open always.
|
|
|
"
|
|
|
" You can close the MRU window by pressing the 'q' key or using one of the Vim
|
|
|
" window commands.
|
|
|
"
|
|
|
+" To display only files matching a pattern from the MRU list in the MRU
|
|
|
+" window, you can specify a pattern to the ":MRU" command. For example, to
|
|
|
+" display only file names containing "vim" in them, you can use the following
|
|
|
+" command ":MRU vim"
|
|
|
+"
|
|
|
" You can use the ":MRUedit" command to edit files from the MRU list. This
|
|
|
" command supports completion of file names from the MRU list. You can specify
|
|
|
-" the file either by the name or by the location in the MRU list.
|
|
|
+" a file either by the name or by the location in the MRU list.
|
|
|
"
|
|
|
" Whenever the MRU list changes, the MRU file is updated with the latest MRU
|
|
|
" list. When you have multiple instances of Vim running at the same time, the
|
|
|
@@ -122,10 +133,14 @@
|
|
|
" let MRU_Auto_Close = 0
|
|
|
"
|
|
|
" ****************** Do not modify after this line ************************
|
|
|
-if exists('loaded_mru')
|
|
|
+if exists('loaded_mru_autoload')
|
|
|
+ finish
|
|
|
+endif
|
|
|
+let loaded_mru_autoload=1
|
|
|
+
|
|
|
+if v:version < 700
|
|
|
finish
|
|
|
endif
|
|
|
-let loaded_mru=1
|
|
|
|
|
|
" Line continuation used here
|
|
|
let s:cpo_save = &cpo
|
|
|
@@ -168,15 +183,17 @@ endif
|
|
|
function! s:MRU_LoadList()
|
|
|
" Read the list from the MRU file.
|
|
|
if filereadable(g:MRU_File)
|
|
|
- exe "source " . escape(g:MRU_File, ' ')
|
|
|
- endif
|
|
|
-
|
|
|
- if exists('g:MRU_files')
|
|
|
- " Replace file separator (|) with newline
|
|
|
- let s:MRU_files = substitute(g:MRU_files, "|", "\n", "g")
|
|
|
- unlet! g:MRU_files
|
|
|
+ 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
|
|
|
+ let s:MRU_files = []
|
|
|
+ elseif s:MRU_files[0] =~# '^#'
|
|
|
+ " Remove the comment line
|
|
|
+ call remove(s:MRU_files, 0)
|
|
|
+ endif
|
|
|
else
|
|
|
- let s:MRU_files = ''
|
|
|
+ let s:MRU_files = []
|
|
|
endif
|
|
|
|
|
|
" Refresh the MRU menu
|
|
|
@@ -186,79 +203,10 @@ endfunction
|
|
|
" MRU_SaveList
|
|
|
" Save the MRU list to the file
|
|
|
function! s:MRU_SaveList()
|
|
|
- " Replace all newlines with file separator (|)
|
|
|
- let mru_list = substitute(s:MRU_files, "\n", "|", "g")
|
|
|
- " Escape single quote in filenames with double single quotes
|
|
|
- let mru_list = substitute(mru_list, "'", "''", "g")
|
|
|
-
|
|
|
- " set the verbose option to zero (default). Otherwise this will
|
|
|
- " mess up the text emitted below.
|
|
|
- let old_verbose = &verbose
|
|
|
- set verbose&vim
|
|
|
-
|
|
|
- " Clear the messages displayed on the status line
|
|
|
- echo
|
|
|
-
|
|
|
- " Save the MRU list
|
|
|
- exe "redir! > " . g:MRU_File
|
|
|
- silent! echon '" Most recently edited files in Vim (auto-generated)' . "\n"
|
|
|
- silent! echon "let MRU_files='" . mru_list . "'\n"
|
|
|
- redir END
|
|
|
-
|
|
|
- " Restore the verbose setting
|
|
|
- let &verbose = old_verbose
|
|
|
-endfunction
|
|
|
-
|
|
|
-" MRU_RemoveLines()
|
|
|
-" Remove the lines matching 'one_line' from 'str'
|
|
|
-function! s:MRU_RemoveLines(str, one_line)
|
|
|
- let idx = stridx(a:str, a:one_line . "\n")
|
|
|
- if idx == -1
|
|
|
- " one_line is not present in str
|
|
|
- return a:str
|
|
|
- endif
|
|
|
-
|
|
|
- let x = a:str
|
|
|
-
|
|
|
- while idx != -1
|
|
|
- " Remove the entry from the list by extracting the text before it
|
|
|
- " and then the text after it and then concatenate them
|
|
|
- let text_before = strpart(x, 0, idx)
|
|
|
- let rem_text = strpart(x, idx)
|
|
|
- let next_idx = stridx(rem_text, "\n")
|
|
|
- let text_after = strpart(rem_text, next_idx + 1)
|
|
|
-
|
|
|
- let x = text_before . text_after
|
|
|
- let idx = stridx(x, a:one_line . "\n")
|
|
|
- endwhile
|
|
|
-
|
|
|
- return x
|
|
|
-endfunction
|
|
|
-
|
|
|
-" MRU_TrimLines()
|
|
|
-" Returns the first "lcnt" lines from "lines"
|
|
|
-function! s:MRU_TrimLines(lines, lcnt)
|
|
|
- " Retain only lcnt lines in lines. Remove the remaining lines
|
|
|
- let llist = a:lines
|
|
|
- let cnt = a:lcnt
|
|
|
- let new_llist = ''
|
|
|
- while cnt > 0 && llist != ''
|
|
|
- " Extract one filename from the list
|
|
|
- let one_line = strpart(llist, 0, stridx(llist, "\n"))
|
|
|
-
|
|
|
- " Remove the extracted line from the list
|
|
|
- let llist = strpart(llist, stridx(llist, "\n") + 1)
|
|
|
-
|
|
|
- if one_line != ''
|
|
|
- " Retain the line (if non-empty)
|
|
|
- let new_llist = new_llist . one_line . "\n"
|
|
|
- endif
|
|
|
-
|
|
|
- " One more entry used up
|
|
|
- let cnt = cnt - 1
|
|
|
- endwhile
|
|
|
-
|
|
|
- return new_llist
|
|
|
+ let l = []
|
|
|
+ call add(l, '# Most recently edited files in Vim (version 3.0)')
|
|
|
+ call extend(l, s:MRU_files)
|
|
|
+ call writefile(l, g:MRU_File)
|
|
|
endfunction
|
|
|
|
|
|
" MRU_AddFile
|
|
|
@@ -285,23 +233,27 @@ function! s:MRU_AddFile(acmd_bufnr)
|
|
|
|
|
|
" If the filename is already present in the MRU list, then move
|
|
|
" it to the beginning of the list
|
|
|
- let idx = stridx(s:MRU_files, fname . "\n")
|
|
|
- if idx == -1 && !filereadable(fname)
|
|
|
- " File is not readable and is not in the MRU list
|
|
|
- return
|
|
|
+ let idx = index(s:MRU_files, fname)
|
|
|
+ if idx == -1
|
|
|
+ if !filereadable(fname)
|
|
|
+ " File is not readable and is not in the MRU list
|
|
|
+ return
|
|
|
+ endif
|
|
|
endif
|
|
|
|
|
|
" Load the latest MRU file list
|
|
|
call s:MRU_LoadList()
|
|
|
|
|
|
" Remove the new file name from the existing MRU list (if already present)
|
|
|
- let old_flist = s:MRU_RemoveLines(s:MRU_files, fname)
|
|
|
+ call filter(s:MRU_files, 'v:val !=# fname')
|
|
|
|
|
|
" Add the new file list to the beginning of the updated old file list
|
|
|
- let s:MRU_files = fname . "\n" . old_flist
|
|
|
+ call insert(s:MRU_files, fname, 0)
|
|
|
|
|
|
" Return the trimmed list
|
|
|
- let s:MRU_files = s:MRU_TrimLines(s:MRU_files, g:MRU_Max_Entries)
|
|
|
+ if len(s:MRU_files) > g:MRU_Max_Entries
|
|
|
+ call remove(s:MRU_files, g:MRU_Max_Entries, -1)
|
|
|
+ endif
|
|
|
|
|
|
" Save the updated MRU list
|
|
|
call s:MRU_SaveList()
|
|
|
@@ -344,7 +296,10 @@ endfunction
|
|
|
|
|
|
" MRU_Window_Edit_File
|
|
|
" Open a file selected from the MRU window
|
|
|
-function! s:MRU_Window_Edit_File(new_window)
|
|
|
+" win_opt == useopen, open file in previous window
|
|
|
+" win_opt == newwin, open file in new window
|
|
|
+" win_opt == newtab, open file in new tab
|
|
|
+function! s:MRU_Window_Edit_File(win_opt)
|
|
|
let fname = getline('.')
|
|
|
|
|
|
if fname == ''
|
|
|
@@ -353,7 +308,7 @@ function! s:MRU_Window_Edit_File(new_window)
|
|
|
|
|
|
let fname = escape(fname, ' %#')
|
|
|
|
|
|
- if a:new_window
|
|
|
+ if a:win_opt == 'newwin'
|
|
|
" Edit the file in a new window
|
|
|
exe 'leftabove new ' . fname
|
|
|
|
|
|
@@ -368,6 +323,41 @@ function! s:MRU_Window_Edit_File(new_window)
|
|
|
exe cur_winnr . 'wincmd w'
|
|
|
endif
|
|
|
endif
|
|
|
+ elseif a:win_opt == 'newtab'
|
|
|
+ if g:MRU_Auto_Close == 1 && g:MRU_Use_Current_Window == 0
|
|
|
+ " Automatically close the window if the file window is
|
|
|
+ " not used to display the MRU list.
|
|
|
+ silent! close
|
|
|
+ endif
|
|
|
+
|
|
|
+ " If the selected file is already open in the current tab or in
|
|
|
+ " another tab, jump to it. Otherwise open it in a new tab
|
|
|
+ if bufwinnr('^' . fname . '$') == -1
|
|
|
+ let tabnum = -1
|
|
|
+ let i = 1
|
|
|
+ let bnum = bufnr('^' . fname . '$')
|
|
|
+ while i <= tabpagenr('$')
|
|
|
+ if index(tabpagebuflist(i), bnum) != -1
|
|
|
+ let tabnum = i
|
|
|
+ break
|
|
|
+ endif
|
|
|
+ let i += 1
|
|
|
+ endwhile
|
|
|
+
|
|
|
+ if tabnum != -1
|
|
|
+ " Goto the tab containing the file
|
|
|
+ exe 'tabnext ' . i
|
|
|
+ else
|
|
|
+ " Open a new tab as the last tab page
|
|
|
+ exe '999tabnew ' . escape(fname, ' ')
|
|
|
+ endif
|
|
|
+ endif
|
|
|
+
|
|
|
+ " Jump to the window containing the file
|
|
|
+ let winnum = bufwinnr('^' . fname . '$')
|
|
|
+ if winnum != winnr()
|
|
|
+ exe winnum . 'wincmd w'
|
|
|
+ endif
|
|
|
else
|
|
|
" If the selected file is already open in one of the windows,
|
|
|
" jump to it
|
|
|
@@ -421,13 +411,13 @@ endfunction
|
|
|
|
|
|
" MRU_Open_Window
|
|
|
" Display the Most Recently Used file list in a temporary window.
|
|
|
-function! s:MRU_Open_Window()
|
|
|
+function! s:MRU_Open_Window(...)
|
|
|
|
|
|
" Load the latest MRU file list
|
|
|
call s:MRU_LoadList()
|
|
|
|
|
|
" Empty MRU list
|
|
|
- if s:MRU_files == ''
|
|
|
+ if empty(s:MRU_files)
|
|
|
echohl WarningMsg | echo 'MRU file list is empty' | echohl None
|
|
|
return
|
|
|
endif
|
|
|
@@ -502,18 +492,28 @@ function! s:MRU_Open_Window()
|
|
|
set cpoptions&vim
|
|
|
|
|
|
" Create a mapping to jump to the file
|
|
|
- nnoremap <buffer> <silent> <CR> :call <SID>MRU_Window_Edit_File(0)<CR>
|
|
|
- nnoremap <buffer> <silent> o :call <SID>MRU_Window_Edit_File(1)<CR>
|
|
|
+ nnoremap <buffer> <silent> <CR>
|
|
|
+ \ :call <SID>MRU_Window_Edit_File('useopen')<CR>
|
|
|
+ nnoremap <buffer> <silent> o
|
|
|
+ \ :call <SID>MRU_Window_Edit_File('newwin')<CR>
|
|
|
+ nnoremap <buffer> <silent> t
|
|
|
+ \ :call <SID>MRU_Window_Edit_File('newtab')<CR>
|
|
|
nnoremap <buffer> <silent> u :MRU<CR>
|
|
|
nnoremap <buffer> <silent> <2-LeftMouse>
|
|
|
- \ :call <SID>MRU_Window_Edit_File(0)<CR>
|
|
|
+ \ :call <SID>MRU_Window_Edit_File('useopen')<CR>
|
|
|
nnoremap <buffer> <silent> q :close<CR>
|
|
|
|
|
|
" Restore the previous cpoptions settings
|
|
|
let &cpoptions = old_cpoptions
|
|
|
|
|
|
" Display the MRU list
|
|
|
- silent! 0put =s:MRU_files
|
|
|
+ if a:0 == 0
|
|
|
+ " No search pattern specified. Display the complete list
|
|
|
+ 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')
|
|
|
+ endif
|
|
|
|
|
|
" Move the cursor to the beginning of the file
|
|
|
exe 1
|
|
|
@@ -524,8 +524,12 @@ endfunction
|
|
|
" MRU_Edit_Complete
|
|
|
" Command-line completion function used by :MRUedit command
|
|
|
function! s:MRU_Edit_Complete(ArgLead, CmdLine, CursorPos)
|
|
|
- " Return the list of MRU files
|
|
|
- return s:MRU_files
|
|
|
+ if a:ArgLead == ''
|
|
|
+ " Return the list of MRU files
|
|
|
+ return s:MRU_files
|
|
|
+ else
|
|
|
+ return filter(copy(s:MRU_files), 'v:val =~? a:ArgLead')
|
|
|
+ endif
|
|
|
endfunction
|
|
|
|
|
|
" MRU_Edit_File_Cmd
|
|
|
@@ -543,71 +547,44 @@ function! s:MRU_Edit_File_Cmd(fspec)
|
|
|
if a:fspec =~ '^\d\+$'
|
|
|
" A number is specified
|
|
|
let fnum = a:fspec
|
|
|
- if fnum > g:MRU_Max_Entries
|
|
|
+ if fnum <= 0 || fnum > len(s:MRU_files)
|
|
|
echohl WarningMsg
|
|
|
- echo 'Maximum number of entries in MRU list = ' .
|
|
|
- \ g:MRU_Max_Entries
|
|
|
+ echo 'Error: valid range of values is 1 - ' . len(s:MRU_files)
|
|
|
echohl None
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
- let mru_list = s:MRU_files
|
|
|
-
|
|
|
- let i = 1
|
|
|
- while mru_list != '' && i < fnum
|
|
|
- let one_fname = strpart(mru_list, 0, stridx(mru_list, "\n"))
|
|
|
- if one_fname == ''
|
|
|
- break
|
|
|
- endif
|
|
|
-
|
|
|
- let mru_list = strpart(mru_list, stridx(mru_list, "\n") + 1)
|
|
|
- let i = i + 1
|
|
|
- endwhile
|
|
|
+ " User index is 1 based, but the internal index is 0 based
|
|
|
+ let fnum -= 1
|
|
|
|
|
|
- if i == fnum
|
|
|
- let fname = strpart(mru_list, 0, stridx(mru_list, "\n"))
|
|
|
- if fname != ''
|
|
|
- call s:MRU_Edit_File(fname)
|
|
|
- endif
|
|
|
+ let fname = s:MRU_files[fnum]
|
|
|
+ if fname != ''
|
|
|
+ call s:MRU_Edit_File(fname)
|
|
|
endif
|
|
|
else
|
|
|
" Locate the file name matching the supplied partial name
|
|
|
- let mru_list = s:MRU_files
|
|
|
- let fname = ''
|
|
|
- let fname_cnt = 0
|
|
|
|
|
|
" Escape backslash in the partial filename, otherwise regexp
|
|
|
" comparison will fail
|
|
|
let fpat = escape(a:fspec, '\')
|
|
|
|
|
|
- while mru_list != ''
|
|
|
- let one_fname = strpart(mru_list, 0, stridx(mru_list, "\n"))
|
|
|
- if one_fname == ''
|
|
|
- break
|
|
|
- endif
|
|
|
-
|
|
|
- if one_fname =~? fpat
|
|
|
- let fname = one_fname
|
|
|
- let fname_cnt = fname_cnt + 1
|
|
|
- endif
|
|
|
-
|
|
|
- let mru_list = strpart(mru_list, stridx(mru_list, "\n") + 1)
|
|
|
- endwhile
|
|
|
-
|
|
|
- if fname_cnt == 0
|
|
|
+ let l = filter(copy(s:MRU_files), 'v:val =~ fpat')
|
|
|
+ if len(l) == 0
|
|
|
echohl WarningMsg
|
|
|
- echo 'No matching file for ' . a:fspec
|
|
|
+ echo 'Error: No matching file for ' . a:fspec
|
|
|
echohl None
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
- if fname_cnt > 1
|
|
|
+ if len(l) > 1
|
|
|
echohl WarningMsg
|
|
|
- echo 'More than one match for ' . a:fspec
|
|
|
+ echo 'Error: More than one match for ' . a:fspec
|
|
|
echohl None
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
+ let fname = l[0]
|
|
|
+
|
|
|
call s:MRU_Edit_File(fname)
|
|
|
endif
|
|
|
endfunction
|
|
|
@@ -615,8 +592,8 @@ endfunction
|
|
|
" MRU_Refresh_Menu()
|
|
|
" Refresh the MRU menu
|
|
|
function! s:MRU_Refresh_Menu()
|
|
|
- if !has('gui_running') || &guioptions !~ 'm'
|
|
|
- " Not running in GUI mode
|
|
|
+ if !has('menu')
|
|
|
+ " No support for menus
|
|
|
return
|
|
|
endif
|
|
|
|
|
|
@@ -635,20 +612,10 @@ function! s:MRU_Refresh_Menu()
|
|
|
anoremenu File.Recent\ Files.-SEP1- :
|
|
|
|
|
|
" Add the filenames in the MRU list to the menu
|
|
|
- let flist = s:MRU_files
|
|
|
- while flist != ''
|
|
|
- " Extract one filename from the list
|
|
|
- let fname = strpart(flist, 0, stridx(flist, "\n"))
|
|
|
- if fname == ''
|
|
|
- break
|
|
|
- endif
|
|
|
-
|
|
|
+ for fname in s:MRU_files
|
|
|
" Escape special characters in the filename
|
|
|
let esc_fname = escape(fnamemodify(fname, ':t'), ". \\|\t%#")
|
|
|
|
|
|
- " Remove the extracted line from the list
|
|
|
- let flist = strpart(flist, stridx(flist, "\n") + 1)
|
|
|
-
|
|
|
" Truncate the directory name if it is long
|
|
|
let dir_name = fnamemodify(fname, ':h')
|
|
|
let len = strlen(dir_name)
|
|
|
@@ -664,7 +631,7 @@ function! s:MRU_Refresh_Menu()
|
|
|
exe 'anoremenu <silent> &File.Recent\ Files.' . esc_fname .
|
|
|
\ '\ (' . esc_dir_name . ')' .
|
|
|
\ " :call <SID>MRU_Edit_File('" . fname . "')<CR>"
|
|
|
- endwhile
|
|
|
+ endfor
|
|
|
|
|
|
" Remove the dummy menu entry
|
|
|
unmenu &File.Recent\ Files.Dummy
|
|
|
@@ -682,8 +649,8 @@ autocmd BufNewFile * call s:MRU_AddFile(expand('<abuf>'))
|
|
|
autocmd BufWritePost * call s:MRU_AddFile(expand('<abuf>'))
|
|
|
|
|
|
" Command to open the MRU window
|
|
|
-command! -nargs=0 MRU call s:MRU_Open_Window()
|
|
|
-command! -nargs=1 -complete=custom,s:MRU_Edit_Complete MRUedit
|
|
|
+command! -nargs=? MRU call s:MRU_Open_Window(<q-args>)
|
|
|
+command! -nargs=1 -complete=customlist,s:MRU_Edit_Complete MRUedit
|
|
|
\ call s:MRU_Edit_File_Cmd(<q-args>)
|
|
|
|
|
|
" restore 'cpo'
|