diff options
author | Silvio Rhatto <rhatto@riseup.net> | 2013-01-14 11:12:47 -0200 |
---|---|---|
committer | Silvio Rhatto <rhatto@riseup.net> | 2013-01-14 11:12:47 -0200 |
commit | 616a093f1251903a51db0e1247888f5614ca2ed8 (patch) | |
tree | 970b9edd7b1303c24b60e6b6570397085255d640 /modules | |
parent | ec3df5c5a7171e239ef7db859f8f31e1f282b4d0 (diff) | |
download | dotfiles-616a093f1251903a51db0e1247888f5614ca2ed8.tar.gz dotfiles-616a093f1251903a51db0e1247888f5614ca2ed8.tar.bz2 |
Updating bufexplorer vim plugin
Diffstat (limited to 'modules')
-rw-r--r-- | modules/vim/vim/doc/bufexplorer.txt | 147 | ||||
-rw-r--r-- | modules/vim/vim/plugin/bufexplorer.vim | 1628 |
2 files changed, 1084 insertions, 691 deletions
diff --git a/modules/vim/vim/doc/bufexplorer.txt b/modules/vim/vim/doc/bufexplorer.txt index 9af0682..5d2fbcf 100644 --- a/modules/vim/vim/doc/bufexplorer.txt +++ b/modules/vim/vim/doc/bufexplorer.txt @@ -1,12 +1,13 @@ -*bufexplorer.txt* Buffer Explorer Last Change: 19 Nov 2008 +*bufexplorer.txt* Buffer Explorer Last Change: 23 Dec 2012 Buffer Explorer *buffer-explorer* *bufexplorer* - Version 7.2.2 + Version 7.3.2 Plugin for easily exploring (or browsing) Vim |:buffers|. -|bufexplorer-usage| Usage |bufexplorer-installation| Installation +|bufexplorer-usage| Usage +|bufexplorer-windowlayout| Window Layout |bufexplorer-customization| Customization |bufexplorer-changelog| Change Log |bufexplorer-todo| Todo @@ -27,7 +28,7 @@ To install: - Start Vim or goto an existing instance of Vim. - Execute the following command: > - :helptag <your runtime directory/doc + :helptag <your runtime directory>/doc < This will generate all the help tags for any file located in the doc directory. @@ -36,11 +37,11 @@ To install: USAGE *bufexplorer-usage* To start exploring in the current window, use: > - \be OR :BufExplorer + \be or :BufExplorer or Your custom key mapping To start exploring in a newly split horizontal window, use: > - \bs or :HSBufExplorer + \bs or :BufExplorerHorizontalSplit or Your custom key mapping To start exploring in a newly split vertical window, use: > - \bv or :VSBufExplorer + \bv or :BufExplorerVerticalSplit or Your custom key mapping If you would like to use something other than '\', you may simply change the leader (see |mapleader|). @@ -51,27 +52,36 @@ Note: If the current buffer is modified when bufexplorer started, the current Commands to use once exploring: + <F1> Toggle help information. <enter> Opens the buffer that is under the cursor into the current window. - <F1> Toggle help information. <leftmouse> Opens the buffer that is under the cursor into the current window. <shift-enter> Opens the buffer that is under the cursor in another tab. - d |:wipeout| the buffer under the cursor from the list. - When a buffers is wiped, it will not be shown when unlisted - buffer are displayed. - D |:delete| the buffer under the cursor from the list. - The buffer's 'buflisted' is cleared. This allows for the buffer - to be displayed again using the 'show unlisted' command. + B Works in association with the|ShowTabBuffer|option. If + |ShowTabBuffer|is set to 1, this toggles if BufExplorer is to + only store the most recent tab for this buffer or not. + d |:delete|the buffer under the cursor from the list. The + buffer's 'buflisted' is cleared. This allows for the buffer to + be displayed again using the 'show unlisted' command. + D |:wipeout|the buffer under the cursor from the list. When a + buffers is wiped, it will not be shown when unlisted buffer are + displayed. f Toggles whether you are taken to the active window when selecting a buffer or not. + o Opens the buffer that is under the cursor into the current + window. p Toggles the showing of a split filename/pathname. - q Quit exploring. + q Exit/Close bufexplorer. r Reverses the order the buffers are listed in. R Toggles relative path/absolute path. - s Selects the order the buffers are listed in. Either by buffer + s Cycle thru how the buffers are listed. Either by buffer number, file name, file extension, most recently used (MRU), or full path. + S Cycle thru how the buffers are listed, in reverse order. + Either by buffer number, file name, file extension, most + recently used (MRU), or full path. + T Toggles to show only buffers for this tab or not. t Opens the buffer that is under the cursor in another tab. u Toggles the showing of "unlisted" buffers. @@ -83,8 +93,37 @@ you can then either open it, close it(delete), resort the list, reverse the sort, quit exploring and so on... =============================================================================== +WINDOW LAYOUT *bufexplorer-windowlayout* + +------------------------------------------------------------------------------- +" Press <F1> for Help +" Sorted by mru | Locate buffer | Absolute Split path +"= + 01 %a bufexplorer.txt C:\Vim\vimfiles\doc line 87 + 02 # bufexplorer.vim c:\Vim\vimfiles\plugin line 1 +------------------------------------------------------------------------------- + | | | | | + | | | | +-- Current Line #. + | | | +-- Relative/Full Path + | | +-- Buffer Name. + | +-- Buffer Attributes. See|:buffers|for more information. + +-- Buffer Number. See|:buffers|for more information. + +=============================================================================== CUSTOMIZATION *bufexplorer-customization* +If you do not like the default key mappings of \be, \bs, and \bv, you can +override bufexplorer's default mappings by setting up something like the +following in your vimrc file: + + noremap <silent> <F11> :BufExplorer<CR> + noremap <silent> <m-F11> :BufExplorerHorizontalSplit<CR> + noremap <silent> <c-F11> :BufExplorerVerticalSplit<CR> + + *g:bufExplorerChgWin* +If set, bufexplorer will bring up the selected buffer in the window specified +by g:bufExplorerChgWin. + *g:bufExplorerDefaultHelp* To control whether the default help is displayed or not, use: > let g:bufExplorerDefaultHelp=0 " Do not show default help. @@ -104,6 +143,10 @@ use: > let g:bufExplorerFindActive=1 " Go to active window. The default is to be taken to the active window. + *g:bufExplorerFuncRef* +When a buffer is selected, the functions specified either singly or as a list +will be called. + *g:bufExplorerReverseSort* To control whether to sort the buffer in reverse order or not, use: > let g:bufExplorerReverseSort=0 " Do not sort in reverse order. @@ -124,6 +167,12 @@ directory, use: > let g:bufExplorerShowRelativePath=1 " Show relative paths. The default is to show absolute paths. + *g:bufExplorerShowTabBuffer* +To control weither or not to show buffers on for the specific tab or not, use: > + let g:bufExplorerShowTabBuffer=0 " No. + let g:bufExplorerShowTabBuffer=1 " Yes. +The default is not to show. + *g:bufExplorerShowUnlisted* To control whether to show unlisted buffer or not, use: > let g:bufExplorerShowUnlisted=0 " Do not show unlisted buffers. @@ -164,11 +213,68 @@ The default is to use the global &splitright. =============================================================================== CHANGE LOG *bufexplorer-changelog* -7.2.2 - Fix: +7.3.2 - Fix: + * Thanks go out to Michael Henry for pointing out that I completely + missed yet another function, ReverseSortSelect(), during the + refactoring. This function has now returned. +7.3.1 - Fix: + * Thanks go out to Brett Rasmussen for pointing out that the feature + added way back in version 7.2.3 by Yuriy Ershov to automatically + reposition the cursor to the line containing the active buffer, was + no longer in the plugin. That bit of code has been re-added and + all is well. +7.3.0 - It has been quite a while since I published a new version and this + is the first version since Vim 7.3 was released. + * Thanks to Tim Johnson for testing out this new version. + * I have put some time into reworking and cleaning up the code as + * well as various bug fixes. + * I have hopefully allowed for better mapping of the main public + methods as is explained in the|bufexplorer-customization|section + of the documentation. + * Add new 'B', 'o', and 'S' key mappings. + * Overall, I am hopeful that I not forgotten or lost a feature. +7.2.8 - Enhancements: + * Thanks to Charles Campbell for integrating bufexplorer with GDBMGR. + http://mysite.verizon.net/astronaut/vim/index.html#GDBMGR +7.2.7 - Fix: + * My 1st attempt to fix the "cache" issue where buffers information + has changed but the cache/display does not reflect those changes. + More work still needs to be done. +7.2.6 - Fix: + * Thanks to Michael Henry for pointing out that I totally forgot to + update the inline help to reflect the previous change to the 'd' + and 'D' keys. Opps! +7.2.5 - Fix: + * Philip Morant suggested switching the command (bwipe) associated + with the 'd' key with the command (bdelete) associated with the 'D' + key. This made sense since the 'd' key is more likely to be used + compared to the 'D' key. +7.2.4 - Fix: + * I did not implement the patch provided by Godefroid Chapelle + correctly. I missed one line which happened to be the most + important one :) +7.2.3 - Enhancements: + * Thanks to David Fishburn for helping me out with a much needed + code overhaul as well as some awesome performance enhancements. + He also reworked the handling of tabs. + * Thanks to Vladimir Dobriakov for making the suggestions on + enhancing the documentation to include a better explaination of + what is contained in the main bufexplorer window. + * Thanks to Yuriy Ershov for added code that when the bufexplorer + window is opened, the cursor is now positioned at the line with the + active buffer (useful in non-MRU sort modes). + * Yuriy also added the abiltiy to cycle through the sort fields in + reverse order. + Fixes: + * Thanks to Michael Henry for supplying a patch that allows + bufexplorer to be opened even when there is one buffer or less. + * Thanks to Godefroid Chapelle for supplying a patch that fixed + MRU sort order after loading a session. +7.2.2 - Fixes: * Thanks to David L. Dight for spotting and fixing an issue when using ctrl^. bufexplorer would incorrectly handle the previous buffer so that when ctrl^ was pressed the incorrect file was opened. -7.2.1 - Fix: +7.2.1 - Fixes: * Thanks to Dimitar for spotting and fixing a feature that was inadvertently left out of the previous version. The feature was when bufexplorer was used together with WinManager, you could use @@ -419,14 +525,13 @@ CHANGE LOG *bufexplorer-changelog* *compliant*, adding default keymappings of <Leader>be and <Leader>bs as well as fixing the 'w:sortDirLabel not being defined' bug. 6.0.3 - Added sorting capabilities. Sort taken from explorer.vim. -6.0.2 - Can't remember. +6.0.2 - Can't remember. (2001-07-25) 6.0.1 - Initial release. =============================================================================== TODO *bufexplorer-todo* -- The issuing of a ':bd' command does not always remove the buffer number from - the MRU list. +- Nothing as of now, buf if you have any suggestions, drop me an email. =============================================================================== CREDITS *bufexplorer-credits* diff --git a/modules/vim/vim/plugin/bufexplorer.vim b/modules/vim/vim/plugin/bufexplorer.vim index fb7aea9..de957d8 100644 --- a/modules/vim/vim/plugin/bufexplorer.vim +++ b/modules/vim/vim/plugin/bufexplorer.vim @@ -1,5 +1,5 @@ "============================================================================= -" Copyright: Copyright (C) 2001-2008 Jeff Lanzarotta +" Copyright: Copyright (C) 2001-2012 Jeff Lanzarotta " Permission is hereby granted to use and distribute this code, " with or without modifications, provided that this copyright " notice is copied with it. Like anything else that's free, @@ -10,7 +10,7 @@ " Name Of File: bufexplorer.vim " Description: Buffer Explorer Vim Plugin " Maintainer: Jeff Lanzarotta (delux256-vim at yahoo dot com) -" Last Changed: Wednesday, 19 Nov 2008 +" Last Changed: Sunday, 23 Dec 2012 " Version: See g:bufexplorer_version for version number. " Usage: This file should reside in the plugin directory and be " automatically sourced. @@ -21,849 +21,1137 @@ " <Leader>bs - Opens horizontally split window BufExplorer " <Leader>bv - Opens vertically split window BufExplorer " +" Or you can override the defaults and define your own mapping +" in your vimrc file, for example: +" +" noremap <silent> <F11> :BufExplorer<CR> +" noremap <silent> <m-F11> :BufExplorerHorizontalSplit<CR> +" noremap <silent> <c-F11> :BufExplorerVerticalSplit<CR> +" " Or you can use " -" ":BufExplorer" - Opens BufExplorer -" ":HSBufExplorer" - Opens horizontally window BufExplorer -" ":VSBufExplorer" - Opens vertically split window BufExplorer +" ":BufExplorer" - Opens BufExplorer +" ":BufExplorerHorizontalSplit" - Opens horizontally window BufExplorer +" ":BufExplorerVerticalSplit" - Opens vertically split window BufExplorer " " For more help see supplied documentation. " History: See supplied documentation. +" Issues: 'D' and 'd' remove the buffer from the list but the list is not +" displayed correctly. +" - Add ability to open a buffer in a new split when \be is used. "============================================================================= -" Exit quickly if already running or when 'compatible' is set. {{{1 +" Plugin Code {{{1 +" Exit quickly if already running or when 'compatible' is set. {{{2 if exists("g:bufexplorer_version") || &cp - finish + finish endif -"1}}} +"2}}} " Version number -let g:bufexplorer_version = "7.2.2" +let g:bufexplorer_version = "7.3.2" -" Check for Vim version 700 or greater {{{1 +" Check for Vim version {{{2 if v:version < 700 - echo "Sorry, bufexplorer ".g:bufexplorer_version."\nONLY runs with Vim 7.0 and greater." - finish + echohl WarningMsg + echo "Sorry, bufexplorer ".g:bufexplorer_version." required Vim 7.0 and greater." + echohl None + finish endif -" Public Interface {{{1 -nmap <silent> <unique> <Leader>be :BufExplorer<CR> -nmap <silent> <unique> <Leader>bs :HSBufExplorer<CR> -nmap <silent> <unique> <Leader>bv :VSBufExplorer<CR> - -" Create commands {{{1 -command BufExplorer :call StartBufExplorer(has ("gui") ? "drop" : "hide edit") -command HSBufExplorer :call HorizontalSplitBufExplorer() -command VSBufExplorer :call VerticalSplitBufExplorer() - -" Set {{{1 -function s:Set(var, default) - if !exists(a:var) - if type(a:default) - exec "let" a:var "=" string(a:default) - else - exec "let" a:var "=" a:default - endif +" Create commands {{{2 +command! BufExplorer :call BufExplorer(has ("gui") ? "drop" : "hide edit") +command! BufExplorerHorizontalSplit :call BufExplorerHorizontalSplit() +command! BufExplorerVerticalSplit :call BufExplorerVerticalSplit() - return 1 - endif +" Set {{{2 +function! s:Set(var, default) + if !exists(a:var) + if type(a:default) + exec "let" a:var "=" string(a:default) + else + exec "let" a:var "=" a:default + endif - return 0 -endfunction + return 1 + endif -" Default values {{{1 -call s:Set("g:bufExplorerDefaultHelp", 1) " Show default help? -call s:Set("g:bufExplorerDetailedHelp", 0) " Show detailed help? -call s:Set("g:bufExplorerFindActive", 1) " When selecting an active buffer, take you to the window where it is active? -call s:Set("g:bufExplorerReverseSort", 0) " sort reverse? -call s:Set("g:bufExplorerShowDirectories", 1) " (Dir's are added by commands like ':e .') -call s:Set("g:bufExplorerShowRelativePath", 0) " Show listings with relative or absolute paths? -call s:Set("g:bufExplorerShowUnlisted", 0) " Show unlisted buffers? -call s:Set("g:bufExplorerSortBy", "mru") " Sorting methods are in s:sort_by: -call s:Set("g:bufExplorerSplitOutPathName", 1) " Split out path and file name? -call s:Set("g:bufExplorerSplitRight", &splitright) " Should vertical splits be on the right or left of current window? -call s:Set("g:bufExplorerSplitBelow", &splitbelow) " Should horizontal splits be below or above current window? + return 0 +endfunction -" Global variables {{{1 +" Script variables {{{2 +let s:MRU_Exclude_List = ["[BufExplorer]","__MRU_Files__"] let s:MRUList = [] +let s:name = '[BufExplorer]' +let s:originBuffer = 0 let s:running = 0 let s:sort_by = ["number", "name", "fullpath", "mru", "extension"] +let s:splitMode = "" let s:tabSpace = [] let s:types = {"fullname": ':p', "path": ':p:h', "relativename": ':~:.', "relativepath": ':~:.:h', "shortname": ':t'} -let s:originBuffer = 0 -let s:splitMode = "" -" Setup the autocommands that handle the MRUList and other stuff. {{{1 +" Setup the autocommands that handle the MRUList and other stuff. {{{2 autocmd VimEnter * call s:Setup() -" Setup {{{1 -function s:Setup() - " Build initial MRUList. - let s:MRUList = range(1, bufnr('$')) - let s:tabSpace = [] - " Now that the MRUList is created, add the other autocmds. - autocmd BufEnter,BufNew * call s:ActivateBuffer() - autocmd BufWipeOut * call s:DeactivateBuffer(1) - autocmd BufDelete * call s:DeactivateBuffer(0) +" Setup {{{2 +function! s:Setup() + call s:Reset() + + " Now that the MRUList is created, add the other autocmds. + augroup BufExplorer + autocmd! + autocmd BufEnter,BufNew * call s:ActivateBuffer() + autocmd BufWipeOut * call s:DeactivateBuffer(1) + autocmd BufDelete * call s:DeactivateBuffer(0) - autocmd BufWinEnter \[BufExplorer\] call s:Initialize() - autocmd BufWinLeave \[BufExplorer\] call s:Cleanup() + autocmd BufWinEnter \[BufExplorer\] call s:Initialize() + autocmd BufWinLeave \[BufExplorer\] call s:Cleanup() + + autocmd TabEnter * call s:TabEnter() + + autocmd SessionLoadPost * call s:Reset() + augroup END endfunction -" ActivateBuffer {{{1 -function s:ActivateBuffer() - let b = bufnr("%") - let l = get(s:tabSpace, tabpagenr(), []) +" Reset {{{2 +function! s:Reset() + " Build initial MRUList. This makes sure all the files specified on the + " command line are picked up correctly. + let s:MRUList = range(1, bufnr('$')) + + " Initialize one tab space array, ignore zero-based tabpagenr + " since all tabpagenr's start at 1. + " -1 signifies this is the first time we are referencing this + " tabpagenr. + " If Vim has been loaded with mksession, then it is possible for + " more tabs to exist. So use tabpagenr() to determine how large + " to make the array. If there are 4 tabs, there should be 5 + " elements in this array. + " Each element will hold a CSV list of buffers viewed in + " that tab. So on the 3rd tab, if there user has viewed + " 4 different buffers in that tab, the value would be: + " echo s:tabSpace[3] + " [4, 9, 1, 10] + " echo s:tabSpace + " [[-1], [-1], [-1], [4, 9, 1, 10], [-1]] + let s:tabSpace = [] + let i = 0 + + while( tabpagenr('$') > 0 && i <= tabpagenr('$') ) + call add(s:tabSpace, [-1]) + let i = i + 1 + endwhile +endfunction - if empty(l) || index(l, b) == -1 - call add(l, b) - let s:tabSpace[tabpagenr()] = l - endif +" ActivateBuffer {{{2 +function! s:ActivateBuffer() + " Verify the current tabpage exists in the + " current s:tabSpace array. This can be missing + " entries when restoring sessions. + let i = 0 + while( tabpagenr('$') > 0 && i <= tabpagenr() ) + " Number: 0 + " String: 1 + " Funcref: 2 + " List: 3 + " Dictionary: 4 + " Float: 5 + if type(get(s:tabSpace, i)) == 0 + call add(s:tabSpace, [-1]) + endif + + let i = i + 1 + endwhile + + let _bufnr = bufnr("%") + let list = get(s:tabSpace, tabpagenr(), [-1]) + + if !empty(list) && list[0] == '-1' + " The first time we add a tab, Vim uses the current buffer + " as it's starting page. Even though we are about to + " edit a new page (BufEnter is triggered after), so + " remove the -1 entry indicating we have covered this case. + let list = [] + call add(list, _bufnr) + let s:tabSpace[tabpagenr()] = list + elseif empty(list) || index(list, _bufnr) == -1 + " Add new buffer to this tab's buffer list. + call add(list, _bufnr) + let s:tabSpace[tabpagenr()] = list + + if g:bufExplorerOnlyOneTab == 1 + " If a buffer can only be available in 1 tab page ensure this + " buffer is not present in any other tabs + let tabidx = 1 + while tabidx < len(s:tabSpace) + if tabidx != tabpagenr() + let bufidx = index(s:tabSpace[tabidx], _bufnr) + if bufidx != -1 + call remove(s:tabSpace[tabidx], bufidx) + endif + endif + let tabidx = tabidx + 1 + endwhile + endif + endif + + call s:MRUPush(_bufnr) +endfunction + +" DeactivateBuffer {{{2 +function! s:DeactivateBuffer(remove) + let _bufnr = str2nr(expand("<abuf>")) + call s:MRUPop(_bufnr) +endfunction - call s:MRUPush(b) +" TabEnter {{{2 +function! s:TabEnter() + " Make s:tabSpace 1-based + if empty(s:tabSpace) || len(s:tabSpace) < (tabpagenr() + 1) + call add(s:tabSpace, [-1]) + endif endfunction -" DeactivateBuffer {{{1 -function s:DeactivateBuffer(remove) - "echom "afile:" expand("<afile>") - "echom "bufnr, afile:" bufnr(expand("<afile>")) - "echom "buffers:" string(tabpagebuflist()) - "echom "MRU before:" string(s:MRUList) +" MRUPop {{{2 +function! s:MRUPop(bufnr) + call filter(s:MRUList, 'v:val != '.a:bufnr) +endfunction - let _bufnr = bufnr(expand("<afile>")) - let _buftype = getbufvar(_bufnr, "&buftype") +" MRUPush {{{2 +function! s:MRUPush(buf) + " Skip temporary buffer with buftype set. Don't add the BufExplorer window to the + " list. + if s:ShouldIgnore(a:buf) == 1 + return + endif - if empty(_buftype) || _buftype == "nofile" || !buflisted(_bufnr) || empty(bufname(_bufnr)) || fnamemodify(bufname(_bufnr), ":t") == "[BufExplorer]" - return - end + " Remove the buffer number from the list if it already exists. + call s:MRUPop(a:buf) - if a:remove - call s:MRUPop(bufnr(expand("<afile>"))) - end + " Add the buffer number to the head of the list. + call insert(s:MRUList, a:buf) endfunction -" MRUPop {{{1 -function s:MRUPop(buf) - call filter(s:MRUList, 'v:val != '.a:buf) +" ShouldIgnore {{{2 +function! s:ShouldIgnore(buf) + " Ignore temporary buffers with buftype set. + if empty(getbufvar(a:buf, "&buftype") == 0) + return 1 + endif + + " Ignore unlisted buffers. + if buflisted(a:buf) == 0 + return 1 + endif + + " Ignore buffers with no name. + if empty(bufname(a:buf)) == 1 + return 1 + endif + + " Ignore the BufExplorer buffer. + if fnamemodify(bufname(a:buf), ":t") == s:name + return 1 + endif + + " Ignore any buffers in the exclude list. + if index(s:MRU_Exclude_List, bufname(a:buf)) >= 0 + return 1 + endif + + " Else return 0 to indicate that the buffer was not ignored. + return 0 endfunction -" MRUPush {{{1 -function s:MRUPush(buf) - " Skip temporary buffer with buftype set. Don't add the BufExplorer window to the - " list. - if !empty(getbufvar(a:buf, "&buftype")) || - \ !buflisted(a:buf) || empty(bufname(a:buf)) || - \ fnamemodify(bufname(a:buf), ":t") == "[BufExplorer]" - return - end - " Remove the buffer number from the list if it already exists. - call s:MRUPop(a:buf) - " Add the buffer number to the head of the list. - call insert(s:MRUList,a:buf) +" Initialize {{{2 +function! s:Initialize() + let s:_insertmode = &insertmode + set noinsertmode + + let s:_showcmd = &showcmd + set noshowcmd + + let s:_cpo = &cpo + set cpo&vim + + let s:_report = &report + let &report = 10000 + + let s:_list = &list + set nolist + + setlocal nonumber + setlocal foldcolumn=0 + setlocal nofoldenable + setlocal cursorline + setlocal nospell + + setlocal nobuflisted + + let s:running = 1 endfunction -" Initialize {{{1 -function s:Initialize() - let s:_insertmode = &insertmode - set noinsertmode +" Cleanup {{{2 +function! s:Cleanup() + if exists("s:_insertmode") + let &insertmode = s:_insertmode + endif + + if exists("s:_showcmd") + let &showcmd = s:_showcmd + endif - let s:_showcmd = &showcmd - set noshowcmd + if exists("s:_cpo") + let &cpo = s:_cpo + endif - let s:_cpo = &cpo - set cpo&vim + if exists("s:_report") + let &report = s:_report + endif - let s:_report = &report - let &report = 10000 + if exists("s:_list") + let &list = s:_list + endif - let s:_list = &list - set nolist + let s:running = 0 + let s:splitMode = "" - setlocal nonumber - setlocal foldcolumn=0 - setlocal nofoldenable - setlocal cursorline - setlocal nospell + delmarks! +endfunction - set nobuflisted +" BufExplorerHorizontalSplit {{{2 +function! BufExplorerHorizontalSplit() + let s:splitMode = "sp" + exec "BufExplorer" +endfunction - let s:running = 1 +" BufExplorerVerticalSplit {{{2 +function! BufExplorerVerticalSplit() + let s:splitMode = "vsp" + exec "BufExplorer" endfunction -" Cleanup {{{1 -function s:Cleanup() - let &insertmode = s:_insertmode - let &showcmd = s:_showcmd - let &cpo = s:_cpo - let &report = s:_report - let &list = s:_list - let s:running = 0 - let s:splitMode = "" +" BufExplorer {{{2 +function! BufExplorer(open) + let name = s:name + + if !has("win32") + " On non-Windows boxes, escape the name so that is shows up correctly. + let name = escape(name, "[]") + endif + + " Make sure there is only one explorer open at a time. + if s:running == 1 + " Go to the open buffer. + if has("gui") + exec "drop" name + endif + + return + endif + + " Add zero to ensure the variable is treated as a number. + let s:originBuffer = bufnr("%") + 0 + + silent let s:raw_buffer_listing = s:GetBufferInfo(0) + + let buffer_listing_copy = copy(s:raw_buffer_listing) + + if (g:bufExplorerShowUnlisted == 0) + call filter(buffer_listing_copy, 'v:val.attributes !~ "u"') + endif + + if (!empty(buffer_listing_copy)) + call filter(buffer_listing_copy, 'v:val.shortname !~ "\\\[No Name\\\]"') + endif + +" if len(buffer_listing_copy) <= 1 +" call s:Warning("Sorry, there are no more buffers to explore") +" return +" endif + + " We may have to split the current window. + if (s:splitMode != "") + " Save off the original settings. + let [_splitbelow, _splitright] = [&splitbelow, &splitright] + + " Set the setting to ours. + let [&splitbelow, &splitright] = [g:bufExplorerSplitBelow, g:bufExplorerSplitRight] + + " Do it. + exe 'keepalt '.s:splitMode + + " Restore the original settings. + let [&splitbelow, &splitright] = [_splitbelow, _splitright] + endif + + if !exists("b:displayMode") || b:displayMode != "winmanager" + " Do not use keepalt when opening bufexplorer to allow the buffer that + " we are leaving to become the new alternate buffer + exec "silent keepjumps ".a:open." ".name + endif - delmarks! + call s:DisplayBufferList() + + " Position the cursor in the newly displayed list on the line representing + " the active buffer. The active buffer is the line with the '%' character + " in it. + execute search("%") endfunction -" HorizontalSplitBufExplorer {{{1 -function HorizontalSplitBufExplorer() - let s:splitMode = "sp" - exec "BufExplorer" +" DisplayBufferList {{{2 +function! s:DisplayBufferList() + " Do not set bufhidden since it wipes out the data if we switch away from + " the buffer using CTRL-^. + setlocal buftype=nofile + setlocal modifiable + setlocal noswapfile + setlocal nowrap + + call s:SetupSyntax() + call s:MapKeys() + call setline(1, s:CreateHelp()) + call s:BuildBufferList() + call cursor(s:firstBufferLine, 1) + + if !g:bufExplorerResize + normal! zz + endif + + setlocal nomodifiable endfunction -" VerticalSplitBufExplorer {{{1 -function VerticalSplitBufExplorer() - let s:splitMode = "vsp" - exec "BufExplorer" -endfunction - -" StartBufExplorer {{{1 -function StartBufExplorer(open) - let name = '[BufExplorer]' - - if !has("win32") - " On non-Windows boxes, escape the name so that is shows up correctly. - let name = escape(name, "[]") - endif - " Make sure there is only one explorer open at a time. - if s:running == 1 - " Go to the open buffer. - if has("gui") - exec "drop" name - endif - - return - endif - - let s:originBuffer = bufnr("%") - silent let s:raw_buffer_listing = s:GetBufferInfo() - - let copy = copy(s:raw_buffer_listing) - - if (g:bufExplorerShowUnlisted == 0) - call filter(copy, 'v:val.attributes !~ "u"') - endif - - if (!empty(copy)) - call filter(copy, 'v:val.shortname !~ "\\\[No Name\\\]"') - endif - - if len(copy) <= 1 - echo "\r" - call s:Warning("Sorry, there are no more buffers to explore") - - return - endif - " We may have to split the current window. - if (s:splitMode != "") - " Save off the original settings. - let [_splitbelow, _splitright] = [&splitbelow, &splitright] - " Set the setting to ours. - let [&splitbelow, &splitright] = [g:bufExplorerSplitBelow, g:bufExplorerSplitRight] - " Do it. - exe s:splitMode - " Restore the original settings. - let [&splitbelow, &splitright] = [_splitbelow, _splitright] - endif - - if !exists("b:displayMode") || b:displayMode != "winmanager" - " Do not use keepalt when opening bufexplorer to allow the buffer that we are - " leaving to become the new alternate buffer - exec "silent keepjumps ".a:open." ".name - endif - - call s:DisplayBufferList() -endfunction - -" DisplayBufferList {{{1 -function s:DisplayBufferList() - setlocal bufhidden=delete - setlocal buftype=nofile - setlocal modifiable - setlocal noswapfile - setlocal nowrap - - call s:SetupSyntax() - call s:MapKeys() - call setline(1, s:CreateHelp()) - call s:BuildBufferList() - call cursor(s:firstBufferLine, 1) - - if !g:bufExplorerResize - normal! zz - endif - - setlocal nomodifiable -endfunction - -" MapKeys {{{1 -function s:MapKeys() - if exists("b:displayMode") && b:displayMode == "winmanager" - nnoremap <buffer> <silent> <tab> :call <SID>SelectBuffer("tab")<cr> - endif - - nnoremap <buffer> <silent> <F1> :call <SID>ToggleHelp()<cr> - nnoremap <buffer> <silent> <2-leftmouse> :call <SID>SelectBuffer()<cr> - nnoremap <buffer> <silent> <cr> :call <SID>SelectBuffer()<cr> - nnoremap <buffer> <silent> t :call <SID>SelectBuffer("tab")<cr> - nnoremap <buffer> <silent> <s-cr> :call <SID>SelectBuffer("tab")<cr> - nnoremap <buffer> <silent> d :call <SID>RemoveBuffer("wipe")<cr> - nnoremap <buffer> <silent> D :call <SID>RemoveBuffer("delete")<cr> - nnoremap <buffer> <silent> m :call <SID>MRUListShow()<cr> - nnoremap <buffer> <silent> p :call <SID>ToggleSplitOutPathName()<cr> - nnoremap <buffer> <silent> q :call <SID>Close()<cr> - nnoremap <buffer> <silent> r :call <SID>SortReverse()<cr> - nnoremap <buffer> <silent> R :call <SID>ToggleShowRelativePath()<cr> - nnoremap <buffer> <silent> s :call <SID>SortSelect()<cr> - nnoremap <buffer> <silent> u :call <SID>ToggleShowUnlisted()<cr> - nnoremap <buffer> <silent> f :call <SID>ToggleFindActive()<cr> - - for k in ["G", "n", "N", "L", "M", "H"] - exec "nnoremap <buffer> <silent>" k ":keepjumps normal!" k."<cr>" - endfor -endfunction - -" SetupSyntax {{{1 -function s:SetupSyntax() - if has("syntax") - syn match bufExplorerHelp "^\".*" contains=bufExplorerSortBy,bufExplorerMapping,bufExplorerTitle,bufExplorerSortType,bufExplorerToggleSplit,bufExplorerToggleOpen - syn match bufExplorerOpenIn "Open in \w\+ window" contained - syn match bufExplorerSplit "\w\+ split" contained - syn match bufExplorerSortBy "Sorted by .*" contained contains=bufExplorerOpenIn,bufExplorerSplit - syn match bufExplorerMapping "\" \zs.\+\ze :" contained - syn match bufExplorerTitle "Buffer Explorer.*" contained - syn match bufExplorerSortType "'\w\{-}'" contained - syn match bufExplorerBufNbr /^\s*\d\+/ - syn match bufExplorerToggleSplit "toggle split type" contained - syn match bufExplorerToggleOpen "toggle open mode" contained - - syn match bufExplorerModBuf /^\s*\d\+.\{4}+.*/ - syn match bufExplorerLockedBuf /^\s*\d\+.\{3}[\-=].*/ - syn match bufExplorerHidBuf /^\s*\d\+.\{2}h.*/ - syn match bufExplorerActBuf /^\s*\d\+.\{2}a.*/ - syn match bufExplorerCurBuf /^\s*\d\+.%.*/ - syn match bufExplorerAltBuf /^\s*\d\+.#.*/ - syn match bufExplorerUnlBuf /^\s*\d\+u.*/ - - hi def link bufExplorerBufNbr Number - hi def link bufExplorerMapping NonText - hi def link bufExplorerHelp Special - hi def link bufExplorerOpenIn Identifier - hi def link bufExplorerSortBy String - hi def link bufExplorerSplit NonText - hi def link bufExplorerTitle NonText - hi def link bufExplorerSortType bufExplorerSortBy - hi def link bufExplorerToggleSplit bufExplorerSplit - hi def link bufExplorerToggleOpen bufExplorerOpenIn - - hi def link bufExplorerActBuf Identifier - hi def link bufExplorerAltBuf String - hi def link bufExplorerCurBuf Type - hi def link bufExplorerHidBuf Constant - hi def link bufExplorerLockedBuf Special - hi def link bufExplorerModBuf Exception - hi def link bufExplorerUnlBuf Comment - endif -endfunction - -" ToggleHelp {{{1 -function s:ToggleHelp() - let g:bufExplorerDetailedHelp = !g:bufExplorerDetailedHelp - - setlocal modifiable - " Save position. - normal! ma - " Remove old header. - if (s:firstBufferLine > 1) - exec "keepjumps 1,".(s:firstBufferLine - 1) "d _" - endif - - call append(0, s:CreateHelp()) - - silent! normal! g`a - delmarks a - - setlocal nomodifiable - - if exists("b:displayMode") && b:displayMode == "winmanager" - call WinManagerForceReSize("BufExplorer") - end -endfunction - -" GetHelpStatus {{{1 -function s:GetHelpStatus() - let ret = '" Sorted by '.((g:bufExplorerReverseSort == 1) ? "reverse " : "").g:bufExplorerSortBy - let ret .= ' | '.((g:bufExplorerFindActive == 0) ? "Don't " : "")."Locate buffer" - let ret .= ((g:bufExplorerShowUnlisted == 0) ? "" : " | Show unlisted") - let ret .= ' | '.((g:bufExplorerShowRelativePath == 0) ? "Absolute" : "Relative") - let ret .= ' '.((g:bufExplorerSplitOutPathName == 0) ? "Full" : "Split")." path" - - return ret -endfunction - -" CreateHelp {{{1 -function s:CreateHelp() - if g:bufExplorerDefaultHelp == 0 && g:bufExplorerDetailedHelp == 0 - let s:firstBufferLine = 1 - return [] - endif - - let header = [] - - if g:bufExplorerDetailedHelp == 1 - call add(header, '" Buffer Explorer ('.g:bufexplorer_version.')') - call add(header, '" --------------------------') - call add(header, '" <F1> : toggle this help') - call add(header, '" <enter> or Mouse-Double-Click : open buffer under cursor') - call add(header, '" <shift-enter> or t : open buffer in another tab') - call add(header, '" d : wipe buffer') - call add(header, '" D : delete buffer') - call add(header, '" p : toggle spliting of file and path name') - call add(header, '" q : quit') - call add(header, '" r : reverse sort') - call add(header, '" R : toggle showing relative or full paths') - call add(header, '" u : toggle showing unlisted buffers') - call add(header, '" s : select sort field '.string(s:sort_by).'') - call add(header, '" f : toggle find active buffer') - else - call add(header, '" Press <F1> for Help') - endif - - call add(header, s:GetHelpStatus()) - call add(header, '"=') - - let s:firstBufferLine = len(header) + 1 - - return header -endfunction - -" GetBufferInfo {{{1 -function s:GetBufferInfo() - redir => bufoutput - buffers! - redir END - - let [all, allwidths, listedwidths] = [[], {}, {}] - - for n in keys(s:types) - let allwidths[n] = [] - let listedwidths[n] = [] - endfor - - for buf in split(bufoutput, '\n') - let bits = split(buf, '"') - let b = {"attributes": bits[0], "line": substitute(bits[2], '\s*', '', '')} - - for [key, val] in items(s:types) - let b[key] = fnamemodify(bits[1], val) +" MapKeys {{{2 +function! s:MapKeys() + if exists("b:displayMode") && b:displayMode == "winmanager" + nnoremap <buffer> <silent> <tab> :call <SID>SelectBuffer()<CR> + endif + + nnoremap <script> <silent> <buffer> <2-leftmouse> :call <SID>SelectBuffer()<CR> + nnoremap <script> <silent> <buffer> <CR> :call <SID>SelectBuffer()<CR> + nnoremap <script> <silent> <buffer> <F1> :call <SID>ToggleHelp()<CR> + nnoremap <script> <silent> <buffer> <s-cr> :call <SID>SelectBuffer("tab")<CR> + nnoremap <script> <silent> <buffer> B :call <SID>ToggleOnlyOneTab()<CR> + nnoremap <script> <silent> <buffer> d :call <SID>RemoveBuffer("delete")<CR> + nnoremap <script> <silent> <buffer> D :call <SID>RemoveBuffer("wipe")<CR> + nnoremap <script> <silent> <buffer> f :call <SID>ToggleFindActive()<CR> + nnoremap <script> <silent> <buffer> m :call <SID>MRUListShow()<CR> + nnoremap <script> <silent> <buffer> o :call <SID>SelectBuffer()<CR> + nnoremap <script> <silent> <buffer> p :call <SID>ToggleSplitOutPathName()<CR> + nnoremap <script> <silent> <buffer> q :call <SID>Close()<CR> + nnoremap <script> <silent> <buffer> r :call <SID>SortReverse()<CR> + nnoremap <script> <silent> <buffer> R :call <SID>ToggleShowRelativePath()<CR> + nnoremap <script> <silent> <buffer> s :call <SID>SortSelect()<CR> + nnoremap <script> <silent> <buffer> S :call <SID>ReverseSortSelect()<CR> + nnoremap <script> <silent> <buffer> t :call <SID>SelectBuffer("tab")<CR> + nnoremap <script> <silent> <buffer> T :call <SID>ToggleShowTabBuffer()<CR> + nnoremap <script> <silent> <buffer> u :call <SID>ToggleShowUnlisted()<CR> + + for k in ["G", "n", "N", "L", "M", "H"] + exec "nnoremap <buffer> <silent>" k ":keepjumps normal!" k."<CR>" endfor +endfunction - if getftype(b.fullname) == "dir" && g:bufExplorerShowDirectories == 1 - let b.shortname = "<DIRECTORY>" - end +" SetupSyntax {{{2 +function! s:SetupSyntax() + if has("syntax") + syn match bufExplorerHelp "^\".*" contains=bufExplorerSortBy,bufExplorerMapping,bufExplorerTitle,bufExplorerSortType,bufExplorerToggleSplit,bufExplorerToggleOpen + syn match bufExplorerOpenIn "Open in \w\+ window" contained + syn match bufExplorerSplit "\w\+ split" contained + syn match bufExplorerSortBy "Sorted by .*" contained contains=bufExplorerOpenIn,bufExplorerSplit + syn match bufExplorerMapping "\" \zs.\+\ze :" contained + syn match bufExplorerTitle "Buffer Explorer.*" contained + syn match bufExplorerSortType "'\w\{-}'" contained + syn match bufExplorerBufNbr /^\s*\d\+/ + syn match bufExplorerToggleSplit "toggle split type" contained + syn match bufExplorerToggleOpen "toggle open mode" contained + + syn match bufExplorerModBuf /^\s*\d\+.\{4}+.*/ + syn match bufExplorerLockedBuf /^\s*\d\+.\{3}[\-=].*/ + syn match bufExplorerHidBuf /^\s*\d\+.\{2}h.*/ + syn match bufExplorerActBuf /^\s*\d\+.\{2}a.*/ + syn match bufExplorerCurBuf /^\s*\d\+.%.*/ + syn match bufExplorerAltBuf /^\s*\d\+.#.*/ + syn match bufExplorerUnlBuf /^\s*\d\+u.*/ + + hi def link bufExplorerBufNbr Number + hi def link bufExplorerMapping NonText + hi def link bufExplorerHelp Special + hi def link bufExplorerOpenIn Identifier + hi def link bufExplorerSortBy String + hi def link bufExplorerSplit NonText + hi def link bufExplorerTitle NonText + hi def link bufExplorerSortType bufExplorerSortBy + hi def link bufExplorerToggleSplit bufExplorerSplit + hi def link bufExplorerToggleOpen bufExplorerOpenIn + + hi def link bufExplorerActBuf Identifier + hi def link bufExplorerAltBuf String + hi def link bufExplorerCurBuf Type + hi def link bufExplorerHidBuf Constant + hi def link bufExplorerLockedBuf Special + hi def link bufExplorerModBuf Exception + hi def link bufExplorerUnlBuf Comment + endif +endfunction - call add(all, b) +" ToggleHelp {{{2 +function! s:ToggleHelp() + let g:bufExplorerDetailedHelp = !g:bufExplorerDetailedHelp - for n in keys(s:types) - call add(allwidths[n], len(b[n])) + setlocal modifiable - if b.attributes !~ "u" - call add(listedwidths[n], len(b[n])) - endif - endfor - endfor + " Save position. + normal! ma - let [s:allpads, s:listedpads] = [{}, {}] + " Remove old header. + if (s:firstBufferLine > 1) + exec "keepjumps 1,".(s:firstBufferLine - 1) "d _" + endif - for n in keys(s:types) - let s:allpads[n] = repeat(' ', max(allwidths[n])) - let s:listedpads[n] = repeat(' ', max(listedwidths[n])) - endfor + call append(0, s:CreateHelp()) - return all -endfunction + silent! normal! g`a + delmarks a -" BuildBufferList {{{1 -function s:BuildBufferList() - let lines = [] - " Loop through every buffer. - for buf in s:raw_buffer_listing - if (!g:bufExplorerShowUnlisted && buf.attributes =~ "u") - " Skip unlisted buffers if we are not to show them. - continue + setlocal nomodifiable + + if exists("b:displayMode") && b:displayMode == "winmanager" + call WinManagerForceReSize("BufExplorer") endif +endfunction - let line = buf.attributes." " +" GetHelpStatus {{{2 +function! s:GetHelpStatus() + let ret = '" Sorted by '.((g:bufExplorerReverseSort == 1) ? "reverse " : "").g:bufExplorerSortBy + let ret .= ' | '.((g:bufExplorerFindActive == 0) ? "Don't " : "")."Locate buffer" + let ret .= ((g:bufExplorerShowUnlisted == 0) ? "" : " | Show unlisted") + let ret .= ((g:bufExplorerShowTabBuffer == 0) ? "" : " | Show buffers/tab") + let ret .= ((g:bufExplorerOnlyOneTab == 1) ? "" : " | One tab/buffer") + let ret .= ' | '.((g:bufExplorerShowRelativePath == 0) ? "Absolute" : "Relative") + let ret .= ' '.((g:bufExplorerSplitOutPathName == 0) ? "Full" : "Split")." path" + + return ret +endfunction + +" CreateHelp {{{2 +function! s:CreateHelp() + if g:bufExplorerDefaultHelp == 0 && g:bufExplorerDetailedHelp == 0 + let s:firstBufferLine = 1 + return [] + endif - if g:bufExplorerSplitOutPathName - let type = (g:bufExplorerShowRelativePath) ? "relativepath" : "path" - let path = buf[type] - let pad = (g:bufExplorerShowUnlisted) ? s:allpads.shortname : s:listedpads.shortname - let line .= buf.shortname." ".strpart(pad.path, len(buf.shortname)) + let header = [] + + if g:bufExplorerDetailedHelp == 1 + call add(header, '" Buffer Explorer ('.g:bufexplorer_version.')') + call add(header, '" --------------------------') + call add(header, '" <F1> : toggle this help') + call add(header, '" <enter> or o or Mouse-Double-Click : open buffer under cursor') + call add(header, '" <shift-enter> or t : open buffer in another tab') + call add(header, '" B : toggle if to save/use recent tab or not') + call add(header, '" d : delete buffer') + call add(header, '" D : wipe buffer') + call add(header, '" f : toggle find active buffer') + call add(header, '" p : toggle spliting of file and path name') + call add(header, '" q : quit') + call add(header, '" r : reverse sort') + call add(header, '" R : toggle showing relative or full paths') + call add(header, '" s : cycle thru "sort by" fields '.string(s:sort_by).'') + call add(header, '" S : reverse cycle thru "sort by" fields') + call add(header, '" T : toggle if to show only buffers for this tab or not') + call add(header, '" u : toggle showing unlisted buffers') else - let type = (g:bufExplorerShowRelativePath) ? "relativename" : "fullname" - let path = buf[type] - let line .= path + call add(header, '" Press <F1> for Help') endif - let pads = (g:bufExplorerShowUnlisted) ? s:allpads : s:listedpads + if (!exists("b:displayMode") || b:displayMode != "winmanager") || (b:displayMode == "winmanager" && g:bufExplorerDetailedHelp == 1) + call add(header, s:GetHelpStatus()) + call add(header, '"=') + endif + + let s:firstBufferLine = len(header) + 1 + + return header +endfunction + +" GetBufferInfo {{{2 +function! s:GetBufferInfo(bufnr) + redir => bufoutput + buffers! + redir END - if !empty(pads[type]) - let line .= strpart(pads[type], len(path))." " + if (a:bufnr > 0) + " Since we are only interested in this specified buffer + " remove the other buffers listed + let bufoutput = substitute(bufoutput."\n", '^.*\n\(\s*'.a:bufnr.'\>.\{-}\)\n.*', '\1', '') endif - let line .= buf.line + let [all, allwidths, listedwidths] = [[], {}, {}] + + for n in keys(s:types) + let allwidths[n] = [] + let listedwidths[n] = [] + endfor + + " Loop over each line in the buffer. + for buf in split(bufoutput, '\n') + let bits = split(buf, '"') + let b = {"attributes": bits[0], "line": substitute(bits[2], '\s*', '', '')} + + for [key, val] in items(s:types) + let b[key] = fnamemodify(bits[1], val) + endfor + + if getftype(b.fullname) == "dir" && g:bufExplorerShowDirectories == 1 + let b.shortname = "<DIRECTORY>" + endif - call add(lines, line) - endfor + call add(all, b) - call setline(s:firstBufferLine, lines) + for n in keys(s:types) + call add(allwidths[n], len(b[n])) - call s:SortListing() + if b.attributes !~ "u" + call add(listedwidths[n], len(b[n])) + endif + endfor + endfor + + let [s:allpads, s:listedpads] = [{}, {}] + + for n in keys(s:types) + let s:allpads[n] = repeat(' ', max(allwidths[n])) + let s:listedpads[n] = repeat(' ', max(listedwidths[n])) + endfor + + return all endfunction -" SelectBuffer {{{1 -function s:SelectBuffer(...) - " Sometimes messages are not cleared when we get here so it looks like an error has - " occurred when it really has not. - echo "" - " Are we on a line with a file name? - if line('.') < s:firstBufferLine - exec "normal! \<cr>" - return - endif +" BuildBufferList {{{2 +function! s:BuildBufferList() + let lines = [] - let _bufNbr = str2nr(getline('.')) + " Loop through every buffer. + for buf in s:raw_buffer_listing + " Skip unlisted buffers if we are not to show them. + if (!g:bufExplorerShowUnlisted && buf.attributes =~ "u") + " Skip unlisted buffers if we are not to show them. + continue + endif - if exists("b:displayMode") && b:displayMode == "winmanager" - let bufname = expand("#"._bufNbr.":p") + " Ignore buffers with no name. + if empty(bufname(str2nr(buf.attributes))) == 1 + continue + endif + + if (g:bufExplorerShowTabBuffer) + let show_buffer = 0 + + for bufnr in s:tabSpace[tabpagenr()] + if (buf.attributes =~ '^\s*'.bufnr.'\>') + " Only buffers shown on the current tabpagenr + let show_buffer = 1 + break + endif + endfor + + if show_buffer == 0 + continue + endif + endif + + let line = buf.attributes." " + + if g:bufExplorerSplitOutPathName + let type = (g:bufExplorerShowRelativePath) ? "relativepath" : "path" + let path = buf[type] + let pad = (g:bufExplorerShowUnlisted) ? s:allpads.shortname : s:listedpads.shortname + let line .= buf.shortname." ".strpart(pad.path, len(buf.shortname)) + else + let type = (g:bufExplorerShowRelativePath) ? "relativename" : "fullname" + let path = buf[type] + let line .= path + endif - if (a:0 == 1) && (a:1 == "tab") - call WinManagerFileEdit(bufname, 1) + let pads = (g:bufExplorerShowUnlisted) ? s:allpads : s:listedpads + + if !empty(pads[type]) + let line .= strpart(pads[type], len(path))." " + endif + + let line .= buf.line + + call add(lines, line) + endfor + + call setline(s:firstBufferLine, lines) + + call s:SortListing() +endfunction + +" SelectBuffer {{{2 +function! s:SelectBuffer(...) + " Sometimes messages are not cleared when we get here so it looks like an + " error has occurred when it really has not. +" 3/25/2012 echo "" + + " Are we on a line with a file name? + if line('.') < s:firstBufferLine + exec "normal! \<CR>" + return + endif + + let _bufNbr = str2nr(getline('.')) + + " Check and see if we are running BufferExplorer via WinManager. + if exists("b:displayMode") && b:displayMode == "winmanager" + let _bufName = expand("#"._bufNbr.":p") + + if (a:0 == 1) && (a:1 == "tab") + call WinManagerFileEdit(_bufName, 1) + else + call WinManagerFileEdit(_bufName, 0) + endif + + return + endif + + if bufexists(_bufNbr) + if bufnr("#") == _bufNbr && !exists("g:bufExplorerChgWin") + return s:Close() + endif + + " Are we suppose to open the selected buffer in a tab? + if (a:0 == 1) && (a:1 == "tab") + " Yes, we are to open the selected buffer in a tab. + + " Restore [BufExplorer] buffer. + exec "keepjumps silent buffer!".s:originBuffer + + " Get the tab nmber where this bufer is located in. + let tabNbr = s:GetTabNbr(_bufNbr) + + " Was the tab found? + if tabNbr == 0 + " _bufNbr is not opened in any tabs. Open a new tab with the selected buffer in it. + exec "999tab split +buffer" . _bufNbr + else + " The _bufNbr is already opened in a tab, go to that tab. + exec tabNbr . "tabnext" + + " Focus window. + exec s:GetWinNbr(tabNbr, _bufNbr) . "wincmd w" + endif + else + " No, the user did not ask to open the selected buffer in a tab. + + " Are we suppose to move to the tab where the active buffer is? + if exists("g:bufExplorerChgWin") + exe g:bufExplorerChgWin."wincmd w" + elseif bufloaded(_bufNbr) && g:bufExplorerFindActive + call s:Close() + + " Get the tab number where this buffer is located in. + let tabNbr = s:GetTabNbr(_bufNbr) + + " Was the tab found? + if tabNbr != 0 + " Yes, the buffer is located in a tab. Go to that tab number. + exec tabNbr . "tabnext" + else + "Nope, the buffer is not in a tab. Simply switch to that + "buffer. + let _bufName = expand("#"._bufNbr.":p") + exec _bufName ? "drop ".escape(_bufName, " ") : "buffer "._bufNbr + endif + endif + + " Switch to the buffer. + exec "keepalt keepjumps silent b!" _bufNbr + endif + + " Make the buffer 'listed' again. + call setbufvar(_bufNbr, "&buflisted", "1") + + " Call any associated function references. g:bufExplorerFuncRef may be + " an individual function reference or it may be a list containing + " function references. It will ignore anything that's not a function + " reference. + " + " See :help FuncRef for more on function references. + if exists("g:BufExplorerFuncRef") + if type(g:BufExplorerFuncRef) == 2 + keepj call g:BufExplorerFuncRef() + elseif type(g:BufExplorerFuncRef) == 3 + for FncRef in g:BufExplorerFuncRef + if type(FncRef) == 2 + keepj call FncRef() + endif + endfor + endif + endif else - call WinManagerFileEdit(bufname, 0) + call s:Error("Sorry, that buffer no longer exists, please select another") + call s:DeleteBuffer(_bufNbr, "wipe") endif - - return - end +endfunction - if bufexists(_bufNbr) - if bufnr("#") == _bufNbr - return s:Close() +" RemoveBuffer {{{2 +function! s:RemoveBuffer(mode) + " Are we on a line with a file name? + if line('.') < s:firstBufferLine + return endif - if (a:0 == 1) && (a:1 == "tab") - " Restore [BufExplorer] buffer. - exec "keepjumps silent buffer!".s:originBuffer + " Do not allow this buffer to be deleted if it is the last one. + if len(s:MRUList) == 1 + call s:Error("Sorry, you are not allowed to delete the last buffer") + return + endif + + " These commands are to temporarily suspend the activity of winmanager. + if exists("b:displayMode") && b:displayMode == "winmanager" + call WinManagerSuspendAUs() + end - let tabNbr = s:GetTabNbr(_bufNbr) + let _bufNbr = str2nr(getline('.')) - if tabNbr == 0 - " _bufNbr is not opened in any tabs. Open a new tab with the selected buffer in it. - exec "999tab split +buffer" . _bufNbr - else - " The _bufNbr is already opened in tab(s), go to that tab. - exec tabNbr . "tabnext" - " Focus window. - exec s:GetWinNbr(tabNbr, _bufNbr) . "wincmd w" - endif + if getbufvar(_bufNbr, '&modified') == 1 + call s:Error("Sorry, no write since last change for buffer "._bufNbr.", unable to delete") + return else - if bufloaded(_bufNbr) && g:bufExplorerFindActive - call s:Close() + " Okay, everything is good, delete or wipe the buffer. + call s:DeleteBuffer(_bufNbr, a:mode) + endif - let tabNbr = s:GetTabNbr(_bufNbr) + " Reactivate winmanager autocommand activity. + if exists("b:displayMode") && b:displayMode == "winmanager" + call WinManagerForceReSize("BufExplorer") + call WinManagerResumeAUs() + end +endfunction - if tabNbr != 0 - " The buffer is located in a tab. Go to that tab number. - exec tabNbr . "tabnext" +" DeleteBuffer {{{2 +function! s:DeleteBuffer(buf, mode) + " This routine assumes that the buffer to be removed is on the current line. + try + " Wipe/Delete buffer from Vim. + if a:mode == "wipe" + exe "silent bwipe" a:buf else - let bufname = expand("#"._bufNbr.":p") - exec bufname ? "drop ".escape(bufname, " ") : "buffer "._bufNbr + exe "silent bdelete" a:buf endif - endif - " Switch to the buffer. - exec "keepalt keepjumps silent b!" _bufNbr - endif - " Make the buffer 'listed' again. - call setbufvar(_bufNbr, "&buflisted", "1") - else - call s:Error("Sorry, that buffer no longer exists, please select another") - call s:DeleteBuffer(_bufNbr, "wipe") - endif -endfunction - -" RemoveBuffer {{{1 -function s:RemoveBuffer(mode) - " Are we on a line with a file name? - if line('.') < s:firstBufferLine - return - endif - " Do not allow this buffer to be deleted if it is the last one. - if len(s:MRUList) == 1 - call s:Error("Sorry, you are not allowed to delete the last buffer") - return - endif - " These commands are to temporarily suspend the activity of winmanager. - if exists("b:displayMode") && b:displayMode == "winmanager" - call WinManagerSuspendAUs() - end - - let _bufNbr = str2nr(getline('.')) - - if getbufvar(_bufNbr, '&modified') == 1 - call s:Error("Sorry, no write since last change for buffer "._bufNbr.", unable to delete") - return - else - " Okay, everything is good, delete or wipe the buffer. - call s:DeleteBuffer(_bufNbr, a:mode) - endif - " Reactivate winmanager autocommand activity. - if exists("b:displayMode") && b:displayMode == "winmanager" - call WinManagerForceReSize("BufExplorer") - call WinManagerResumeAUs() - end -endfunction - -" DeleteBuffer {{{1 -function s:DeleteBuffer(buf, mode) - " This routine assumes that the buffer to be removed is on the current line. - try - if a:mode == "wipe" - exe "silent bw" a:buf + + " Delete the buffer from the list on screen. + setlocal modifiable + normal! "_dd + setlocal nomodifiable + + " Delete the buffer from the raw buffer list. + call filter(s:raw_buffer_listing, 'v:val.attributes !~ " '.a:buf.' "') + catch + call s:Error(v:exception) + endtry +endfunction + +" Close {{{2 +function! s:Close() + " Get only the listed buffers. + let listed = filter(copy(s:MRUList), "buflisted(v:val)") + + " If we needed to split the main window, close the split one. + if (s:splitMode != "") + exec "wincmd c" + endif + + " Check to see if there are anymore buffers listed. + if len(listed) == 0 + " Since there are no buffers left to switch to, open a new empty + " buffers. + exe "enew" else - exe "silent bd" a:buf - end + " Since there are buffers left to switch to, swith to them... + for b in reverse(listed[0:1]) + exec "keepjumps silent b ".b + endfor + endif - setlocal modifiable - normal! "_dd - setlocal nomodifiable - " Delete the buffer from the raw buffer list. - call filter(s:raw_buffer_listing, 'v:val.attributes !~ " '.a:buf.' "') - catch - call s:Error(v:exception) - endtry + " Clear any messages. + echo endfunction -" Close {{{1 -function s:Close() - " Get only the listed buffers. - let listed = filter(copy(s:MRUList), "buflisted(v:val)") - " If we needed to split the main window, close the split one. - if (s:splitMode != "") - exec "wincmd c" - end +" ToggleSplitOutPathName {{{2 +function! s:ToggleSplitOutPathName() + let g:bufExplorerSplitOutPathName = !g:bufExplorerSplitOutPathName + call s:RebuildBufferList() + call s:UpdateHelpStatus() +endfunction - for b in reverse(listed[0:1]) - exec "keepjumps silent b ".b - endfor +" ToggleShowRelativePath {{{2 +function! s:ToggleShowRelativePath() + let g:bufExplorerShowRelativePath = !g:bufExplorerShowRelativePath + call s:RebuildBufferList() + call s:UpdateHelpStatus() endfunction -" ToggleSplitOutPathName {{{1 -function s:ToggleSplitOutPathName() - let g:bufExplorerSplitOutPathName = !g:bufExplorerSplitOutPathName - call s:RebuildBufferList() - call s:UpdateHelpStatus() +" ToggleShowTabBuffer {{{2 +function! s:ToggleShowTabBuffer() + let g:bufExplorerShowTabBuffer = !g:bufExplorerShowTabBuffer + call s:RebuildBufferList(g:bufExplorerShowTabBuffer) + call s:UpdateHelpStatus() endfunction -" ToggleShowRelativePath {{{1 -function s:ToggleShowRelativePath() - let g:bufExplorerShowRelativePath = !g:bufExplorerShowRelativePath - call s:RebuildBufferList() - call s:UpdateHelpStatus() +" ToggleOnlyOneTab {{{2 +function! s:ToggleOnlyOneTab() + let g:bufExplorerOnlyOneTab = !g:bufExplorerOnlyOneTab + call s:RebuildBufferList() + call s:UpdateHelpStatus() endfunction -" ToggleShowUnlisted {{{1 -function s:ToggleShowUnlisted() - let g:bufExplorerShowUnlisted = !g:bufExplorerShowUnlisted - let num_bufs = s:RebuildBufferList(g:bufExplorerShowUnlisted == 0) - call s:UpdateHelpStatus() +" ToggleShowUnlisted {{{2 +function! s:ToggleShowUnlisted() + let g:bufExplorerShowUnlisted = !g:bufExplorerShowUnlisted + let num_bufs = s:RebuildBufferList(g:bufExplorerShowUnlisted == 0) + call s:UpdateHelpStatus() endfunction -" ToggleFindActive {{{1 -function s:ToggleFindActive() - let g:bufExplorerFindActive = !g:bufExplorerFindActive - call s:UpdateHelpStatus() +" ToggleFindActive {{{2 +function! s:ToggleFindActive() + let g:bufExplorerFindActive = !g:bufExplorerFindActive + call s:UpdateHelpStatus() endfunction -" RebuildBufferList {{{1 -function s:RebuildBufferList(...) - setlocal modifiable +" RebuildBufferList {{{2 +function! s:RebuildBufferList(...) + setlocal modifiable - let curPos = getpos('.') + let curPos = getpos('.') - if a:0 - " Clear the list first. - exec "keepjumps ".s:firstBufferLine.',$d "_' - endif + if a:0 + " Clear the list first. + exec "keepjumps ".s:firstBufferLine.',$d "_' + endif - let num_bufs = s:BuildBufferList() + let num_bufs = s:BuildBufferList() - call setpos('.', curPos) + call setpos('.', curPos) - setlocal nomodifiable + setlocal nomodifiable - return num_bufs + return num_bufs endfunction -" UpdateHelpStatus {{{1 -function s:UpdateHelpStatus() - setlocal modifiable +" UpdateHelpStatus {{{2 +function! s:UpdateHelpStatus() + setlocal modifiable - let text = s:GetHelpStatus() - call setline(s:firstBufferLine - 2, text) + let text = s:GetHelpStatus() + call setline(s:firstBufferLine - 2, text) - setlocal nomodifiable + setlocal nomodifiable endfunction -" MRUCmp {{{1 -function s:MRUCmp(line1, line2) - return index(s:MRUList, str2nr(a:line1)) - index(s:MRUList, str2nr(a:line2)) +" MRUCmp {{{2 +function! s:MRUCmp(line1, line2) + return index(s:MRUList, str2nr(a:line1)) - index(s:MRUList, str2nr(a:line2)) endfunction -" SortReverse {{{1 -function s:SortReverse() - let g:bufExplorerReverseSort = !g:bufExplorerReverseSort - - call s:ReSortListing() +" SortReverse {{{2 +function! s:SortReverse() + let g:bufExplorerReverseSort = !g:bufExplorerReverseSort + call s:ReSortListing() endfunction -" SortSelect {{{1 -function s:SortSelect() - let g:bufExplorerSortBy = get(s:sort_by, index(s:sort_by, g:bufExplorerSortBy) + 1, s:sort_by[0]) +" SortSelect {{{2 +function! s:SortSelect() + let g:bufExplorerSortBy = get(s:sort_by, index(s:sort_by, g:bufExplorerSortBy) + 1, s:sort_by[0]) + call s:ReSortListing() +endfunction - call s:ReSortListing() +" ReverseSortSelect {{{2 +function! s:ReverseSortSelect() + let g:bufExplorerSortBy = get(s:sort_by, index(s:sort_by, g:bufExplorerSortBy) - 1, s:sort_by[-1]) + call s:ReSortListing() endfunction -" ReSortListing {{{1 -function s:ReSortListing() - setlocal modifiable +" ReSortListing {{{2 +function! s:ReSortListing() + setlocal modifiable - let curPos = getpos('.') + let curPos = getpos('.') - call s:SortListing() - call s:UpdateHelpStatus() + call s:SortListing() + call s:UpdateHelpStatus() - call setpos('.', curPos) + call setpos('.', curPos) - setlocal nomodifiable + setlocal nomodifiable endfunction -" SortListing {{{1 -function s:SortListing() - let sort = s:firstBufferLine.",$sort".((g:bufExplorerReverseSort == 1) ? "!": "") +" SortListing {{{2 +function! s:SortListing() + let sort = s:firstBufferLine.",$sort".((g:bufExplorerReverseSort == 1) ? "!": "") - if g:bufExplorerSortBy == "number" - " Easiest case. - exec sort 'n' - elseif g:bufExplorerSortBy == "name" - if g:bufExplorerSplitOutPathName - exec sort 'ir /\d.\{7}\zs\f\+\ze/' - else - exec sort 'ir /\zs[^\/\\]\+\ze\s*line/' - endif - elseif g:bufExplorerSortBy == "fullpath" - if g:bufExplorerSplitOutPathName - " Sort twice - first on the file name then on the path. - exec sort 'ir /\d.\{7}\zs\f\+\ze/' - endif + if g:bufExplorerSortBy == "number" + " Easiest case. + exec sort 'n' + elseif g:bufExplorerSortBy == "name" + if g:bufExplorerSplitOutPathName + exec sort 'ir /\d.\{7}\zs\f\+\ze/' + else + exec sort 'ir /\zs[^\/\\]\+\ze\s*line/' + endif + elseif g:bufExplorerSortBy == "fullpath" + if g:bufExplorerSplitOutPathName + " Sort twice - first on the file name then on the path. + exec sort 'ir /\d.\{7}\zs\f\+\ze/' + endif - exec sort 'ir /\zs\f\+\ze\s\+line/' - elseif g:bufExplorerSortBy == "extension" - exec sort 'ir /\.\zs\w\+\ze\s/' - elseif g:bufExplorerSortBy == "mru" - let l = getline(s:firstBufferLine, "$") + exec sort 'ir /\zs\f\+\ze\s\+line/' + elseif g:bufExplorerSortBy == "extension" + exec sort 'ir /\.\zs\w\+\ze\s/' + elseif g:bufExplorerSortBy == "mru" + let l = getline(s:firstBufferLine, "$") - call sort(l, "<SID>MRUCmp") + call sort(l, "<SID>MRUCmp") - if g:bufExplorerReverseSort - call reverse(l) - endif + if g:bufExplorerReverseSort + call reverse(l) + endif - call setline(s:firstBufferLine, l) - endif + call setline(s:firstBufferLine, l) + endif endfunction -" MRUListShow {{{1 -function s:MRUListShow() - echomsg "MRUList=".string(s:MRUList) +" MRUListShow {{{2 +function! s:MRUListShow() + echomsg "MRUList=".string(s:MRUList) endfunction -" Error {{{1 -function s:Error(msg) - echohl ErrorMsg | echo a:msg | echohl none +" Error {{{2 +" Display a message using ErrorMsg highlight group. +function! s:Error(msg) + echohl ErrorMsg + echomsg a:msg + echohl None endfunction -" Warning {{{1 -function s:Warning(msg) - echohl WarningMsg | echo a:msg | echohl none +" Warning {{{2 +" Display a message using WarningMsg highlight group. +function! s:Warning(msg) + echohl WarningMsg + echomsg a:msg + echohl None endfunction -" GetTabNbr {{{1 -function s:GetTabNbr(bufNbr) - " Searching buffer bufno, in tabs. - for i in range(tabpagenr("$")) - if index(tabpagebuflist(i + 1), a:bufNbr) != -1 - return i + 1 - endif - endfor +" GetTabNbr {{{2 +function! s:GetTabNbr(bufNbr) + " Searching buffer bufno, in tabs. + for i in range(tabpagenr("$")) + if index(tabpagebuflist(i + 1), a:bufNbr) != -1 + return i + 1 + endif + endfor - return 0 + return 0 endfunction -" GetWinNbr" {{{1 -function s:GetWinNbr(tabNbr, bufNbr) - " window number in tabpage. - return index(tabpagebuflist(a:tabNbr), a:bufNbr) + 1 +" GetWinNbr" {{{2 +function! s:GetWinNbr(tabNbr, bufNbr) + " window number in tabpage. + let tablist = tabpagebuflist(a:tabNbr) + " Number: 0 + " String: 1 + " Funcref: 2 + " List: 3 + " Dictionary: 4 + " Float: 5 + if type(tablist) == 3 + return index(tabpagebuflist(a:tabNbr), a:bufNbr) + 1 + else + return 1 + endif endfunction -" Winmanager Integration {{{1 +" Winmanager Integration {{{2 let g:BufExplorer_title = "\[Buf\ List\]" call s:Set("g:bufExplorerResize", 1) call s:Set("g:bufExplorerMaxHeight", 25) " Handles dynamic resizing of the window. -" Function to start display. Set the mode to 'winmanager' for this buffer. +" function! to start display. Set the mode to 'winmanager' for this buffer. " This is to figure out how this plugin was called. In a standalone fashion " or by winmanager. -function BufExplorer_Start() - let b:displayMode = "winmanager" - call StartBufExplorer("e") +function! BufExplorer_Start() + let b:displayMode = "winmanager" + call BufExplorer("e") endfunction " Returns whether the display is okay or not. -function BufExplorer_IsValid() - return 0 +function! BufExplorer_IsValid() + return 0 endfunction " Handles dynamic refreshing of the window. -function BufExplorer_Refresh() - let b:displayMode = "winmanager" - call StartBufExplorer("e") +function! BufExplorer_Refresh() + let b:displayMode = "winmanager" + call BufExplorer("e") endfunction -function BufExplorer_ReSize() - if !g:bufExplorerResize - return - end +function! BufExplorer_ReSize() + if !g:bufExplorerResize + return + end - let nlines = min([line("$"), g:bufExplorerMaxHeight]) + let nlines = min([line("$"), g:bufExplorerMaxHeight]) - exe nlines." wincmd _" + exe nlines." wincmd _" - " The following lines restore the layout so that the last file line is also - " the last window line. Sometimes, when a line is deleted, although the - " window size is exactly equal to the number of lines in the file, some of - " the lines are pushed up and we see some lagging '~'s. - let pres = getpos(".") + " The following lines restore the layout so that the last file line is also + " the last window line. Sometimes, when a line is deleted, although the + " window size is exactly equal to the number of lines in the file, some of + " the lines are pushed up and we see some lagging '~'s. + let pres = getpos(".") - exe $ + exe $ - let _scr = &scrolloff - let &scrolloff = 0 + let _scr = &scrolloff + let &scrolloff = 0 - normal! z- + normal! z- - let &scrolloff = _scr + let &scrolloff = _scr - call setpos(".", pres) + call setpos(".", pres) endfunction + +" Default key mapping {{{1 +if !hasmapto('BufExplorer') + noremap <script> <silent> <unique> <Leader>be :BufExplorer<CR> +endif + +if !hasmapto('BufExplorerHorizontalSplit') + noremap <script> <silent> <unique> <Leader>bs :BufExplorerHorizontalSplit<CR> +endif + +if !hasmapto('BufExplorerVerticalSplit') + noremap <script> <silent> <unique> <Leader>bv :BufExplorerVerticalSplit<CR> +endif + +" Default values {{{1 +call s:Set("g:bufExplorerDefaultHelp", 1) " Show default help? +call s:Set("g:bufExplorerDetailedHelp", 0) " Show detailed help? +call s:Set("g:bufExplorerFindActive", 1) " When selecting an active buffer, take you to the window where it is active? +call s:Set("g:bufExplorerOnlyOneTab", 1) " If ShowTabBuffer = 1, only store the most recent tab for this buffer. +call s:Set("g:bufExplorerReverseSort", 0) " Sort in reverse order by default? +call s:Set("g:bufExplorerShowDirectories", 1) " (Dir's are added by commands like ':e .') +call s:Set("g:bufExplorerShowRelativePath", 0) " Show listings with relative or absolute paths? +call s:Set("g:bufExplorerShowTabBuffer", 0) " Show only buffer(s) for this tab? +call s:Set("g:bufExplorerShowUnlisted", 0) " Show unlisted buffers? +call s:Set("g:bufExplorerSortBy", "mru") " Sorting methods are in s:sort_by: +call s:Set("g:bufExplorerSplitBelow", &splitbelow) " Should horizontal splits be below or above current window? +call s:Set("g:bufExplorerSplitOutPathName", 1) " Split out path and file name? +call s:Set("g:bufExplorerSplitRight", &splitright) " Should vertical splits be on the right or left of current window? "1}}} -" vim:ft=vim foldmethod=marker sw=2 +" vim:ft=vim foldmethod=marker sw=4 |