Skip to content
Browse files

Version 3.0

Works only with Vim version 7.0 and above. Uses Vim 7.0 data structures and functions. Support for opening files in tabs. Support for displaying files matching a pattern in the MRU window.
  • Loading branch information...
1 parent 6ce20b3 commit 4afc71beef1691fdce539d12b6250d34b83d2bf4 @yegappan yegappan committed with Jan 12, 2008
Showing with 129 additions and 162 deletions.
  1. +129 −162 plugin/mru.vim
View
291 plugin/mru.vim
@@ -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,80 +547,53 @@ 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
" 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'

0 comments on commit 4afc71b

Please sign in to comment.
Something went wrong with that request. Please try again.