1316 lines
39 KiB
VimL
1316 lines
39 KiB
VimL
"=============================================================================
|
|
" File: winmanager.vim
|
|
" Author: Srinath Avadhanula (srinath@eecs.berkeley.edu)
|
|
" Last Change: Wed Apr 03 05:00 PM 2002 PST
|
|
" Help: winmanager.vim is a plugin which implements a classical windows
|
|
" type IDE in Vim-6.0. When you open up a new file, simply type
|
|
" in :WMToggle. This will start up the file explorer.
|
|
"
|
|
"
|
|
" NOTE: Starting from winmanager-2.x you can add new plugins to winmanager
|
|
" and also customize the window layout in your .vimrc
|
|
"
|
|
" See ":help winmanager" for additional details.
|
|
" ============================================================================
|
|
|
|
" quit if the user doesnt want us or if we are already loaded.
|
|
if exists("loaded_winmanager")
|
|
finish
|
|
end
|
|
let loaded_winmanager = 1
|
|
|
|
" width of the explorer windows
|
|
if !exists("g:winManagerWidth")
|
|
let g:winManagerWidth = 25
|
|
end
|
|
|
|
" whether to close winmanager if only explorer windows are visible.
|
|
if !exists("g:persistentBehaviour")
|
|
let g:persistentBehaviour = 1
|
|
end
|
|
|
|
" default window layout
|
|
if !exists("g:winManagerWindowLayout")
|
|
let g:winManagerWindowLayout = "FileExplorer,TagsExplorer|BufExplorer"
|
|
end
|
|
|
|
" use default explorer plugin which ships with vim.
|
|
if !exists("g:defaultExplorer")
|
|
let g:defaultExplorer = 1
|
|
end
|
|
|
|
" commands
|
|
" toggling between the windows manager open or closed. this can also be used
|
|
" to start win manager.
|
|
if !exists(':WMToggle')
|
|
command -nargs=0 WMToggle :silent call <SID>ToggleWindowsManager()
|
|
end
|
|
|
|
" WManager and WMclose still exist for backward compatibility, but their use
|
|
" is deprecated because WMToggle has the functionality of both of them.
|
|
if !exists(':WManager')
|
|
command -nargs=0 WManager :silent call <SID>StartWindowsManager()
|
|
end
|
|
if !exists(':WMClose')
|
|
command -nargs=0 WMClose :silent call <SID>CloseWindowsManager()
|
|
end
|
|
" command to go to either the first explorer window visible
|
|
if !exists(':FirstExplorerWindow')
|
|
command -nargs=0 FirstExplorerWindow :silent call <SID>GotoExplorerWindow('1')
|
|
end
|
|
" command to go to either the last explorer window visible
|
|
if !exists(':BottomExplorerWindow')
|
|
command -nargs=0 BottomExplorerWindow :silent call <SID>GotoExplorerWindow('$')
|
|
end
|
|
|
|
" this command is used internally by winmanager. shouldnt be of concern to the
|
|
" user.
|
|
if !exists(':WinManagerGotoNextInGroup')
|
|
command -nargs=1 WinManagerGotoNextInGroup :silent call <SID>GotoNextExplorerInGroup(<args>)
|
|
end
|
|
if !exists(':WinManagerGotoPrevInGroup')
|
|
command -nargs=1 WinManagerGotoPrevInGroup :silent call <SID>GotoNextExplorerInGroup(<args>,-1)
|
|
end
|
|
|
|
" nifty command for debugging. SVarValueWinManager 'MRUList' will echo the
|
|
" value of 's:MRUList' for instance. to be used for debugging winmanager.
|
|
" shouldn't be of interest to the user.
|
|
if !exists(':SVarValueWinManager')
|
|
command -nargs=* SVarValueWinManager :call <SID>ShowVariableValue(<args>)
|
|
end
|
|
|
|
" characters that must be escaped for filenames
|
|
if has("dos16") || has("dos32") || has("win16") || has("win32") || has("os2")
|
|
let s:escfilename = ' %#'
|
|
else
|
|
let s:escfilename = ' \%#'
|
|
endif
|
|
|
|
" a quick way to "uncomment" all the debug print statements.
|
|
let g:debugWinManager = 1
|
|
let g:numRefs = 0
|
|
|
|
" initialization.
|
|
let s:numExplorerGroups = 0
|
|
let s:numExplorers = 0
|
|
|
|
" Line continuation used here
|
|
let s:cpo_save = &cpo
|
|
set cpo&vim
|
|
|
|
"---
|
|
" this function creates a variable
|
|
" s:explorerGroup_i
|
|
" for the i^th time it is called. This variable will be of the form
|
|
" s:explorerGroup_i = ",member1,member2,member3,"
|
|
"
|
|
" this provides a way to "group" various explorers into common groups, so that
|
|
" one of them will be visible at a time.
|
|
"
|
|
function! <SID>RegisterExplorerGroup()
|
|
" g:winManagerWindowLayout is of the form
|
|
" 'FileExplorer,TagsExplorer|BufExplorer'
|
|
|
|
" begin extracting groups from the layout variable.
|
|
let groupNum = 1
|
|
while 1
|
|
" if no more groups then break.
|
|
let curGroup = s:Strntok(g:winManagerWindowLayout, '|', groupNum)
|
|
if curGroup == ''
|
|
break
|
|
end
|
|
|
|
" otherwise extract the explorers belonging to this group and the
|
|
" explorer ID's etc. also protect against the same explorer being put
|
|
" in 2 groups.
|
|
let grplist = ','
|
|
let numlist = ','
|
|
let curgn = s:numExplorerGroups + 1
|
|
|
|
let i = 1
|
|
while 1
|
|
let name = s:Strntok(curGroup, ',', i)
|
|
if name == ''
|
|
break
|
|
end
|
|
" refuse to register an explorer twice, or if the explorer's title
|
|
" doesnt exist.
|
|
if exists('s:'.name.'_numberID') || !exists('g:'.name.'_title')
|
|
if !exists('g:'.name.'_title')
|
|
if has('gui_running')
|
|
call confirm(name." is registered as a plugin, but I cannot seem to find it anywhere.\n"
|
|
\.'Make sure you have downloaded the relevant plugin or change the g:winManagerWindowLayout variable',
|
|
\"&ok", 1, 'Warning')
|
|
else
|
|
echohl Error
|
|
echomsg name." is registered as a plugin, but I cannot seem to find it anywhere."
|
|
\.'Please make sure you have downloaded the relevant plugin'
|
|
echohl None
|
|
endif
|
|
endif
|
|
let i = i + 1
|
|
continue
|
|
end
|
|
|
|
let s:numExplorers = s:numExplorers + 1
|
|
let num = s:numExplorers
|
|
|
|
exe 'let s:explorerName_'.num.' = name'
|
|
|
|
let grplist = grplist.name.","
|
|
let numlist = numlist.''.num.','
|
|
|
|
" create variables of the form ExplorerName_<group/member/number>ID
|
|
" which contains which group the explorer belongs to and its member
|
|
" number within that group and also its number
|
|
" this will create a variable of the form
|
|
exe 'let s:'.name.'_groupID = "'.curgn.'"'
|
|
exe 'let s:'.name.'_memberID = "'.i.'"'
|
|
exe 'let s:'.name.'_numberID = "'.num.'"'
|
|
|
|
let i = i + 1
|
|
endwhile
|
|
if grplist == ','
|
|
call PrintError('no explorers registered in this run')
|
|
return
|
|
end
|
|
|
|
let s:numExplorerGroups = s:numExplorerGroups + 1
|
|
|
|
exe 'let s:explorerGroup_'.curgn.' = grplist'
|
|
exe 'let s:explorerGroupNums_'.curgn.' = numlist'
|
|
exe 'let s:numMembers_'.curgn.' = a:0'
|
|
|
|
let groupNum = groupNum + 1
|
|
endwhile
|
|
|
|
endfunction
|
|
|
|
|
|
"---
|
|
" initializes the window manager. sets the initial layout. as of now, the
|
|
" layout of the explorer windows (i.e, which plugin appears above or below the
|
|
" other) depends on the order in which the plugins are sourced.
|
|
" TODO: make this easily user customizable later.
|
|
" Done! See comments about registration.
|
|
"
|
|
" this function opens each "registered" plugin in its appropriate position. it
|
|
" also starts off the autocommand which makes dynamic updating of buffers
|
|
" possible.
|
|
"
|
|
function! <SID>StartWindowsManager()
|
|
" for the first few versions of winmanager, if no registration is done,
|
|
" assume the following default configuration of the windows:
|
|
" (FileExplorer, TagsExplorer)
|
|
" (BufExplorer)
|
|
" This allows for an "easy" distribution. i.e, the installation will not
|
|
" break if the user is careless with his .vimrc
|
|
let oldRep=&report
|
|
let save_sc = &sc
|
|
set report=10000 nosc
|
|
if s:numExplorers == 0
|
|
call s:RegisterExplorerGroup()
|
|
end
|
|
let nothingShown = 1
|
|
let s:commandRunning = 1
|
|
|
|
if !exists("s:MRUList")
|
|
call s:InitializeMRUList()
|
|
end
|
|
let currentWindowNumber = winnr()
|
|
|
|
if !exists("s:gotExplorerTitles")
|
|
let s:gotExplorerTitles = 1
|
|
let i = 1
|
|
while i <= s:numExplorers
|
|
exe 'let name = s:explorerName_'.i
|
|
exe 'let s:explorerTitle_'.i.' = g:'.name.'_title'
|
|
let i = i + 1
|
|
endwhile
|
|
endif
|
|
|
|
" focus on the first visible explorer window.
|
|
let gotvisible = 0
|
|
let i = 1
|
|
while i <= s:numExplorerGroups
|
|
" check if the ith explorer is visible.
|
|
let windownum = s:IsExplorerGroupVisible(i)
|
|
if windownum != -1
|
|
call s:GotoWindow(windownum)
|
|
let gotvisible = 1
|
|
" cen is the "current explorer number". used while restoring the
|
|
" layout.
|
|
let cen = i
|
|
let nothingShown = 0
|
|
break
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
|
|
" split the current window or vsplit a new window for the explorers if
|
|
" none of the explorers is visible.
|
|
if !gotvisible
|
|
if exists('s:lastMemberDisplayed_1')
|
|
let lastmem = s:lastMemberDisplayed_1
|
|
else
|
|
let lastmem = 1
|
|
end
|
|
let somethingDisplayed = s:EditNextVisibleExplorer(1, lastmem-1, 1, 'vsplit')
|
|
" if nothing was displayed this time, there is a possiblity it could
|
|
" happen later during one of the refresh cycles. remember this for
|
|
" then.
|
|
call PrintError('something displayed on '.lastmem.' of 1 :'.somethingDisplayed)
|
|
if !somethingDisplayed
|
|
let s:tryGroupAgain_1 = 1
|
|
q
|
|
else
|
|
let s:tryGroupAgain_1 = 0
|
|
let nothingShown = 0
|
|
let currentWindowNumber = currentWindowNumber + 1
|
|
end
|
|
let cen = 1
|
|
" for now assume that the explorer windows always stay on the left.
|
|
" TODO: make this optional later
|
|
wincmd H
|
|
" set up the correct width
|
|
exe g:winManagerWidth.'wincmd |'
|
|
end
|
|
|
|
" now we are on one of the explorers. time to redo the original layout.
|
|
let _split = &splitbelow
|
|
let i = 1
|
|
while i <= s:numExplorerGroups
|
|
" for each group, see if any member of it is visible.
|
|
let windownum = s:IsExplorerGroupVisible(i)
|
|
|
|
" if this explorer group is not visible, then open the first plugin
|
|
" belonging to this group
|
|
if windownum == -1
|
|
|
|
" if this explorer group is "before" the cen, then split above, else
|
|
" below. except for the first time when this could possibly be
|
|
" true, it always evaluates to the else.
|
|
if i < cen
|
|
set nosplitbelow
|
|
else
|
|
set splitbelow
|
|
end
|
|
" find the last plugin belonging to this "group" which was
|
|
" displayed.
|
|
if exists('s:lastMemberDisplayed_'.i)
|
|
exe 'let lastmem = s:lastMemberDisplayed_'.i
|
|
else
|
|
let lastmem = 1
|
|
end
|
|
" try to display either that plugin or the one after it.
|
|
let somethingDisplayed = s:EditNextVisibleExplorer(i, lastmem-1,1,"split")
|
|
if !somethingDisplayed
|
|
exe 'let s:tryGroupAgain_'.i.' = 1'
|
|
q
|
|
else
|
|
exe 'let s:tryGroupAgain_'.i.' = 0'
|
|
" if this is the first explorer shown, need to push it to the
|
|
" right.
|
|
if nothingShown
|
|
wincmd H
|
|
" set up the correct width
|
|
exe g:winManagerWidth.'wincmd |'
|
|
end
|
|
let nothingShown = 0
|
|
let currentWindowNumber = currentWindowNumber + 1
|
|
end
|
|
let cen = i
|
|
|
|
" the group is visible, go to it so we can split the one after that
|
|
" from it.
|
|
else
|
|
call s:GotoWindow(windownum)
|
|
endif
|
|
|
|
let i = i + 1
|
|
" cen: current explorer (group) number which was visited.
|
|
let cen = i
|
|
endwhile
|
|
call PrintError('done with start while loop')
|
|
|
|
" now make the run for resizing.
|
|
let i = 1
|
|
while i <= s:numExplorerGroups
|
|
" find if its visible and the explorer of this group which is
|
|
" currently displayed.
|
|
let windownum = s:IsExplorerGroupVisible(i)
|
|
" need to check because some of the explorer groups might not have
|
|
" been displayed, if all their members were unable to display
|
|
" anything.
|
|
if windownum == -1
|
|
let i = i + 1
|
|
continue
|
|
end
|
|
let numexp = s:WhichMemberVisible(i)
|
|
|
|
" visible, goto that window.
|
|
call s:GotoWindow(windownum)
|
|
exe 'let name = s:explorerName_'.numexp
|
|
" if this is not occupying the entire height of the window, then call
|
|
" its ReSize() function (if it exists).
|
|
if exists('*'.name.'_ReSize') && !s:IsOnlyVertical()
|
|
exe 'call '.name.'_ReSize()'
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
call PrintError('done with refresh while loop')
|
|
|
|
let &splitbelow = _split
|
|
|
|
augroup WinManagerRefresh
|
|
au!
|
|
au BufEnter * call <SID>RefreshWinManager()
|
|
au BufDelete * call <SID>RefreshWinManager("BufDelete")
|
|
augroup END
|
|
|
|
call s:GotoWindow(currentWindowNumber)
|
|
" RepairAltRegister needs to be called here as well, because
|
|
" 1. when winmanager is re-started, we need to restore the @# register to
|
|
" what it was.
|
|
" 2. if winmanager is started for the first time, then we need to ensure
|
|
" that @# is at least not one of the explorer windows.
|
|
if buflisted(bufnr('%'))
|
|
call s:RepairAltRegister()
|
|
end
|
|
let s:commandRunning = 0
|
|
let &report=oldRep
|
|
let &sc = save_sc
|
|
if nothingShown
|
|
echomsg "[ no valid explorers available. winmanager will start when next possible ]"
|
|
end
|
|
endfunction
|
|
|
|
"---
|
|
" if this window occupies the entire height of the screen, return 1, else
|
|
" return 0. i.e return 1 if there is no window above or below this window.
|
|
"
|
|
function! <SID>IsOnlyVertical()
|
|
let curwin = winnr()
|
|
wincmd k
|
|
if curwin != winnr()
|
|
wincmd j
|
|
return 0
|
|
else
|
|
wincmd j
|
|
if winnr() != curwin
|
|
wincmd k
|
|
return 0
|
|
end
|
|
end
|
|
return 1
|
|
endfunction
|
|
|
|
"---
|
|
" this function first takes focus to the last listed file being edited and
|
|
" then depending on the users action and modified, etc opens the file bufName
|
|
" either on it or splits a new window etc.
|
|
"
|
|
function! WinManagerFileEdit(bufName, split)
|
|
" this function is usually _not_ triggered from an autocommand, so the
|
|
" movement commands in this function will trigger RefreshWinManager().
|
|
" make that do nothing with this flag.
|
|
let s:commandRunning = 1
|
|
let oldRep=&report
|
|
let save_sc = &sc
|
|
set report=10000 nosc
|
|
|
|
" if the file is already visible somewhere just go there.
|
|
" a:bufName is a fully qualified filename of the form
|
|
" e:/path/to/file
|
|
" now bufnr('e:/path/to/file') != -1 even in the case where a file called
|
|
" e:/path/to/file/other/name is opened. (this is bufnr()'s behavior).
|
|
" therefore make an additional check so were protected against false
|
|
" matches.
|
|
if bufwinnr(bufnr(a:bufName)) != -1 &&
|
|
\ a:bufName == expand('#'.bufnr(a:bufName).':p')
|
|
|
|
call s:GotoWindow(bufwinnr(a:bufName))
|
|
" however, we still have to repair the @# register
|
|
call s:RepairAltRegister()
|
|
|
|
" otherwise goto the last listed buffer being edited.
|
|
else
|
|
|
|
" if we had already opened this file, then use the #n notation instead
|
|
" of opening by file name. this preserves cursor position.
|
|
if bufnr(a:bufName) != -1 &&
|
|
\ a:bufName == expand('#'.bufnr(a:bufName).':p')
|
|
let bufcall = '#'.bufnr(a:bufName)
|
|
else
|
|
let bufcall = a:bufName
|
|
end
|
|
|
|
let lastBufferNumber = s:MRUGet(1)
|
|
" if the last accessed buffer is visible, then goto it.
|
|
if bufwinnr(lastBufferNumber) != -1
|
|
" the fact that we go to the last listed buffer and then open this
|
|
" buffer automatically protects the @# register.
|
|
call s:GotoWindow(bufwinnr(bufnr(lastBufferNumber)))
|
|
" now split it or not depending on stuff.
|
|
if (&modified && !&hidden) || a:split
|
|
exe 'silent! split '.bufcall
|
|
else
|
|
exe 'silent! e '.bufcall
|
|
end
|
|
else
|
|
" the last accessed buffer is not visible. this most probably
|
|
" means that the explorer buffers are the only windows visible.
|
|
" this means that the layout has to be redone by v-splitting a new
|
|
" window for this file.
|
|
" first open the alternate file just to retain @# if its still
|
|
" listed.
|
|
if buflisted(lastBufferNumber)
|
|
exe 'silent! vsplit #'.lastBufferNumber
|
|
exe 'silent! e '.bufcall
|
|
" the last accessed buffer has dissapeared. just edit this file.
|
|
else
|
|
exe 'silent! vsplit '.bufcall
|
|
end
|
|
" now push this to the very right
|
|
wincmd L
|
|
" calculate the width of this window and reset it.
|
|
exe &columns-g:winManagerWidth.' wincmd |'
|
|
end
|
|
end
|
|
|
|
let s:commandRunning = 0
|
|
|
|
" call Refresh incase this fileopen made some displays invalid.
|
|
call s:RefreshWinManager()
|
|
let &report=oldRep
|
|
let &sc = save_sc
|
|
endfunction
|
|
|
|
|
|
"---
|
|
" function to repair the @# register.
|
|
"
|
|
" quickly edit the alternate buffer previously being edited in the
|
|
" FileExplorer area so that the % and # registers are not screwed with.
|
|
" This function must be called while focus is on a listed buffer which needs
|
|
" to be made @%.
|
|
"
|
|
function! <SID>RepairAltRegister()
|
|
" setting hidden while going back and forth is very wise because sometimes
|
|
" this function is used from within an autocommand. in such cases,
|
|
" switching back and forth between buffers makes the syntax highlighting
|
|
" dissapear.
|
|
let _hidden = &l:bufhidden
|
|
setlocal bufhidden=hide
|
|
let oldRep=&report
|
|
let save_sc = &sc
|
|
set report=10000 nosc
|
|
|
|
let currentBufferNumber = bufnr('%')
|
|
let currentBufferName = expand('%:p')
|
|
let alternateBufferNumber = s:MRUGet(2)
|
|
|
|
" if the required alternatebuffer exists, then first edit it to preserve @#
|
|
if alternateBufferNumber != bufnr("#")
|
|
\ && alternateBufferNumber != -1
|
|
\ && buflisted(alternateBufferNumber)
|
|
exec 'silent! b! '.alternateBufferNumber
|
|
elseif alternateBufferNumber == -1
|
|
" if the alternate buffer doesnt exist, do some randomness so that the @#
|
|
" register is at least not some explorer buffer number. ideally, at this
|
|
" stage, something would have been done to ensure that @# = -1, however,
|
|
" for now, edit a temporary file.
|
|
exe "e ".tempname()
|
|
setlocal nobuflisted
|
|
setlocal nomodifiable
|
|
setlocal bufhidden=delete
|
|
setlocal buftype=nofile
|
|
let tmpBufNum = bufnr('%')
|
|
exe 'silent! b! '.currentBufferNumber
|
|
exe 'silent! bwipeout '.tmpBufNum
|
|
let &l:bufhidden = _hidden
|
|
return
|
|
end
|
|
|
|
" now edit the current file (to preserve @% :-) )
|
|
" it seems that using ":b !" is _very_ important to preserve syntax
|
|
" highlighting. if ":e #" or ":b " is used, then syntax highlighting is
|
|
" lost and the ugly hack thing keeps getting called everytime.
|
|
" still dont know exactly why this is. it has something to do with
|
|
" abandoned buffers being kept and also nested autocommands, but its not
|
|
" very clear to me what it is.
|
|
exec('silent! b! '.currentBufferNumber)
|
|
|
|
" a totally ugly hack to restore syntax highlighting... i have NO idea why
|
|
" this has to be here... somehow mixing opening files with autocommands
|
|
" has always been very very problematic.
|
|
" NOTE: the problem seems to have gone away now... see above comment.
|
|
if has("syntax") && exists("g:syntax_on") && !has("syntax_items")
|
|
call PrintError('needing to reset syntax!')
|
|
do syntax
|
|
else
|
|
call PrintError('fugly hack not needed!')
|
|
end
|
|
" end fugly hack.
|
|
|
|
let &l:bufhidden = _hidden
|
|
let &report=oldRep
|
|
let &sc = save_sc
|
|
endfunction
|
|
|
|
"---
|
|
" the main function. this is responsible for updating plugins dynamically.
|
|
" this function is triggered on the BufEnter and BufDelete events. every time
|
|
" it is called, it makes a pass through all visible plugins and if their
|
|
" display is not valid, it calls their Start() function.
|
|
"
|
|
" if this function is called with no arguments, it is assumed to be triggered
|
|
" from a BufEnter even or due to a forcible refresh. If it is called with one
|
|
" argument called "BufDelete", then it is assumed that it is triggered from
|
|
" the BufDelete event.
|
|
"
|
|
function! <SID>RefreshWinManager(...)
|
|
" refreshes the window layout and the displayes of windows which trigger
|
|
" on autocommands.
|
|
|
|
" make a note of whether this refresh was triggered by the BufDelete event
|
|
" or not.
|
|
let _split = &splitbelow
|
|
if a:0 > 0 && a:1 == "BufDelete"
|
|
let BufDelete = 1
|
|
else
|
|
let BufDelete = 0
|
|
end
|
|
" do the push pop thing irrespective of whether we do the rest of the
|
|
" stuff or not.
|
|
if BufDelete
|
|
call s:MRUPop()
|
|
else
|
|
call s:MRUPush()
|
|
end
|
|
" if this autocommand was triggered because of internal movements/commands
|
|
" due to other winmanager commands, then quit.
|
|
if exists("s:commandRunning") && s:commandRunning
|
|
return
|
|
end
|
|
" check if only explorer windows are visible and if so quit if we dont
|
|
" want persistent behavior.
|
|
if !g:persistentBehaviour && s:OnlyExplorerWindowsOpen()
|
|
qa
|
|
end
|
|
|
|
" this magic statement is curing the syntax losing problem. WHY?
|
|
let s:commandRunning = 1
|
|
let g:numRefs = g:numRefs + 1
|
|
|
|
" remember this window number because we will return to it after
|
|
" refreshing the buffer listing.
|
|
let currentWindowNumber = winnr()
|
|
let curBufListed = buflisted(bufnr('%'))
|
|
let cfn = s:Path(expand("%:p"))
|
|
|
|
" now cycle through all the visible explorers and and for each "invalid"ly
|
|
" displayed explorer call its corresponding refresh and resize functions.
|
|
let i = 1
|
|
while i <= s:numExplorerGroups && curBufListed
|
|
" find if its visible and the explorer of this group which is
|
|
" currently displayed.
|
|
let windownum = s:IsExplorerGroupVisible(i)
|
|
" if this explorer is visible, then call its _IsValid() function, etc.
|
|
if windownum == -1
|
|
let i = i + 1
|
|
continue
|
|
end
|
|
let numexp = s:WhichMemberVisible(i)
|
|
" visible, goto that window.
|
|
call s:GotoWindow(windownum)
|
|
exe 'let name = s:explorerName_'.numexp
|
|
|
|
exe 'let explorerName = s:explorerName_'.numexp
|
|
exe 'let isvalid = '.explorerName.'_IsValid()'
|
|
" ... and if it isnt then update it.
|
|
if !isvalid
|
|
call <SID>GotoWindow(windownum)
|
|
exe 'call '.explorerName.'_Start()'
|
|
if exists('*'.explorerName.'_ReSize') && !s:IsOnlyVertical()
|
|
exe 'call '.explorerName.'_ReSize()'
|
|
end
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
|
|
" this while loop handles the case where a group of explorers are was not
|
|
" valid at some point and therefore didnt occupy a window, but became
|
|
" valid after some point and therefore need to obtain a seperate window.
|
|
let i = 1
|
|
while i <= s:numExplorerGroups && curBufListed
|
|
exe 'let retry = s:tryGroupAgain_'.i
|
|
" only do this if we need to retry opening this buffer. we should not
|
|
" keep opening a group which the user has closed using a ":quit"
|
|
" command.
|
|
if retry
|
|
call PrintError('retrying group '.i)
|
|
" find the 'nearest' group which is open.
|
|
let nearestGroup = 'inf'
|
|
let nearestWindow = 'inf'
|
|
" TODO: possible bug: what if there are more than a million
|
|
" plugins being used? :-)
|
|
let nearestGroupDist = 1000000
|
|
let j = 1
|
|
while j <= s:numExplorerGroups
|
|
|
|
let windownum = s:IsExplorerGroupVisible(j)
|
|
if windownum != -1
|
|
let dist = ( (j-i) < 0 ? (i-j) : (j-i) )
|
|
if dist < nearestGroupDist
|
|
let nearestGroupDist = dist
|
|
let nearestGroup = j
|
|
let nearestWindow = windownum
|
|
end
|
|
end
|
|
let j = j + 1
|
|
endwhile
|
|
|
|
call PrintError('nearestWindow = '.nearestWindow)
|
|
" if nearestWindow is 'inf', it means no other explorer plugins
|
|
" are open. which means that this thing needs to go the very
|
|
" right.
|
|
if nearestWindow == 'inf'
|
|
let ecmd = 'vsplit'
|
|
else
|
|
let ecmd = 'split'
|
|
if nearestGroup > i
|
|
setlocal nosplitbelow
|
|
else
|
|
setlocal splitbelow
|
|
end
|
|
end
|
|
let somethingDisplayed = s:EditNextVisibleExplorer(i, 0, 1, ecmd)
|
|
" if nothing was displayed this time, there is a possiblity it could
|
|
" happen later during one of the refresh cycles. remember this for
|
|
" then.
|
|
if !somethingDisplayed
|
|
exe 'let s:tryGroupAgain_'.i.' = 1'
|
|
q
|
|
else
|
|
exe 'let s:tryGroupAgain_'.i.' = 0'
|
|
let currentWindowNumber = currentWindowNumber + 1
|
|
exe 'let name = s:explorerName_'.somethingDisplayed
|
|
if exists('*'.name.'_ReSize') && !s:IsOnlyVertical()
|
|
exe 'call '.name.'_ReSize()'
|
|
end
|
|
if nearestWindow == 'inf'
|
|
wincmd H
|
|
" set up the correct width
|
|
" set width only if we are creating a new window...
|
|
exe g:winManagerWidth.'wincmd |'
|
|
end
|
|
call PrintError('doing the funky open thing')
|
|
end
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
|
|
call s:ResizeAllExplorers()
|
|
|
|
" refreshing done, now return back to where we were originally.
|
|
call <SID>GotoWindow(currentWindowNumber)
|
|
|
|
" however, we still have to "repair" the actual @% and @# registers, in
|
|
" case we are returning to a listed buffer. also should do this only for
|
|
" a BufEnter event. For a BufDelete event, the do this only if the current
|
|
" buffer is not the buffer being deleted.
|
|
call PrintError('refresh: abuf = '.expand('<abuf>'))
|
|
if buflisted(bufnr("%")) && !isdirectory(bufname("%")) &&
|
|
\ ( !BufDelete || ( bufnr('%') != expand('<abuf>') ) )
|
|
call <SID>RepairAltRegister()
|
|
end
|
|
|
|
let s:commandRunning = 0
|
|
let &splitbelow = _split
|
|
endfunction
|
|
|
|
function! <SID>ResizeAllExplorers()
|
|
let i = 1
|
|
while i <= s:numExplorers
|
|
let explorerWinNum = s:IsExplorerVisible(i)
|
|
if explorerWinNum != -1
|
|
exe 'let explorerName = s:explorerName_'.i
|
|
if exists('*'.explorerName.'_ReSize') && !s:IsOnlyVertical()
|
|
" if a resize() function exists for this explorer and there
|
|
" is some window above and/or below this window, then call its
|
|
" resize function. this allows for dynamic resizing.
|
|
call s:GotoWindow(explorerWinNum)
|
|
exe 'call '.explorerName.'_ReSize()'
|
|
call PrintError('calling resize for '.explorerName)
|
|
end
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
endfunction
|
|
|
|
"---
|
|
" Make sure a path has proper form.
|
|
" this function forces every path to take the following form
|
|
" dir1/dir2/file OR
|
|
" dir1/dir2/dir/
|
|
" i.e, it replaces \ with / and stuff.
|
|
"
|
|
function! <SID>Path(p)
|
|
let _p = a:p
|
|
if a:p =~ '//$'
|
|
return ""
|
|
end
|
|
if isdirectory(_p)
|
|
let origdir= getcwd()
|
|
exe "chdir" _p
|
|
let _p = getcwd()
|
|
exe "chdir" origdir
|
|
end
|
|
if has("dos16") || has("dos32") || has("win16") || has("win32") || has("os2")
|
|
let _p = substitute(_p,'\\','/','g')
|
|
endif
|
|
if _p !~ '/$' && isdirectory(_p)
|
|
let _p = _p.'/'
|
|
endif
|
|
return _p
|
|
endfunction
|
|
|
|
" goto the reqdWinNum^th window. returns 0 on failure otherwise 1.
|
|
function! <SID>GotoWindow(reqdWinNum)
|
|
let startWinNum = winnr()
|
|
if startWinNum == a:reqdWinNum
|
|
return 1
|
|
end
|
|
if winbufnr(a:reqdWinNum) == -1
|
|
return 0
|
|
else
|
|
exe a:reqdWinNum.' wincmd w'
|
|
return 1
|
|
end
|
|
|
|
endfunction
|
|
|
|
" returns the window number of the ith explorer if its visible, else -1
|
|
function! <SID>IsExplorerVisible(i)
|
|
if exists('s:explorerBufNum_'.a:i)
|
|
exe 'let explorerBufNum = s:explorerBufNum_'.a:i
|
|
else
|
|
let explorerBufNum = -1
|
|
end
|
|
return bufwinnr(explorerBufNum)
|
|
endfunction
|
|
|
|
" returns the window number of the first explorer of the ith explorer group if
|
|
" its visible, else -1
|
|
"
|
|
" if called with 2 arguments with the second being 'member', then returns the
|
|
" member number which is visible instead of its window number
|
|
"
|
|
function! <SID>IsExplorerGroupVisible(i, ...)
|
|
" numList : the list of explorer numbers belonging to this group
|
|
exe 'let numList = s:explorerGroupNums_'.a:i
|
|
" ncl : next comma location
|
|
" pcl : previous comma location
|
|
let pcl = 0
|
|
let ncl = match(numList, ',', pcl + 1)
|
|
while ncl != -1
|
|
exe 'let num = '.strpart(numList, pcl + 1, ncl - pcl - 1)
|
|
if s:IsExplorerVisible(num) != -1
|
|
if a:0 == 1 && a:1 == 'mem'
|
|
return num
|
|
else
|
|
return s:IsExplorerVisible(num)
|
|
end
|
|
end
|
|
let pcl = ncl
|
|
let ncl = match(numList, ',', pcl + 1)
|
|
endwhile
|
|
return -1
|
|
endfunction
|
|
|
|
" returns the member number of the first explorer of the ith explorer group if
|
|
" its visible, else -1
|
|
function! <SID>WhichMemberVisible(i)
|
|
return s:IsExplorerGroupVisible(a:i, 'mem')
|
|
endfunction
|
|
|
|
" a handy little function for debugging.
|
|
function! PrintError(eline)
|
|
if !g:debugWinManager
|
|
return
|
|
end
|
|
if !exists("g:myerror")
|
|
let g:myerror = ""
|
|
end
|
|
let g:myerror = g:myerror . "\n" . a:eline
|
|
endfunction
|
|
|
|
"---
|
|
" find the memn^th member's explorer number of the groupn^th explorer group
|
|
" i.e, if s:explorerGroup_2 = ",3,4,5,"
|
|
" then FindExplorerInGroup(2,3) = 5
|
|
"
|
|
" returs -1 if its not possible.
|
|
"
|
|
function! <SID>FindExplorerInGroup(groupn, memn)
|
|
" numList : the list of explorer numbers belonging to this group
|
|
exe 'let numList = s:explorerGroupNums_'.a:groupn
|
|
|
|
let num = s:Strntok2(numList, ',', a:memn)
|
|
if num == ''
|
|
return -1
|
|
end
|
|
exe 'return '.num
|
|
endfunction
|
|
|
|
"---
|
|
" goto the next explorer in the group which this one belongs to.
|
|
" if called with 2 arguments, goto the previous explorer.
|
|
"
|
|
function! <SID>GotoNextExplorerInGroup(name, ...)
|
|
let s:commandRunning = 1
|
|
" go forward or back?
|
|
if a:0 > 1
|
|
let dir = -1
|
|
else
|
|
let dir = 1
|
|
end
|
|
|
|
" first extract the ID variable from the name
|
|
exe 'let grpn = s:'.a:name.'_groupID'
|
|
exe 'let memn = s:'.a:name.'_memberID'
|
|
exe 'let numn = s:'.a:name.'_numberID'
|
|
|
|
" find the number of members of this group.
|
|
exe 'let nummems = s:numMembers_'.grpn
|
|
if nummems == 1
|
|
return 0
|
|
end
|
|
|
|
if exists('*'.a:name.'_WrapUp')
|
|
exe 'call '.a:name.'_WrapUp()'
|
|
end
|
|
|
|
let curbufnum = bufnr('%')
|
|
let somethingDisplayed = s:EditNextVisibleExplorer(grpn, memn, dir, 'e')
|
|
if !somethingDisplayed && curbufnum != bufnr('%')
|
|
" now start the next explorer using its title
|
|
exe 'let title = s:explorerTitle_'.numn
|
|
exe 'silent! e '.title
|
|
setlocal nobuflisted
|
|
setlocal bufhidden=delete
|
|
setlocal buftype=nofile
|
|
setlocal noswapfile
|
|
|
|
" call the Start() function for the next explorer ...
|
|
exe 'call '.a:name.'_Start()'
|
|
exe 'nnoremap <buffer> <C-n> :WinManagerGotoNextInGroup "'.a:name.'"<cr>'
|
|
exe 'nnoremap <buffer> <C-p> :WinManagerGotoPrevInGroup "'.a:name.'"<cr>'
|
|
setlocal nomodifiable
|
|
call WinManagerForceReSize(a:name)
|
|
end
|
|
|
|
let s:commandRunning = 0
|
|
endfunction
|
|
|
|
" edit the first possible explorer after memn belonging to groun. use editcmd
|
|
" to form the new window.
|
|
function! <SID>EditNextVisibleExplorer(grpn, memn, dir, editcmd)
|
|
|
|
call PrintError('EditNext: grpn = '.a:grpn.', memn = '.a:memn.', dir = '.a:dir.' editcmd = '.a:editcmd)
|
|
" then try to find the number of the next member.
|
|
let startmn = (a:memn ? a:memn : 1)
|
|
let nextmn = a:memn + a:dir
|
|
let editcmd = a:editcmd
|
|
|
|
let somethingDisplayed = 0
|
|
|
|
let once = 0
|
|
" enter this loop at least once
|
|
while nextmn != startmn || !once
|
|
" cycle through the next explorers in this group finding out the next
|
|
" explorer which says its able to display anything at all.
|
|
let once = 1
|
|
|
|
let nextEN = s:FindExplorerInGroup(a:grpn, nextmn)
|
|
" if the next member doesnt exist wrap around.
|
|
if nextEN == -1
|
|
if a:dir == 1
|
|
let nextEN = s:FindExplorerInGroup(a:grpn, 1)
|
|
let nextmn = 1
|
|
continue
|
|
else
|
|
let nextEN = s:FindExplorerInGroup(a:grpn, nummems)
|
|
let nextmn = nummems
|
|
continue
|
|
end
|
|
end
|
|
|
|
" if we have come back to the same explorer with every other group
|
|
" member not able to display anything, then return.
|
|
call PrintError('nextmn = '.nextmn.' a:memn = '.a:memn)
|
|
|
|
exe 'let name = s:explorerName_'.nextEN
|
|
" if the _IsPossible() function doesn't exist, assume its always
|
|
" possible to display stuff.
|
|
let isposs = 1
|
|
if exists('*'.name.'_IsPossible')
|
|
exe 'let isposs = '.name.'_IsPossible()'
|
|
end
|
|
if isposs
|
|
" now start the next explorer using its title
|
|
exe 'let title = s:explorerTitle_'.nextEN
|
|
exe 'let name = s:explorerName_'.nextEN
|
|
exe 'silent! '.editcmd.' '.title
|
|
" use vsplitting etc only the first time things are opened.
|
|
if editcmd != 'e'
|
|
let editcmd = 'e'
|
|
end
|
|
" these are a few setting which most well-made explorers
|
|
" already set, but just to be on the safe side.
|
|
setlocal nobuflisted
|
|
setlocal bufhidden=delete
|
|
setlocal buftype=nofile
|
|
setlocal noswapfile
|
|
|
|
" call the Start() function for the next explorer ...
|
|
exe 'call '.name.'_Start()'
|
|
setlocal nomodifiable
|
|
" and remember its buffer number for later.
|
|
exe 'let s:explorerBufNum_'.nextEN.' = bufnr("%")'
|
|
" also remember that this was the last explorer of this group which was
|
|
" displayed.
|
|
exe 'let s:lastMemberDisplayed_'.a:grpn.' = nextmn'
|
|
|
|
" if this explorer has actually not put anything in the buffer
|
|
" then quit and forget.
|
|
if line('$') > 0 && getline('$') != ''
|
|
let somethingDisplayed = nextEN
|
|
break
|
|
end
|
|
end
|
|
" goto the next explorer of the group.
|
|
let nextmn = nextmn + a:dir
|
|
endwhile
|
|
|
|
if somethingDisplayed
|
|
" and then add this mapping to switch to the next/previous
|
|
" explorer in this group
|
|
exe 'nnoremap <buffer> <C-n> :WinManagerGotoNextInGroup "'.name.'"<cr>'
|
|
exe 'nnoremap <buffer> <C-p> :WinManagerGotoPrevInGroup "'.name.'"<cr>'
|
|
end
|
|
return somethingDisplayed
|
|
endfunction
|
|
|
|
|
|
" goes to either the first explorer window or the last explorer window
|
|
" visible.
|
|
function! <SID>GotoExplorerWindow(which)
|
|
let s:commandRunning = 1
|
|
" first go to either the top left or the bottom right window.
|
|
if a:which == '1'
|
|
" goto to the top left and move in the bottom/right direction.
|
|
wincmd t
|
|
let winmovecmd = 'wincmd w'
|
|
else
|
|
wincmd b
|
|
let winmovecmd = 'wincmd W'
|
|
end
|
|
" remember the window we started from.
|
|
let startWin = winnr()
|
|
let firstTime = 1
|
|
" then begin cycling through all the windows either going in the
|
|
" bottom/right direction or the top/left direction.
|
|
while 1
|
|
" if we are on an explorer window quit.
|
|
if s:IsExplorerBuffer(bufnr('%'))
|
|
let s:commandRunning = 0
|
|
return
|
|
end
|
|
" if we have cycled through one complete time without hitting pay
|
|
" dirt, quit.
|
|
if winnr() == startWin && !firstTime
|
|
" TODO: this will screw the @% and @# register.
|
|
break
|
|
end
|
|
let firstTime = 0
|
|
exe winmovecmd
|
|
endwhile
|
|
let s:commandRunning = 0
|
|
endfunction
|
|
|
|
" returns the explorer number if an explorer plugin exists with the specified
|
|
" buffer number
|
|
function! <SID>IsExplorerBuffer(num)
|
|
let i = 1
|
|
while i <= s:numExplorers
|
|
if exists('s:explorerBufNum_'.i)
|
|
exe 'let bufnum = s:explorerBufNum_'.i
|
|
if bufnum == a:num
|
|
return i
|
|
end
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
return 0
|
|
endfunction
|
|
|
|
" toggle showing the explorer plugins.
|
|
function! <SID>ToggleWindowsManager()
|
|
if IsWinManagerVisible()
|
|
call s:CloseWindowsManager()
|
|
else
|
|
call s:StartWindowsManager()
|
|
end
|
|
endfunction
|
|
|
|
" exported function. returns the buffer number of the last file being edited
|
|
" in the file editing area.
|
|
function! WinManagerGetLastEditedFile(...)
|
|
if a:0 == 0
|
|
return s:MRUGet(1)
|
|
else
|
|
let ret = s:MRUGet(a:1)
|
|
if ret == ''
|
|
return matchstr(s:MRUList, ',\zs[0-9]\+\ze,$')
|
|
else
|
|
return ret
|
|
end
|
|
endfunction
|
|
|
|
|
|
" exported function. returns 1 if any of the explorer windows are open,
|
|
" otherwise returns 0.
|
|
function! IsWinManagerVisible()
|
|
let i = 1
|
|
while i <= s:numExplorers
|
|
if s:IsExplorerVisible(i) != -1
|
|
return 1
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
return 0
|
|
endfunction
|
|
|
|
|
|
" close all the visible explorer windows.
|
|
function! <SID>CloseWindowsManager()
|
|
let s:commandRunning = 1
|
|
|
|
let i = 1
|
|
while i <= bufnr('$')
|
|
let explNum = s:IsExplorerBuffer(i)
|
|
if explNum > 0 && bufwinnr(i) != -1
|
|
exe 'bd '.i
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
|
|
let s:commandRunning = 0
|
|
endfunction
|
|
|
|
" provides a way to examine script local variables from outside the script.
|
|
" very handy for debugging.
|
|
function! <SID>ShowVariableValue(...)
|
|
let i = 1
|
|
while i <= a:0
|
|
exe 'let arg = a:'.i
|
|
if exists('s:'.arg) ||
|
|
\ exists('*s:'.arg)
|
|
exe 'let val = s:'.arg
|
|
echomsg 's:'.arg.' = '.val
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
endfunction
|
|
|
|
" the following functions are hooks provided by winmanager to external plugins
|
|
" as a way to get winmanager to stop getting triggered on AUs. This is useful
|
|
" when an explorer plugin triggers a BufEnter or BufDelete *internally*. For
|
|
" example, bufexplorer.vim's "delete buffer" function triggers a BufDelete
|
|
" function.
|
|
"
|
|
function! WinManagerSuspendAUs()
|
|
let s:commandRunning = 1
|
|
endfunction
|
|
function! WinManagerResumeAUs()
|
|
let s:commandRunning = 0
|
|
endfunction
|
|
|
|
" Another hook provided by winmanager. Normally winmanager will call the
|
|
" plugins resize function every time the BufEnter or BufDelete event is
|
|
" triggered. However, sometimes a plugin might change the number of lines
|
|
" *internally*. In this case, the plugin could make a call to this function
|
|
" which will make a safety check and then call its resize function.
|
|
"
|
|
function! WinManagerForceReSize(explName)
|
|
if !exists('s:'.a:explName.'_numberID') || !exists('*'.a:explName.'_ReSize')
|
|
call PrintError('resize quitting because resize function not found or explorer not registered')
|
|
return
|
|
end
|
|
exe 'let explNum = s:'.a:explName.'_numberID'
|
|
let s:commandRunning = 1
|
|
let windowNum = s:IsExplorerVisible(explNum)
|
|
if windowNum == -1
|
|
call PrintError('resize quitting because window not visible')
|
|
return
|
|
end
|
|
call s:GotoWindow(windowNum)
|
|
if s:IsOnlyVertical()
|
|
call PrintError('resize quitting because its illegal')
|
|
return
|
|
end
|
|
exe 'call '.a:explName.'_ReSize()'
|
|
let s:commandRunning = 0
|
|
endfunction
|
|
|
|
" returns 1 if the only visible windows are explorer windows.
|
|
function! <SID>OnlyExplorerWindowsOpen()
|
|
let i = 1
|
|
" loop over all open windows
|
|
while 1
|
|
" if we have checked all open windows and not returned yet, then it
|
|
" means only explorers are visible.
|
|
if winbufnr(i) == -1
|
|
return 1
|
|
end
|
|
" if this is a non-explorer window then return 0
|
|
if !s:IsExplorerBuffer(winbufnr(i))
|
|
return 0
|
|
end
|
|
let i = i + 1
|
|
endwhile
|
|
endfunction
|
|
|
|
" MRUPush
|
|
function! <SID>MRUPush()
|
|
if buflisted(bufnr("%")) && !isdirectory(bufname("%"))
|
|
let _bufNbr = bufnr('%')
|
|
let _list = substitute(s:MRUList, ','._bufNbr.',', ',', '')
|
|
let s:MRUList = ','._bufNbr._list
|
|
unlet _bufNbr _list
|
|
end
|
|
endfunction
|
|
|
|
" MRUPop
|
|
function! <SID>MRUPop()
|
|
let _bufNbr = expand('<abuf>')
|
|
let s:MRUList = substitute(s:MRUList, ''._bufNbr.',', '', '')
|
|
unlet _bufNbr
|
|
endfunction
|
|
|
|
" MRUGet
|
|
function! <SID>MRUGet(slot)
|
|
let ret = s:Strntok2(s:MRUList, ',', a:slot)
|
|
if ret == ''
|
|
return -1
|
|
end
|
|
exe 'return '.ret
|
|
endfunction
|
|
|
|
" Strntok:
|
|
" extract the n^th token from s seperated by tok.
|
|
" example: Strntok('1,23,3', ',', 2) = 23
|
|
fun! <SID>Strntok(s, tok, n)
|
|
return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
|
|
endfun
|
|
|
|
" Strntok2
|
|
" same as Strntok except that s is delimited by the tok character at the
|
|
" beginning and end.
|
|
" example: Strntok2(',1,23,3,', ',', 2) = 23
|
|
fun! <SID>Strntok2(s, tok, n)
|
|
return matchstr( a:s, '\v((['.a:tok.']\zs[^'.a:tok.']*)\ze){'.a:n.'}')
|
|
endfun
|
|
|
|
" InitializeMRUList
|
|
"
|
|
" initialize the MRU list. initially this will be just the buffers in the
|
|
" order of their buffer numbers with the @% and @# leading. The MRU list
|
|
" consists of a string of the following form: ",1,2,3,4,"
|
|
" NOTE: there are commas at the beginning and the end. this is to make
|
|
" identifying the position of buffers in the list easier even if they occur in
|
|
" the beginning or end and in situations where one buffer number is part of
|
|
" another. i.e the string "9" is part of the string "19"
|
|
"
|
|
function! <SID>InitializeMRUList()
|
|
let nBufs = bufnr('$')
|
|
let _i = 1
|
|
|
|
" put the % and the # numbers at the beginning if they are listed.
|
|
let s:MRUList = ''
|
|
if buflisted(bufnr("%"))
|
|
let s:MRUList = ','.bufnr("%")
|
|
end
|
|
if buflisted(bufnr("#"))
|
|
let s:MRUList = s:MRUList.','.bufnr("#")
|
|
end
|
|
let s:MRUList = s:MRUList.','
|
|
|
|
" then proceed with the rest of the buffers
|
|
while _i <= nBufs
|
|
" dont keep unlisted buffers in the MRU list.
|
|
if buflisted(_i) && bufnr("%") != _i && bufnr("#") != _i
|
|
let s:MRUList = s:MRUList._i.','
|
|
end
|
|
let _i = _i + 1
|
|
endwhile
|
|
" Doing this makes bufexplorer.vim display the first two listed buffers as
|
|
" @% and @# which they actually are when winmanager starts up after doing
|
|
" something like:
|
|
" vim *.vim
|
|
" :WMtoggle
|
|
let g:MRUList = s:MRUList
|
|
endfunction
|
|
|
|
if !g:defaultExplorer
|
|
let loaded_explorer = 1
|
|
"---
|
|
" Set up the autocommand to allow directories to be edited
|
|
"
|
|
augroup fileExplorer
|
|
au!
|
|
au VimEnter * call s:EditDir("VimEnter")
|
|
au BufEnter * call s:EditDir("BufEnter")
|
|
augroup end
|
|
end
|
|
|
|
" handles editing a directory via winmanager.
|
|
function! <SID>EditDir(event)
|
|
" return immediately if this isn't a directory.
|
|
let name = expand("%")
|
|
if name == ""
|
|
let name = expand("%:p")
|
|
endif
|
|
if !isdirectory(name)
|
|
return
|
|
endif
|
|
|
|
" if it is, then call the modified explorer.vim's Explore command.
|
|
if a:event != "VimEnter"
|
|
if exists(":Explore")
|
|
ExploreInCurrentWindow
|
|
end
|
|
end
|
|
" if we have entered vim while editing a directory, then remove the
|
|
" directory buffer, and start the window layout.
|
|
" Note that we only start up winmanager in a VimEnter event because we
|
|
" want commands such as ":e /some/dir/" within vim to have the same effect
|
|
" as with the standard explorer.vim plugin which ships with vim.
|
|
"
|
|
" NOTE: if the user has chosen a layout where the FileExplorer is not at
|
|
" the top-left, this will be unintuitive.
|
|
if a:event == "VimEnter"
|
|
bwipeout
|
|
|
|
call s:StartWindowsManager()
|
|
call s:MRUPush()
|
|
call s:GotoExplorerWindow('1')
|
|
end
|
|
endfunction
|
|
|
|
" restore 'cpo'
|
|
let &cpo = s:cpo_save
|
|
unlet s:cpo_save
|
|
" vim:ts=4:noet:sw=4
|