Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/home/.vim/plugin/winfileexplorer.vim
diff options
context:
space:
mode:
Diffstat (limited to 'home/.vim/plugin/winfileexplorer.vim')
-rw-r--r--home/.vim/plugin/winfileexplorer.vim1490
1 files changed, 1490 insertions, 0 deletions
diff --git a/home/.vim/plugin/winfileexplorer.vim b/home/.vim/plugin/winfileexplorer.vim
new file mode 100644
index 0000000..c01e306
--- /dev/null
+++ b/home/.vim/plugin/winfileexplorer.vim
@@ -0,0 +1,1490 @@
+"=============================================================================
+" File: explorer.vim
+" Author: M A Aziz Ahmed (aziz@acorn-networks.com)
+" Last Change: Sun Mar 31 11:00 PM 2002 PST
+" Version: 2.5
+" Additions by Mark Waggoner (waggoner@aracnet.com) et al.
+"-----------------------------------------------------------------------------
+" This file implements a file explorer. Latest version available at:
+" http://www.freespeech.org/aziz/vim/
+" Updated version available at:
+" http://www.aracnet.com/~waggoner
+"-----------------------------------------------------------------------------
+" Normally, this file will reside in the plugins directory and be
+" automatically sourced. If not, you must manually source this file
+" using :source explorer.vim
+"
+" To use it, just edit a directory (vi dirname) or type :Explore to
+" launch the file explorer in the current window, or :Sexplore to split
+" the current window and launch explorer there.
+"
+" If the current buffer is modified, the window is always split.
+"
+" It is also possible to delete files and rename files within explorer.
+" See :help file-explorer for more details
+"
+"-----------------------------------------------------------------------------
+" Update history removed, it's not very interesting.
+" Contributors were: Doug Potts, Bram Moolenaar, Thomas Köhler
+"
+" This is a modified version to be compatible with winmanager.vim.
+" Changes by Srinath Avadhanula
+"=============================================================================
+
+" Has this already been loaded?
+if exists("loaded_winfileexplorer")
+ finish
+endif
+let loaded_winfileexplorer=1
+
+" Line continuation used here
+let s:cpo_save = &cpo
+set cpo&vim
+
+"---
+" Default settings for global configuration variables
+
+" Split vertically instead of horizontally?
+if !exists("g:explVertical")
+ let g:explVertical=0
+endif
+
+" How big to make the window? Set to "" to avoid resizing
+if !exists("g:explWinSize")
+ let g:explWinSize=15
+endif
+
+" When opening a new file/directory, split below current window (or
+" above)? 1 = below, 0 = to above
+if !exists("g:explSplitBelow")
+ let g:explSplitBelow = &splitbelow
+endif
+
+" Split to right of current window (or to left)?
+" 1 = to right, 0 = to left
+if !exists("g:explSplitRight")
+ let g:explSplitRight = &splitright
+endif
+
+" Start the first explorer window...
+" Defaults to be the same as explSplitBelow
+if !exists("g:explStartBelow")
+ let g:explStartBelow = g:explSplitBelow
+endif
+
+" Start the first explorer window...
+" Defaults to be the same as explSplitRight
+if !exists("g:explStartRight")
+ let g:explStartRight = g:explSplitRight
+endif
+
+" Show detailed help?
+if !exists("g:explDetailedHelp")
+ let g:explDetailedHelp=0
+endif
+
+" Show file size and dates?
+if !exists("g:explDetailedList")
+ let g:explDetailedList=0
+endif
+
+" Format for the date
+if !exists("g:explDateFormat")
+ let g:explDateFormat="%d %b %Y %H:%M"
+endif
+
+" Files to hide
+if !exists("g:explHideFiles")
+ let g:explHideFiles=''
+endif
+
+" Field to sort by
+if !exists("g:explSortBy")
+ let g:explSortBy='name'
+endif
+
+" Segregate directories? 1, 0, or -1
+if !exists("g:explDirsFirst")
+ let g:explDirsFirst=1
+endif
+
+" Segregate items in suffixes option? 1, 0, or -1
+if !exists("g:explSuffixesLast")
+ let g:explSuffixesLast=1
+endif
+
+" Include separator lines between directories, files, and suffixes?
+if !exists("g:explUseSeparators")
+ let g:explUseSeparators=0
+endif
+
+" whether or not to take over the functioning of the default file-explorer
+" plugin
+if !exists("g:defaultExplorer")
+ let g:defaultExplorer = 1
+end
+
+if !exists('g:favDirs')
+ if exists('$HOME')
+ let s:favDirs = expand('$HOME').'/'
+ end
+else
+ if exists('$HOME')
+ let s:favDirs = g:favDirs."\/\n".expand('$HOME')
+ end
+end
+let s:favDirs = substitute(s:favDirs, '\', '/', 'g')
+let s:favDirs = substitute(s:favDirs, '\/\/', '\/', 'g')
+
+" -- stuff used by winmanager
+let g:FileExplorer_title = "[File List]"
+function! FileExplorer_Start()
+ let b:displayMode = "winmanager"
+ if exists('s:lastDirectoryDisplayed')
+ call s:EditDir(s:lastDirectoryDisplayed)
+ else
+ call s:EditDir(expand("%:p:h"))
+ end
+ if exists('s:lastCursorRow')
+ exe s:lastCursorRow
+ exe 'normal! '.s:lastCursorColumn.'|'
+ end
+endfunction
+
+function! FileExplorer_IsValid()
+ return 1
+endfunction
+
+function! FileExplorer_WrapUp()
+ let s:lastCursorRow = line('.')
+ let s:lastCursorColumn = virtcol('.')
+ let s:lastDirectoryDisplayed = b:completePath
+endfunction
+" --- end winmanager specific stuff (for now)
+
+"---
+" script variables - these are the same across all
+" explorer windows
+
+" characters that must be escaped for a regular expression
+let s:escregexp = '/*^$.~\'
+
+" 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 line to use for separating sections
+let s:separator='"---------------------------------------------------'
+
+"---
+" Create commands
+" commenting stuff for beta version release
+" if !exists(':Explore')
+" command -n=? -complete=dir Explore :call s:StartExplorer(0, '<a>')
+" endif
+" if !exists(':Sexplore')
+" command -n=? -complete=dir Sexplore :call s:StartExplorer(1, '<a>')
+" endif
+"
+"---
+" Start the explorer using the preferences from the global variables
+"
+function! s:StartExplorer(split, start_dir)
+ let startcmd = "edit"
+ if a:start_dir != ""
+ let fname=a:start_dir
+ else
+ let fname = expand("%:p:h")
+ endif
+ if fname == ""
+ let fname = getcwd()
+ endif
+
+ " Create a variable to use if splitting vertically
+ let splitMode = ""
+ if g:explVertical == 1
+ let splitMode = "vertical"
+ endif
+
+ " Save the user's settings for splitbelow and splitright
+ let savesplitbelow = &splitbelow
+ let savesplitright = &splitright
+
+ if a:split || &modified
+ let startcmd = splitMode . " " . g:explWinSize . "new " . fname
+ let &splitbelow = g:explStartBelow
+ let &splitright = g:explStartRight
+ else
+ let startcmd = "edit " . fname
+ endif
+ silent execute startcmd
+ let &splitbelow = savesplitbelow
+ let &splitright = savesplitright
+endfunction
+
+
+"---
+" This is the main entry for 'editing' a directory
+"
+function! s:EditDir(...)
+ " depending on the number of arguments, this function has either been called
+ " by winmanager or by doing "e dirname" or :Explore
+ if a:0 == 0
+ " Get out of here right away if this isn't a directory!
+ let name = expand("%")
+ if name == ""
+ let name = expand("%:p")
+ endif
+ elseif a:0 >= 1
+ let name = a:1
+ set modifiable
+ 1,$d_
+ end
+ if a:0 >= 2
+ let forceReDisplay = a:2
+ else
+ let forceReDisplay = 0
+ end
+
+ if !isdirectory(name)
+ return
+ endif
+
+ " Turn off the swapfile, set the buffer type so that it won't get
+ " written, and so that it will get deleted when it gets hidden.
+ setlocal modifiable
+ setlocal noswapfile
+ setlocal buftype=nowrite
+ setlocal bufhidden=delete
+ " Don't wrap around long lines
+ setlocal nowrap
+
+
+ " Get the complete path to the directory to look at with a slash at
+ " the end
+ let b:completePath = s:Path(name)
+ let s:lastDirectoryDisplayed = b:completePath
+
+ " Save the directory we are currently in and chdir to the directory
+ " we are editing so that we can get a real path to the directory,
+ " eliminating things like ".."
+ let origdir= s:Path(getcwd())
+ exe "chdir" escape(b:completePath,s:escfilename)
+ let b:completePath = s:Path(getcwd())
+ exe "chdir" escape(origdir,s:escfilename)
+
+ " Add a slash at the end
+ if b:completePath !~ '/$'
+ let b:completePath = b:completePath . '/'
+ endif
+
+ " escape special characters for exec commands
+ let b:completePathEsc=escape(b:completePath,s:escfilename)
+ let b:parentDirEsc=substitute(b:completePathEsc, '/[^/]*/$', '/', 'g')
+
+ " Set filter for hiding files
+ let b:filterFormula=substitute(g:explHideFiles, '\([^\\]\),', '\1\\|', 'g')
+ if b:filterFormula != ''
+ let b:filtering="\nNot showing: " . b:filterFormula
+ else
+ let b:filtering=""
+ endif
+
+
+ " added to allow directory caching
+ " s:numFileBuffers is an array containing the names of the directories
+ " visited.
+ if !exists("s:numFileBuffers")
+ let s:numFileBuffers = 0
+ end
+
+ let i = 1
+ while i <= s:numFileBuffers
+ exec 'let diri = s:dir_'.i
+ if diri == b:completePath
+ " if we are on a previously displayed directory which is being redrawn
+ " forcibly, then skip the stage of pasting from memory ...
+ if !forceReDisplay
+ let oldRep=&report
+ let save_sc = &sc
+ set report=10000 nosc
+ 1,$d _
+ exec 'put=s:FileList_'.i
+ 0d
+ 0
+ let b:maxFileLen = 0
+ /^"=/+1,$g/^/call s:MarkDirs()
+ call s:CleanUpHistory()
+ call s:PrintFavDirs()
+ 0
+ /^"=/+1
+ call s:CleanUpHistory()
+ let &report=oldRep
+ let &sc = save_sc
+ end
+ " ... merely remember the variable number and break.
+ let s:currentFileNumberDisplayed = i
+ break
+ endif
+ let i = i+1
+ endwhile
+
+ " No need for any insertmode abbreviations, since we don't allow
+ " insertions anyway!
+ iabc <buffer>
+
+ " Long or short listing? Use the global variable the first time
+ " explorer is called, after that use the script variable as set by
+ " the interactive user.
+ if exists("s:longlist")
+ let w:longlist = s:longlist
+ else
+ let w:longlist = g:explDetailedList
+ endif
+
+ " Show keyboard shortcuts?
+ if exists("s:longhelp")
+ let w:longhelp = s:longhelp
+ else
+ let w:longhelp = g:explDetailedHelp
+ endif
+
+ " Set the sort based on the global variables the first time. If you
+ " later change the sort order, it will be retained in the s:sortby
+ " variable for the next time you open explorer
+ let w:sortdirection=1
+ let w:sortdirlabel = ""
+ let w:sorttype = ""
+ if exists("s:sortby")
+ let sortby=s:sortby
+ else
+ let sortby=g:explSortBy
+ endif
+ if sortby =~ "reverse"
+ let w:sortdirection=-1
+ let w:sortdirlabel = "reverse "
+ endif
+ if sortby =~ "date"
+ let w:sorttype = "date"
+ elseif sortby =~ "size"
+ let w:sorttype = "size"
+ else
+ let w:sorttype = "name"
+ endif
+ call s:SetSuffixesLast()
+
+ " Set up syntax highlighting
+ " Something wrong with the evaluation of the conditional though...
+ if has("syntax") && exists("g:syntax_on") && !has("syntax_items")
+ syn match browseSynopsis "^\"[ -].*"
+ syn match favoriteDirectory "^+ .*$"
+ syn match browseDirectory "[^\"+].*/ "
+ syn match browseDirectory "[^\"+].*/$"
+ syn match browseCurDir "^\"= .*$"
+ syn match browseSortBy "^\" Sorted by .*$" contains=browseSuffixInfo
+ syn match browseSuffixInfo "(.*)$" contained
+ syn match browseFilter "^\" Not Showing:.*$"
+ syn match browseFiletime "«\d\+$"
+ exec('syn match browseSuffixes "' . b:suffixesHighlight . '"')
+
+ "hi def link browseSynopsis PreProc
+ hi def link browseSynopsis Special
+ hi def link browseDirectory Directory
+ hi def link browseCurDir Statement
+ hi def link favoriteDirectory Type
+ hi def link browseSortBy String
+ hi def link browseSuffixInfo Type
+ hi def link browseFilter String
+ hi def link browseFiletime Ignore
+ hi def link browseSuffixes Type
+ endif
+ " Set up mappings for this buffer
+ let cpo_save = &cpo
+ set cpo&vim
+
+ if exists("b:displayMode") && b:displayMode == "winmanager"
+ " when called in winmanager mode, the argument movefirst assumes the role
+ " of whether or not to split a window.
+ nnoremap <buffer> <cr> :call <SID>EditEntry(0,"winmanager")<cr>
+ nnoremap <buffer> <tab> :call <SID>EditEntry(1,"winmanager")<cr>
+ nnoremap <buffer> - :call <SID>EditDir(b:parentDirEsc)<cr>
+ nnoremap <buffer> <2-leftmouse> :call <SID>EditEntry(0,"winmanager")<cr>
+ nnoremap <buffer> C :call <SID>EditDir(getcwd(),1)<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> <F5> :call <SID>EditDir(b:completePath,1)<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> <C-^> <Nop>
+ nnoremap <buffer> f :call <SID>AddToFavDir()<cr>
+ else
+ nnoremap <buffer> <cr> :call <SID>EditEntry("","edit")<cr>
+ nnoremap <buffer> - :exec ("silent e " . b:parentDirEsc)<cr>
+ nnoremap <buffer> o :call <SID>OpenEntry()<cr>
+ nnoremap <buffer> O :call <SID>OpenEntryPrevWindow()<cr>
+ nnoremap <buffer> <2-leftmouse> :call <SID>DoubleClick()<cr>
+ endif
+ nnoremap <buffer> p :call <SID>EditEntry("","pedit")<cr>
+ nnoremap <buffer> a :call <SID>ShowAllFiles()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> R :call <SID>RenameFile()<cr>
+ nnoremap <buffer> D :. call <SID>DeleteFile()<cr>:call <SID>RestoreFileDisplay()<cr>
+ vnoremap <buffer> D :call <SID>DeleteFile()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> i :call <SID>ToggleLongList()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> s :call <SID>SortSelect()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> r :call <SID>SortReverse()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> ? :call <SID>ToggleHelp()<cr>
+ nnoremap <buffer> a :call <SID>ShowAllFiles()<cr>:call <SID>RestoreFileDisplay()<cr>
+ nnoremap <buffer> R :call <SID>RenameFile()<cr>
+ nnoremap <buffer> c :exec "cd ".b:completePathEsc<cr>:pwd<cr>
+ let &cpo = cpo_save
+
+ " If directory is already loaded, don't open it again!
+ if line('$') > 1
+ setlocal nomodifiable
+ return
+ endif
+
+ " Show the files
+ call s:ShowDirectory()
+ call s:PrintFavDirs()
+
+ " prevent the buffer from being modified
+ setlocal nomodifiable
+
+ " remember the contents of this directory if its been displayed for the
+ " first time for fast redraw later. if we have reached here bcause of a
+ " forcible redraw, do not create a new s:dir_i variable.
+ if !forceReDisplay
+ let s:numFileBuffers = s:numFileBuffers + 1
+ let s:currentFileNumberDisplayed = s:numFileBuffers
+ exe 'let s:dir_'.s:currentFileNumberDisplayed.' = b:completePath'
+ end
+ 0
+ /^"=/+1
+ call s:CleanUpHistory()
+ call s:RestoreFileDisplay()
+endfunction
+
+"---
+" If this is the only window, open file in a new window
+" Otherwise, open file in the most recently visited window
+"
+function! s:OpenEntryPrevWindow()
+ " Figure out if there are any other windows
+ let n = winnr()
+ wincmd p
+ " No other window? Then open a new one
+ if n == winnr()
+ call s:OpenEntry()
+ " Other windows exist
+ else
+ " Check if the previous buffer is modified - ask if they want to
+ " save!
+ let bufname = bufname(winbufnr(winnr()))
+ if &modified
+ let action=confirm("Save Changes in " . bufname . "?","&Yes\n&No\n&Cancel")
+ " Yes - try to save - if there is an error, cancel
+ if action == 1
+ let v:errmsg = ""
+ silent w
+ if v:errmsg != ""
+ echoerr "Unable to write buffer!"
+ wincmd p
+ return
+ endif
+ " No, abandon changes
+ elseif action == 2
+ set nomodified
+ echomsg "Warning, abandoning changes in " . bufname
+ " Cancel (or any other result), don't do the open
+ else
+ wincmd p
+ return
+ endif
+ endif
+ wincmd p
+ call s:EditEntry("wincmd p","edit")
+ endif
+endfunction
+
+"
+" save the contents of the currently displayed file listing into the current
+" s:dir_i variable
+"
+function! s:RestoreFileDisplay()
+ let oldRep=&report
+ let save_sc = &sc
+ set report=10000 nosc
+ let presLine = line('.')
+
+ let saverega = @a
+ normal! ggVG"ay
+ exec 'let s:FileList_'.s:currentFileNumberDisplayed.' = @a'
+ let @a = saverega
+
+ let &report=oldRep
+ let &sc = save_sc
+ exe presLine
+endfunction
+
+"---
+" Open a file or directory in a new window.
+" Use g:explSplitBelow and g:explSplitRight to decide where to put the
+" split window, and resize the original explorer window if it is
+" larger than g:explWinSize
+"
+function! s:OpenEntry()
+ " Are we on a line with a file name?
+ let l = getline(".")
+ if l =~ '^"'
+ return
+ endif
+
+ " Copy window settings to script settings
+ let s:sortby=w:sortdirlabel . w:sorttype
+ let s:longhelp = w:longhelp
+ let s:longlist = w:longlist
+
+ " Get the window number of the explorer window
+ let n = winnr()
+
+ " Save the user's settings for splitbelow and splitright
+ let savesplitbelow=&splitbelow
+ let savesplitright=&splitright
+
+ " Figure out how to do the split based on the user's preferences.
+ " We want to split to the (left,right,top,bottom) of the explorer
+ " window, but we want to extract the screen real-estate from the
+ " window next to the explorer if possible.
+ "
+ " 'there' will be set to a command to move from the split window
+ " back to the explorer window
+ "
+ " 'back' will be set to a command to move from the explorer window
+ " back to the newly split window
+ "
+ " 'right' and 'below' will be set to the settings needed for
+ " splitbelow and splitright IF the explorer is the only window.
+ "
+ if g:explVertical
+ if g:explSplitRight
+ let there="wincmd h"
+ let back ="wincmd l"
+ let right=1
+ let below=0
+ else
+ let there="wincmd l"
+ let back ="wincmd h"
+ let right=0
+ let below=0
+ endif
+ else
+ if g:explSplitBelow
+ let there="wincmd k"
+ let back ="wincmd j"
+ let right=0
+ let below=1
+ else
+ let there="wincmd j"
+ let back ="wincmd k"
+ let right=0
+ let below=0
+ endif
+ endif
+
+ " Get the file name
+ let fn=s:GetFullFileName()
+
+ " Attempt to go to adjacent window
+ exec(back)
+ " If no adjacent window, set splitright and splitbelow appropriately
+ if n == winnr()
+ let &splitright=right
+ let &splitbelow=below
+ else
+ " found adjacent window - invert split direction
+ let &splitright=!right
+ let &splitbelow=!below
+ endif
+
+ " Create a variable to use if splitting vertically
+ let splitMode = ""
+ if g:explVertical == 1
+ let splitMode = "vertical"
+ endif
+
+ " Is it a directory? If so, get a real path to it instead of
+ " relative path
+ if isdirectory(fn)
+ let origdir= s:Path(getcwd())
+ exe "chdir" escape(fn,s:escfilename)
+ let fn = s:Path(getcwd())
+ exe "chdir" escape(origdir,s:escfilename)
+ endif
+
+ " Open the new window
+ exec("silent " . splitMode." sp " . escape(fn,s:escfilename))
+
+ " resize the explorer window if it is larger than the requested size
+ exec(there)
+ if g:explWinSize =~ '[0-9]\+' && winheight("") > g:explWinSize
+ exec("silent ".splitMode." resize ".g:explWinSize)
+ endif
+ exec(back)
+
+ " Restore splitmode settings
+ let &splitbelow=savesplitbelow
+ let &splitright=savesplitright
+
+endfunction
+
+"---
+" Double click with the mouse
+"
+function s:DoubleClick()
+ if expand("<cfile>") =~ '[\\/]$'
+ call s:EditEntry("","edit") " directory: open in this window
+ else
+ call s:OpenEntryPrevWindow() " file: open in another window
+ endif
+endfun
+
+"---
+" Open file or directory in the same window as the explorer is
+" currently in
+"
+function! s:EditEntry(movefirst,editcmd)
+ " Are we on a line with a file name?
+ let l = getline(".")
+ if l =~ '^"'
+ return
+ endif
+
+ " Copy window settings to script settings
+ let s:sortby=w:sortdirlabel . w:sorttype
+ let s:longhelp = w:longhelp
+ let s:longlist = w:longlist
+
+ " Get the file name
+ let fn=s:GetFullFileName()
+ if isdirectory(fn)
+ let origdir= s:Path(getcwd())
+ exe "chdir" escape(fn,s:escfilename)
+ let fn = s:Path(getcwd())
+ exe "chdir" escape(origdir,s:escfilename)
+ endif
+
+ " if its the original explorer using this function, then proceed as before.
+ if !(exists("b:displayMode") && b:displayMode == "winmanager")
+ " Move to desired window if needed
+ exec(a:movefirst)
+ " Edit the file/dir
+ exec(a:editcmd . " " . escape(fn,s:escfilename))
+ " otherwise if its winmanager which called it, then do things the winmanager
+ " way, i.e, open directories in the same buffer and open files in the last
+ " visited file editing area (splitting if necessary)
+ else
+ if isdirectory(fn)
+ " callinng EditDir ensures that things are displayed in the same buffer.
+ call s:EditDir(fn)
+ else
+ " this function is provided by winmanager. it takes focus to the last
+ " visited buffer in the file editing area and then opens the new file in
+ " its place, while taking into consideration whether that buffer was
+ " modified, or whether the user wants to force a split each time, etc.
+ call WinManagerFileEdit(fn, a:movefirst)
+ end
+ end
+endfunction
+
+"---
+" Create a regular expression out of the suffixes option for sorting
+" and set a string to indicate whether we are sorting with the
+" suffixes at the end (or the beginning)
+"
+function! s:SetSuffixesLast()
+ let b:suffixesRegexp = '\(' . substitute(escape(&suffixes,s:escregexp),',','\\|','g') . '\)$'
+ let b:suffixesHighlight = '^[^"].*\(' . substitute(escape(&suffixes,s:escregexp),',','\\|','g') . '\)\( \|$\)'
+ if has("fname_case")
+ let b:suffixesRegexp = '\C' . b:suffixesRegexp
+ let b:suffixesHighlight = '\C' . b:suffixesHighlight
+ else
+ let b:suffixesRegexp = '\c' . b:suffixesRegexp
+ let b:suffixesHighlight = '\c' . b:suffixesHighlight
+ endif
+ if g:explSuffixesLast > 0 && &suffixes != ""
+ let b:suffixeslast=" (" . &suffixes . " at end of list)"
+ elseif g:explSuffixesLast < 0 && &suffixes != ""
+ let b:suffixeslast=" (" . &suffixes . " at start of list)"
+ else
+ let b:suffixeslast=" ('suffixes' mixed with files)"
+ endif
+endfunction
+
+"---
+" Show the header and contents of the directory
+"
+function! s:ShowDirectory()
+ " Prevent a report of our actions from showing up
+ let oldRep=&report
+ let save_sc = &sc
+ set report=10000 nosc
+
+ "Delete all lines
+ 1,$d _
+
+ " Add the header
+ call s:AddHeader()
+ $d _
+
+ " Display the files
+
+ " Get a list of all the files
+ let files = s:Path(glob(b:completePath."*"))
+ if files != "" && files !~ '\n$'
+ let files = files . "\n"
+ endif
+
+ " Add the dot files now, making sure "." is not included!
+ let files = files . substitute(s:Path(glob(b:completePath.".*")), "[^\n]*/./\\=\n", '' , '')
+ if files != "" && files !~ '\n$'
+ let files = files . "\n"
+ endif
+
+ " Are there any files left after filtering?
+ if files != ""
+ normal! mt
+ put =files
+ let b:maxFileLen = 0
+ 0
+ /^"=/+1,$g/^/call s:MarkDirs()
+ call s:CleanUpHistory()
+ normal! `t
+ call s:AddFileInfo()
+ endif
+
+ normal! zz
+
+ " Move to first directory in the listing
+ 0
+ /^"=/+1
+ call s:CleanUpHistory()
+
+ " Do the sort
+ call s:SortListing("Loaded contents of ".b:completePath.". ")
+
+ " Move to first directory in the listing
+ 0
+ /^"=/+1
+ call s:CleanUpHistory()
+
+ let &report=oldRep
+ let &sc = save_sc
+
+endfunction
+
+function! s:AddToFavDir()
+
+ if s:favDirs !~ "\\(^\\|\n\\)".b:completePath."\\(\n\\|$\\)"
+ let s:favDirs = s:favDirs."\n".b:completePath
+ else
+ return
+ endif
+
+ let pos = (line('.')+1).' | normal! '.virtcol('.').'|'
+ call s:PrintFavDirs()
+ exe pos
+endfunction
+
+"---
+" Mark which items are directories - called once for each file name
+" must be used only when size/date is not displayed
+"
+function! s:MarkDirs()
+ let oldRep=&report
+ set report=1000
+ "Remove slashes if added
+ s;/$;;e
+ "Removes all the leading slashes and adds slashes at the end of directories
+ s;^.*\\\([^\\]*\)$;\1;e
+ s;^.*/\([^/]*\)$;\1;e
+ "normal! ^
+ let currLine=getline(".")
+ if isdirectory(b:completePath . currLine)
+ s;$;/;
+ let fileLen=strlen(currLine)+1
+ else
+ let fileLen=strlen(currLine)
+ if (b:filterFormula!="") && (currLine =~ b:filterFormula)
+ " Don't show the file if it is to be filtered.
+ d _
+ endif
+ endif
+ if fileLen > b:maxFileLen
+ let b:maxFileLen=fileLen
+ endif
+ let &report=oldRep
+endfunction
+
+"---
+" Make sure a path has proper form
+"
+function! s:Path(p)
+ if has("dos16") || has("dos32") || has("win16") || has("win32") || has("os2")
+ return substitute(a:p,'\\','/','g')
+ else
+ return a:p
+ endif
+endfunction
+
+"---
+" Extract the file name from a line in several different forms
+"
+function! s:GetFullFileNameEsc()
+ return s:EscapeFilename(s:GetFullFileName())
+endfunction
+
+function! s:GetFileNameEsc()
+ return s:EscapeFilename(s:GetFileName())
+endfunction
+
+function! s:EscapeFilename(name)
+ return escape(a:name,s:escfilename)
+endfunction
+
+
+function! s:GetFullFileName()
+ if getline('.') =~ '+ '
+ if match(getline('.'), '(.*)') > 0
+ return matchstr(getline('.'), '(\zs.*\ze)')
+ else
+ return strpart(getline('.'), 2, 1000)
+ endif
+ endif
+ return s:ExtractFullFileName(getline("."))
+endfunction
+
+function! s:GetFileName()
+ return s:ExtractFileName(getline("."))
+endfunction
+
+function! s:ExtractFullFileName(line)
+ let fn=s:ExtractFileName(a:line)
+ if fn == '/'
+ return b:completePath
+ else
+ return b:completePath . s:ExtractFileName(a:line)
+ endif
+endfunction
+
+function! s:ExtractFileName(line)
+ return substitute(strpart(a:line,0,b:maxFileLen),'\s\+$','','')
+endfunction
+
+"---
+" Get the size of the file
+function! s:ExtractFileSize(line)
+ if (w:longlist==0)
+ return getfsize(s:ExtractFileName(a:line))
+ else
+ return strpart(a:line,b:maxFileLen+2,b:maxFileSizeLen);
+ endif
+endfunction
+
+"---
+" Get the date of the file as a number
+function! s:ExtractFileDate(line)
+ if w:longlist==0
+ return getftime(s:ExtractFileName(a:line))
+ else
+ return strpart(matchstr(strpart(a:line,b:maxFileLen+b:maxFileSizeLen+4),"«.*"),1) + 0
+ endif
+endfunction
+
+
+"---
+" Add the header with help information
+"
+function! s:AddHeader()
+ let save_f=@f
+ 1
+ if w:longhelp==1
+ let @f="\" <enter> : open file or directory\n"
+ \."\" o : open new window for file/directory\n"
+ \."\" O : open file in previously visited window\n"
+ \."\" p : preview the file\n"
+ \."\" i : toggle size/date listing\n"
+ \."\" s : select sort field r : reverse sort\n"
+ \."\" - : go up one level c : cd to this dir\n"
+ \."\" R : rename file D : delete file\n"
+ \."\" f : add current directory to favourites\n"
+ \."\" :help file-explorer for detailed help\n"
+ else
+ let @f="\" Press ? for keyboard shortcuts\n"
+ endif
+ let @f=@f."\" Sorted by ".w:sortdirlabel.w:sorttype.b:suffixeslast.b:filtering."\n"
+ let @f=@f."\"= ".b:completePath."\n"
+ put! f
+ let @f=save_f
+endfunction
+
+function! s:PrintFavDirs()
+ if !exists('s:favDirs')
+ return
+ end
+ setlocal modifiable
+ 0
+ if search('^"=')
+ exe 'silent! 1,'.line('.').' g/^+ .*$/d _'
+ else
+ call s:CleanUpHistory()
+ setlocal nomodifiable nomodified
+ return
+ endif
+ call s:CleanUpHistory()
+ let favDirs = s:favDirs
+ let favDirs = substitute(favDirs, "\\(^\\|\n\\)", '\1+ ', 'g')
+ let favDirs = substitute(favDirs, '$', "\n", '')
+ 0
+ call search('^"=')
+ silent! put!=favDirs
+ silent! g/^+ /s/\v^\+ (.*)\/([^\/]+\/=)$/+ \2 (\1\/\2)
+ call s:CleanUpHistory()
+ call s:CleanUpHistory()
+ setlocal nomodifiable nomodified
+endfunction
+
+"---
+" Show the size and date for each file
+"
+function! s:AddFileInfo()
+ let save_sc = &sc
+ set nosc
+
+ " Mark our starting point
+ normal! mt
+
+ call s:RemoveSeparators()
+
+ " Remove all info
+ 0
+ /^"=/+1,$g/^/call setline(line("."),s:GetFileName())
+ call s:CleanUpHistory()
+
+ " Add info if requested
+ if w:longlist==1
+ " Add file size and calculate maximum length of file size field
+ let b:maxFileSizeLen = 0
+ 0
+ /^"=/+1,$g/^/let fn=s:GetFullFileName() |
+ \let fileSize=getfsize(fn) |
+ \let fileSizeLen=strlen(fileSize) |
+ \if fileSizeLen > b:maxFileSizeLen |
+ \ let b:maxFileSizeLen = fileSizeLen |
+ \endif |
+ \exec "normal! ".(b:maxFileLen-strlen(getline("."))+2)."A \<esc>" |
+ \exec 's/$/'.fileSize.'/'
+ call s:CleanUpHistory()
+
+ " Right justify the file sizes and
+ " add file modification date
+ 0
+ /^"=/+1,$g/^/let fn=s:GetFullFileName() |
+ \exec "normal! A \<esc>$b".(b:maxFileLen+b:maxFileSizeLen-strlen(getline("."))+3)."i \<esc>\"_x" |
+ \exec 's/$/ '.escape(s:FileModDate(fn), '/').'/'
+ call s:CleanUpHistory()
+ setlocal nomodified
+ endif
+
+ call s:AddSeparators()
+
+ " return to start
+ normal! `t
+
+ let &sc = save_sc
+endfunction
+
+
+"----
+" Get the modification time for a file
+"
+function! s:FileModDate(name)
+ let filetime=getftime(a:name)
+ if filetime > 0
+ return strftime(g:explDateFormat,filetime) . " «" . filetime
+ else
+ return ""
+ endif
+endfunction
+
+"---
+" Delete a file or files
+"
+function! s:DeleteFile() range
+ let oldRep = &report
+ let &report = 1000
+
+ let filesDeleted = 0
+ let stopDel = 0
+ let delAll = 0
+ let currLine = a:firstline
+ let lastLine = a:lastline
+ setlocal modifiable
+
+ while ((currLine <= lastLine) && (stopDel==0))
+ exec(currLine)
+ let fileName=s:GetFullFileName()
+ if isdirectory(fileName)
+ echo fileName." : Directory deletion not supported yet"
+ let currLine = currLine + 1
+ else
+ if delAll == 0
+ let sure=input("Delete ".fileName." (y/n/a/q)? ")
+ if sure=="a"
+ let delAll = 1
+ endif
+ endif
+ if (sure=="y") || (sure=="a")
+ let success=delete(fileName)
+ if success!=0
+ exec (" ")
+ echo "\nCannot delete ".fileName
+ let currLine = currLine + 1
+ else
+ d _
+ let filesDeleted = filesDeleted + 1
+ let lastLine = lastLine - 1
+ endif
+ elseif sure=="q"
+ let stopDel = 1
+ elseif sure=="n"
+ let currLine = currLine + 1
+ endif
+ endif
+ endwhile
+ echo "\n".filesDeleted." files deleted"
+ let &report = oldRep
+ setlocal nomodified
+ setlocal nomodifiable
+endfunction
+
+"---
+" Rename a file
+"
+function! s:RenameFile()
+ let fileName=s:GetFullFileName()
+ setlocal modifiable
+ if isdirectory(fileName)
+ echo "Directory renaming not supported yet"
+ elseif filereadable(fileName)
+ let altName=input("Rename ".fileName." to : ")
+ echo " "
+ if altName==""
+ setlocal nomodifiable
+ return
+ endif
+ let success=rename(fileName, b:completePath.altName)
+ if success!=0
+ echo "Cannot rename ".fileName. " to ".altName
+ else
+ echo "Renamed ".fileName." to ".altName
+ let oldRep=&report
+ set report=1000
+ " e!
+ " instead of generating a bufEnter event if we use e!, use EditDir. It
+ " doesnt matter that EditDir() is called with more than 0 arguments
+ " whether or not winmanager is active because at this location, we have
+ " a buffer open anyway.
+ call s:EditDir(b:completePath, 1)
+ let &report=oldRep
+ endif
+ endif
+ setlocal nomodified
+ setlocal nomodifiable
+ call s:RestoreFileDisplay()
+endfunction
+
+"---
+" Toggle between short and long help
+"
+function! s:ToggleHelp()
+ if exists("w:longhelp") && w:longhelp==0
+ let w:longhelp=1
+ let s:longhelp=1
+ else
+ let w:longhelp=0
+ let s:longhelp=0
+ endif
+ " Allow modification
+ setlocal modifiable
+ call s:UpdateHeader()
+ " Disallow modification
+ setlocal nomodifiable
+endfunction
+
+"---
+" Update the header
+"
+function! s:UpdateHeader()
+ let oldRep=&report
+ set report=10000
+ " Save position
+ normal! mt
+ " Remove old header
+ 0
+ 1,/^"=/ d _
+ call s:CleanUpHistory()
+ " Add new header
+ call s:AddHeader()
+ " Go back where we came from if possible
+ 0
+ if line("'t") != 0
+ normal! `t
+ endif
+
+ let &report=oldRep
+ setlocal nomodified
+endfunction
+
+"---
+" Toggle long vs. short listing
+"
+function! s:ToggleLongList()
+ setlocal modifiable
+ if exists("w:longlist") && w:longlist==1
+ let w:longlist=0
+ let s:longlist=0
+ else
+ let w:longlist=1
+ let s:longlist=1
+ endif
+ call s:AddFileInfo()
+ setlocal nomodifiable
+endfunction
+
+"---
+" Show all files - remove filtering
+"
+function! s:ShowAllFiles()
+ setlocal modifiable
+ let b:filterFormula=""
+ let b:filtering=""
+ call s:ShowDirectory()
+ setlocal nomodifiable
+endfunction
+
+"---
+" Figure out what section we are in
+"
+function! s:GetSection()
+ let fn=s:GetFileName()
+ let section="file"
+ if fn =~ '/$'
+ let section="directory"
+ elseif fn =~ b:suffixesRegexp
+ let section="suffixes"
+ endif
+ return section
+endfunction
+
+"---
+" Remove section separators
+"
+function! s:RemoveSeparators()
+ if !g:explUseSeparators
+ return
+ endif
+ 0
+ silent! exec '/^"=/+1,$g/^' . s:separator . "/d _"
+ call s:CleanUpHistory()
+endfunction
+
+"---
+" Add section separators
+" between directories and files if they are separated
+" between files and 'suffixes' files if they are separated
+function! s:AddSeparators()
+ if !g:explUseSeparators
+ return
+ endif
+ 0
+ /^"=/+1
+ call s:CleanUpHistory()
+ let lastsec=s:GetSection()
+ +1
+ .,$g/^/let sec=s:GetSection() |
+ \if g:explDirsFirst != 0 && sec != lastsec &&
+ \ (lastsec == "directory" || sec == "directory") |
+ \ exec "normal! I" . s:separator . "\n\<esc>" |
+ \elseif g:explSuffixesLast != 0 && sec != lastsec &&
+ \ (lastsec == "suffixes" || sec == "suffixes") |
+ \ exec "normal! I" . s:separator . "\n\<esc>" |
+ \endif |
+ \let lastsec=sec
+endfunction
+
+"---
+" General string comparison function
+"
+function! s:StrCmp(line1, line2, direction)
+ if a:line1 < a:line2
+ return -a:direction
+ elseif a:line1 > a:line2
+ return a:direction
+ else
+ return 0
+ endif
+endfunction
+
+"---
+" Function for use with Sort(), to compare the file names
+" Default sort is to put in alphabetical order, but with all directory
+" names before all file names
+"
+function! s:FileNameCmp(line1, line2, direction)
+ let f1=s:ExtractFileName(a:line1)
+ let f2=s:ExtractFileName(a:line2)
+
+ " Put directory names before file names
+ if (g:explDirsFirst != 0) && (f1 =~ '\/$') && (f2 !~ '\/$')
+ return -g:explDirsFirst
+ elseif (g:explDirsFirst != 0) && (f1 !~ '\/$') && (f2 =~ '\/$')
+ return g:explDirsFirst
+ elseif (g:explSuffixesLast != 0) && (f1 =~ b:suffixesRegexp) && (f2 !~ b:suffixesRegexp)
+ return g:explSuffixesLast
+ elseif (g:explSuffixesLast != 0) && (f1 !~ b:suffixesRegexp) && (f2 =~ b:suffixesRegexp)
+ return -g:explSuffixesLast
+ else
+ return s:StrCmp(f1,f2,a:direction)
+ endif
+
+endfunction
+
+"---
+" Function for use with Sort(), to compare the file modification dates
+" Default sort is to put NEWEST files first. Reverse will put oldest
+" files first
+"
+function! s:FileDateCmp(line1, line2, direction)
+ let f1=s:ExtractFileName(a:line1)
+ let f2=s:ExtractFileName(a:line2)
+ let t1=s:ExtractFileDate(a:line1)
+ let t2=s:ExtractFileDate(a:line2)
+
+ " Put directory names before file names
+ if (g:explDirsFirst != 0) && (f1 =~ '\/$') && (f2 !~ '\/$')
+ return -g:explDirsFirst
+ elseif (g:explDirsFirst != 0) && (f1 !~ '\/$') && (f2 =~ '\/$')
+ return g:explDirsFirst
+ elseif (g:explSuffixesLast != 0) && (f1 =~ b:suffixesRegexp) && (f2 !~ b:suffixesRegexp)
+ return g:explSuffixesLast
+ elseif (g:explSuffixesLast != 0) && (f1 !~ b:suffixesRegexp) && (f2 =~ b:suffixesRegexp)
+ return -g:explSuffixesLast
+ elseif t1 > t2
+ return -a:direction
+ elseif t1 < t2
+ return a:direction
+ else
+ return s:StrCmp(f1,f2,1)
+ endif
+endfunction
+
+"---
+" Function for use with Sort(), to compare the file sizes
+" Default sort is to put largest files first. Reverse will put
+" smallest files first
+"
+function! s:FileSizeCmp(line1, line2, direction)
+ let f1=s:ExtractFileName(a:line1)
+ let f2=s:ExtractFileName(a:line2)
+ let s1=s:ExtractFileSize(a:line1)
+ let s2=s:ExtractFileSize(a:line2)
+
+ if (g:explDirsFirst != 0) && (f1 =~ '\/$') && (f2 !~ '\/$')
+ return -g:explDirsFirst
+ elseif (g:explDirsFirst != 0) && (f1 !~ '\/$') && (f2 =~ '\/$')
+ return g:explDirsFirst
+ elseif (g:explSuffixesLast != 0) && (f1 =~ b:suffixesRegexp) && (f2 !~ b:suffixesRegexp)
+ return g:explSuffixesLast
+ elseif (g:explSuffixesLast != 0) && (f1 !~ b:suffixesRegexp) && (f2 =~ b:suffixesRegexp)
+ return -g:explSuffixesLast
+ elseif s1 > s2
+ return -a:direction
+ elseif s1 < s2
+ return a:direction
+ else
+ return s:StrCmp(f1,f2,1)
+ endif
+endfunction
+
+"---
+" Sort lines. SortR() is called recursively.
+"
+function! s:SortR(start, end, cmp, direction)
+
+ " Bottom of the recursion if start reaches end
+ if a:start >= a:end
+ return
+ endif
+ "
+ let partition = a:start - 1
+ let middle = partition
+ let partStr = getline((a:start + a:end) / 2)
+ let i = a:start
+ while (i <= a:end)
+ let str = getline(i)
+ exec "let result = " . a:cmp . "(str, partStr, " . a:direction . ")"
+ if result <= 0
+ " Need to put it before the partition. Swap lines i and partition.
+ let partition = partition + 1
+ if result == 0
+ let middle = partition
+ endif
+ if i != partition
+ let str2 = getline(partition)
+ call setline(i, str2)
+ call setline(partition, str)
+ endif
+ endif
+ let i = i + 1
+ endwhile
+
+ " Now we have a pointer to the "middle" element, as far as partitioning
+ " goes, which could be anywhere before the partition. Make sure it is at
+ " the end of the partition.
+ if middle != partition
+ let str = getline(middle)
+ let str2 = getline(partition)
+ call setline(middle, str2)
+ call setline(partition, str)
+ endif
+ call s:SortR(a:start, partition - 1, a:cmp,a:direction)
+ call s:SortR(partition + 1, a:end, a:cmp,a:direction)
+endfunction
+
+"---
+" To Sort a range of lines, pass the range to Sort() along with the name of a
+" function that will compare two lines.
+"
+function! s:Sort(cmp,direction) range
+ call s:SortR(a:firstline, a:lastline, a:cmp, a:direction)
+endfunction
+
+"---
+" Reverse the current sort order
+"
+function! s:SortReverse()
+ if exists("w:sortdirection") && w:sortdirection == -1
+ let w:sortdirection = 1
+ let w:sortdirlabel = ""
+ else
+ let w:sortdirection = -1
+ let w:sortdirlabel = "reverse "
+ endif
+ let s:sortby=w:sortdirlabel . w:sorttype
+ call s:SortListing("")
+endfunction
+
+"---
+" Toggle through the different sort orders
+"
+function! s:SortSelect()
+ " Select the next sort option
+ if !exists("w:sorttype")
+ let w:sorttype="name"
+ elseif w:sorttype == "name"
+ let w:sorttype="size"
+ elseif w:sorttype == "size"
+ let w:sorttype="date"
+ else
+ let w:sorttype="name"
+ endif
+ let s:sortby=w:sortdirlabel . w:sorttype
+ call s:SortListing("")
+endfunction
+
+"---
+" Sort the file listing
+"
+function! s:SortListing(msg)
+ " Save the line we start on so we can go back there when done
+ " sorting
+ let startline = getline(".")
+ let col=col(".")
+ let lin=line(".")
+
+ " Allow modification
+ setlocal modifiable
+
+ " Send a message about what we're doing
+ " Don't really need this - it can cause hit return prompts
+" echo a:msg . "Sorting by" . w:sortdirlabel . w:sorttype
+
+ " Create a regular expression out of the suffixes option in case
+ " we need it.
+ call s:SetSuffixesLast()
+
+ " Remove section separators
+ call s:RemoveSeparators()
+
+ " Do the sort
+ 0
+ if w:sorttype == "size"
+ /^"=/+1,$call s:Sort("s:FileSizeCmp",w:sortdirection)
+ elseif w:sorttype == "date"
+ /^"=/+1,$call s:Sort("s:FileDateCmp",w:sortdirection)
+ else
+ /^"=/+1,$call s:Sort("s:FileNameCmp",w:sortdirection)
+ endif
+ call s:CleanUpHistory()
+
+ " Replace the header with updated information
+ call s:UpdateHeader()
+
+ " Restore section separators
+ call s:AddSeparators()
+
+ " Return to the position we started on
+ 0
+ if search('\m^'.escape(startline,s:escregexp),'W') <= 0
+ execute lin
+ endif
+ execute "normal!" col . "|"
+
+ " Disallow modification
+ setlocal nomodified
+ setlocal nomodifiable
+
+endfunction
+
+if !g:defaultExplorer
+ let loaded_explorer = 1
+ "---
+ " Create commands
+ if !exists(':Explore')
+ command -n=? -complete=dir Explore :call s:StartExplorer(0, '<a>')
+ endif
+ if !exists(':Sexplore')
+ command -n=? -complete=dir Sexplore :call s:StartExplorer(1, '<a>')
+ endif
+ " NOTE: This is a special command NOT to be used by users. Its here for
+ " communication between winmanager and explorer.vim. This command only works
+ " if you are currently 'editing' a directory, in which case, you dont need
+ " this anyway. USE AT YOUR OWN RISK.
+ if !exists(':ExploreInCurrentWindow')
+ command -n=? -complete=dir ExploreInCurrentWindow :call <SID>EditDir()
+ endif
+end
+
+" CleanUpHistory
+function! <SID>CleanUpHistory()
+ call histdel("/", -1)
+ let @/ = histget("/", -1)
+endfunction
+
+" restore 'cpo'
+let &cpo = s:cpo_save
+unlet s:cpo_save
+
+
+" vim: ts=4:noet:sw=4