3539 lines
118 KiB
VimL
3539 lines
118 KiB
VimL
"==================================================
|
|
" File: VimExplorer.vim
|
|
" Brief: VE - the File Manager within Vim!
|
|
" Authors: Ming Bai <mbbill AT gmail DOT com>
|
|
" Last Change: 2009-05-06 00:20:25
|
|
" Version: 0.99
|
|
" Licence: LGPL
|
|
"
|
|
" Usage: :h VimExplorer
|
|
"
|
|
"==================================================
|
|
|
|
|
|
" See if we are already loaded, thanks to Dennis Hostetler.
|
|
if exists("loaded_vimExplorer")
|
|
finish
|
|
else
|
|
let loaded_vimExplorer = 1
|
|
endif
|
|
"
|
|
|
|
" Vim version 7.x is needed.
|
|
if v:version < 700
|
|
echohl ErrorMsg | echomsg "VimExplorer needs vim version >= 7.0!" | echohl None
|
|
finish
|
|
endif
|
|
|
|
"Load config {{{1
|
|
"#######################################################################
|
|
"VimExplorer configuration.
|
|
"
|
|
let VEConf = {}
|
|
|
|
"Normal configurations.
|
|
|
|
"Common settings
|
|
"==========================================
|
|
|
|
"Important! It is used to do iconv() to the path when calling
|
|
"sytem() function. Mine is Simplified Chinese (cp936).
|
|
if exists("g:VEConf_systemEncoding")
|
|
let VEConf.systemEncoding = g:VEConf_systemEncoding
|
|
else
|
|
let VEConf.systemEncoding = ''
|
|
endif
|
|
|
|
"VimExplorer will check all the disks in this list at startup.
|
|
"Delete some of these to fit your system can increase start up
|
|
"speed.
|
|
"let VEConf.win32Disks = ["C:","D:","E:"]
|
|
if exists("g:VEConf_win32Disks")
|
|
let VEConf.win32Disks = g:VEConf_win32Disks
|
|
else
|
|
let VEConf.win32Disks = ["A:","B:","C:","D:","E:","F:","G:","H:",
|
|
\"I:","J:","K:","L:","M:","N:","O:","P:","Q:","R:",
|
|
\"S:","T:","U:","V:","W:","X:","Y:","Z:"]
|
|
endif
|
|
|
|
"Set the forward and backward history stack depth.
|
|
if exists("g:VEConf_browseHistory")
|
|
let VEConf.browseHistory = g:VEConf_browseHistory
|
|
else
|
|
let VEConf.browseHistory = 100
|
|
endif
|
|
|
|
"Split location of preview window
|
|
if exists("g:VEConf_previewSplitLocation")
|
|
let VEConf.previewSplitLocation = g:VEConf_previewSplitLocation
|
|
else
|
|
let VEConf.previewSplitLocation = "belowright"
|
|
endif
|
|
|
|
"Show hidden files ( .* )
|
|
if exists("g:VEConf_showHiddenFiles")
|
|
let VEConf.showHiddenFiles = VEConf_showHiddenFiles
|
|
else
|
|
let VEConf.showHiddenFiles = 1
|
|
endif
|
|
|
|
"External explorer name
|
|
if (has("win32") || has("win95") || has("win64") || has("win16") || has("dos32"))
|
|
if exists("g:VEConf_externalExplorer")
|
|
let VEConf.externalExplorer = g:VEConf_externalExplorer
|
|
else
|
|
let VEConf.externalExplorer = "explorer.exe"
|
|
endif
|
|
else
|
|
if exists("g:VEConf_externalExplorer")
|
|
let VEConf.externalExplorer = g:VEConf_externalExplorer
|
|
else
|
|
let VEConf.externalExplorer = "nautilus"
|
|
endif
|
|
endif
|
|
|
|
"Sort case sensitive , for everything
|
|
if exists("g:VEConf_sortCaseSensitive")
|
|
let VEConf.sortCaseSensitive = g:VEConf_sortCaseSensitive
|
|
else
|
|
let VEConf.sortCaseSensitive = 0
|
|
endif
|
|
|
|
"favorite file name
|
|
if exists("g:VEConf_favorite")
|
|
let VEConf.favorite = g:VEConf_favorite
|
|
else
|
|
let VEConf.favorite = ".ve_favorite"
|
|
endif
|
|
|
|
"Overwrite existing files.
|
|
"boverWrite 0 ask, 1 allyes, 2 allno
|
|
if exists("g:VEConf_overWriteExisting")
|
|
let VEConf.overWriteExisting = g:VEConf_overWriteExisting
|
|
else
|
|
let VEConf.overWriteExisting = 0
|
|
endif
|
|
|
|
"Kde or gonme.
|
|
if !exists("g:VEConf_usingKDE")
|
|
let g:VEConf_usingKDE = 0
|
|
endif
|
|
if !exists("g:VEConf_usingGnome")
|
|
let g:VEConf_usingGnome = 0
|
|
endif
|
|
|
|
"Recycle path
|
|
if !exists("g:VEConf_recyclePath")
|
|
let g:VEConf.recyclePath = ''
|
|
else
|
|
let g:VEConf.recyclePath = g:VEConf_recyclePath
|
|
endif
|
|
|
|
"Tree panel settings
|
|
"==========================================
|
|
|
|
"Show '+' before empty folders.
|
|
"It will cause a little performance lost.
|
|
if exists("g:VEConf_showFolderStatus")
|
|
let VEConf.showFolderStatus = g:VEConf_showFolderStatus
|
|
else
|
|
let VEConf.showFolderStatus = 1
|
|
endif
|
|
|
|
"Tree panel width
|
|
if exists("g:VEConf_treePanelWidth")
|
|
let VEConf.treePanelWidth = g:VEConf_treePanelWidth
|
|
else
|
|
let VEConf.treePanelWidth = 30
|
|
endif
|
|
|
|
"Split mode of tree panel
|
|
if exists("g:VEConf_treePanelSplitMode")
|
|
let VEConf.treePanelSplitMode = g:VEConf_treePanelSplitMode
|
|
else
|
|
let VEConf.treePanelSplitMode = "vertical"
|
|
endif
|
|
|
|
"Split location of file panel
|
|
if exists("g:VEConf_treePanelSplitLocation")
|
|
let VEConf.treePanelSplitLocation = g:VEConf_treePanelSplitLocation
|
|
else
|
|
let VEConf.treePanelSplitLocation = "leftabove"
|
|
endif
|
|
|
|
"Set the tree panel sort direction.
|
|
if exists("g:VEConf_treeSortDirection")
|
|
let VEConf.treeSortDirection = g:VEConf_treeSortDirection
|
|
else
|
|
let VEConf.treeSortDirection = 1
|
|
endif
|
|
|
|
"File panel settings
|
|
"==========================================
|
|
|
|
"Set the file group sort direction.
|
|
if exists("g:VEConf_fileGroupSortDirection")
|
|
let VEConf.fileGroupSortDirection = g:VEConf_fileGroupSortDirection
|
|
else
|
|
let VEConf.fileGroupSortDirection = 1
|
|
endif
|
|
|
|
"Delete file confirm.
|
|
if exists("g:VEConf_fileDeleteConfirm")
|
|
let VEConf.fileDeleteConfirm = g:VEConf_fileDeleteConfirm
|
|
else
|
|
let VEConf.fileDeleteConfirm = 1
|
|
endif
|
|
|
|
"File panel width
|
|
if exists("g:VEConf_filePanelWidth")
|
|
let VEConf.filePanelWidth = g:VEConf_filePanelWidth
|
|
else
|
|
let VEConf.filePanelWidth = 40
|
|
endif
|
|
|
|
"Split mode of file panel
|
|
if exists("g:VEConf_filePanelSplitMode")
|
|
let VEConf.filePanelSplitMode = g:VEConf_filePanelSplitMode
|
|
else
|
|
let VEConf.filePanelSplitMode = "vertical"
|
|
endif
|
|
|
|
"Split location of file panel
|
|
if exists("g:VEConf_filePanelSplitLocation")
|
|
let VEConf.filePanelSplitLocation = g:VEConf_filePanelSplitLocation
|
|
else
|
|
let VEConf.filePanelSplitLocation = "belowright"
|
|
endif
|
|
|
|
"File panel sort type.
|
|
if exists("g:VEConf_filePanelSortType")
|
|
let VEConf.filePanelSortType = g:VEConf_filePanelSortType
|
|
else
|
|
let VEConf.filePanelSortType = 0
|
|
endif
|
|
|
|
"Show file size in M/K/B
|
|
if exists("g:VEConf_showFileSizeInMKB")
|
|
let VEConf.showFileSizeInMKB = g:VEConf_showFileSizeInMKB
|
|
else
|
|
let VEConf.showFileSizeInMKB = 1
|
|
endif
|
|
|
|
"File panel filter.
|
|
if exists("g:VEConf_filePanelFilter")
|
|
let VEConf.filePanelFilter = g:VEConf_filePanelFilter
|
|
else
|
|
let VEConf.filePanelFilter = ''
|
|
endif
|
|
|
|
|
|
"#######################################################################
|
|
"Tree panel hot key bindings.
|
|
let VEConf.treePanelHotkey = {}
|
|
let VEConf.treePanelHotkey.help = '?'
|
|
let VEConf.treePanelHotkey.toggleNode = '<cr>'
|
|
let VEConf.treePanelHotkey.toggleNodeMouse = '<2-LeftMouse>'
|
|
let VEConf.treePanelHotkey.refresh = 'r'
|
|
let VEConf.treePanelHotkey.favorite = 'f'
|
|
let VEConf.treePanelHotkey.addToFavorite = 'F'
|
|
let VEConf.treePanelHotkey.browseHistory = 'b'
|
|
let VEConf.treePanelHotkey.toggleFilePanel = 't'
|
|
let VEConf.treePanelHotkey.toUpperDir = '<bs>'
|
|
let VEConf.treePanelHotkey.switchPanel = '<c-tab>'
|
|
let VEConf.treePanelHotkey.gotoPath = '<c-g>'
|
|
let VEConf.treePanelHotkey.quitVE = 'Q'
|
|
|
|
if exists("g:VEConf_treeHotkey")
|
|
if type(g:VEConf_treeHotkey) != type({})
|
|
echohl WarningMsg | echo "g:VEConf_treeHotkey is not dictionary type!" | echohl None
|
|
finish
|
|
endif
|
|
for i in keys(g:VEConf_treeHotkey)
|
|
let VEConf.treePanelHotkey[i] = g:VEConf_treeHotkey[i]
|
|
endfor
|
|
endif
|
|
|
|
"File panel hot key bindings.
|
|
"normal mode hotkeys
|
|
let VEConf.filePanelHotkey = {}
|
|
"normal
|
|
let VEConf.filePanelHotkey.help = '?'
|
|
let VEConf.filePanelHotkey.itemClicked = '<cr>'
|
|
let VEConf.filePanelHotkey.itemClickMouse = '<2-LeftMouse>'
|
|
let VEConf.filePanelHotkey.refresh = 'r'
|
|
let VEConf.filePanelHotkey.toggleTreePanel = 't'
|
|
let VEConf.filePanelHotkey.toggleModes = 'i'
|
|
let VEConf.filePanelHotkey.newFile = '+f'
|
|
let VEConf.filePanelHotkey.newDirectory = '+d'
|
|
let VEConf.filePanelHotkey.switchPanel = '<c-tab>'
|
|
let VEConf.filePanelHotkey.quitVE = 'Q'
|
|
let VEConf.filePanelHotkey.toggleHidden = 'H'
|
|
let VEConf.filePanelHotkey.search = 'g/'
|
|
let VEConf.filePanelHotkey.markPlace = 'm'
|
|
let VEConf.filePanelHotkey.gotoPlace = "'"
|
|
let VEConf.filePanelHotkey.viewMarks = 'J'
|
|
let VEConf.filePanelHotkey.contextMenuN = '<rightmouse>'
|
|
"Browsing
|
|
let VEConf.filePanelHotkey.toUpperDir = '<bs>'
|
|
let VEConf.filePanelHotkey.gotoForward = '<c-i>'
|
|
let VEConf.filePanelHotkey.gotoBackward = '<c-o>'
|
|
let VEConf.filePanelHotkey.favorite = 'f'
|
|
let VEConf.filePanelHotkey.addToFavorite = 'F'
|
|
let VEConf.filePanelHotkey.browseHistory = 'b'
|
|
let VEConf.filePanelHotkey.gotoPath = '<c-g>'
|
|
"single file actions
|
|
let VEConf.filePanelHotkey.rename = 'R'
|
|
let VEConf.filePanelHotkey.yankSingle = 'yy'
|
|
let VEConf.filePanelHotkey.cutSingle = 'xx'
|
|
let VEConf.filePanelHotkey.showYankList = 'yl'
|
|
let VEConf.filePanelHotkey.deleteSingle = 'dd'
|
|
let VEConf.filePanelHotkey.deleteSingleF = 'DD'
|
|
let VEConf.filePanelHotkey.openPreview = 'u'
|
|
let VEConf.filePanelHotkey.closePreview = 'U'
|
|
"mark
|
|
let VEConf.filePanelHotkey.toggleSelectUp = '<s-space>'
|
|
let VEConf.filePanelHotkey.toggleSelectDown= '<space>'
|
|
let VEConf.filePanelHotkey.toggleSelMouse = '<c-LeftMouse>'
|
|
let VEConf.filePanelHotkey.markViaRegexp = 'Mr'
|
|
let VEConf.filePanelHotkey.markVimFiles = 'Mv'
|
|
let VEConf.filePanelHotkey.markDirectory = 'Md'
|
|
let VEConf.filePanelHotkey.markExecutable = 'Me'
|
|
let VEConf.filePanelHotkey.clearSelect = 'Mc'
|
|
"multiple file actions
|
|
let VEConf.filePanelHotkey.deleteSelected = 'sd'
|
|
let VEConf.filePanelHotkey.deleteSelectedF = 'sD'
|
|
let VEConf.filePanelHotkey.yankSelected = 'sy'
|
|
let VEConf.filePanelHotkey.cutSelected = 'sx'
|
|
let VEConf.filePanelHotkey.tabViewMulti = 'se'
|
|
let VEConf.filePanelHotkey.paste = 'p'
|
|
let VEConf.filePanelHotkey.diff2files = '='
|
|
"visual mode hotkeys.
|
|
let VEConf.filePanelHotkey.visualSelect = '<space>'
|
|
let VEConf.filePanelHotkey.visualDelete = 'd'
|
|
let VEConf.filePanelHotkey.visualDeleteF = 'D'
|
|
let VEConf.filePanelHotkey.visualYank = 'y'
|
|
let VEConf.filePanelHotkey.visualCut = 'x'
|
|
"User defined hotkeys, see below.
|
|
let VEConf.filePanelHotkey.tabView = 'e'
|
|
let VEConf.filePanelHotkey.openRenamer = ';r'
|
|
let VEConf.filePanelHotkey.startShell = ';c'
|
|
let VEConf.filePanelHotkey.startExplorer = ';e'
|
|
|
|
if exists("g:VEConf_fileHotkey")
|
|
if type(g:VEConf_fileHotkey) != type({})
|
|
echohl WarningMsg | echo "g:VEConf_fileHotkey is not dictionary type!" | echohl None
|
|
finish
|
|
endif
|
|
for i in keys(g:VEConf_fileHotkey)
|
|
let VEConf.filePanelHotkey[i] = g:VEConf_fileHotkey[i]
|
|
endfor
|
|
endif
|
|
|
|
"#######################################################################
|
|
"User defined file actions.
|
|
if !exists("g:VEConf_normalActions")
|
|
let VEConf_normalActions = {}
|
|
endif
|
|
if !exists("g:VEConf_normalHotKeys")
|
|
let VEConf_normalHotKeys = {}
|
|
endif
|
|
if !exists("g:VEConf_singleFileActions")
|
|
let VEConf_singleFileActions = {}
|
|
endif
|
|
if !exists("g:VEConf_singleFileHotKeys")
|
|
let VEConf_singleFileHotKeys = {}
|
|
endif
|
|
|
|
if !exists("g:VEConf_multiFileActions")
|
|
let VEConf_multiFileActions = {}
|
|
endif
|
|
if !exists("g:VEConf_multiFileHotKeys")
|
|
let VEConf_multiFileHotKeys = {}
|
|
endif
|
|
|
|
"Template
|
|
" let VEConf_singleFileHotKeys['actionName'] = '<hot_key>'
|
|
" function! VEConf_singleFileActions['actionName'](path)
|
|
" "do some jobs here.
|
|
" endfunction
|
|
"
|
|
"the 'path' is the file name under cursor in the file panel, you
|
|
"can use this path to do some actions.
|
|
"Pay attention to the hotKeys you have defined, dont conflict
|
|
"whth the default hotKey bindings.
|
|
"Normal Actions just run in current path, no path needed to
|
|
"pass.
|
|
|
|
"There are some examples:
|
|
"Open current file using vim in a new tab.
|
|
let VEConf_singleFileHotKeys['openInNewTab'] = VEConf.filePanelHotkey.tabView
|
|
function! VEConf_singleFileActions['openInNewTab'](path)
|
|
if !isdirectory(a:path)
|
|
exec "tabe " . g:VEPlatform.escape(a:path)
|
|
else
|
|
exec "VE " . g:VEPlatform.escape(a:path)
|
|
endif
|
|
endfunction
|
|
|
|
"Renamer is a very good plugin.
|
|
let VEConf_normalHotKeys['openRenamer'] = VEConf.filePanelHotkey.openRenamer
|
|
function! VEConf_normalActions['openRenamer']()
|
|
Renamer
|
|
endfunction
|
|
|
|
"start shell in current directory.
|
|
let VEConf_normalHotKeys['startShell'] = VEConf.filePanelHotkey.startShell
|
|
function! VEConf_normalActions['startShell']()
|
|
call g:VEPlatform.startShell()
|
|
endfunction
|
|
|
|
"start file explorer in current directory
|
|
"(nautilus,konquer,Explorer.exe and so on).
|
|
let VEConf_normalHotKeys['startExplorer'] = VEConf.filePanelHotkey.startExplorer
|
|
function! VEConf_normalActions['startExplorer']()
|
|
call g:VEPlatform.startExplorer()
|
|
endfunction
|
|
|
|
"Multiple file name are contained in the fileList.
|
|
let VEConf_multiFileHotKeys['openMultiFilesWithVim'] = VEConf.filePanelHotkey.tabViewMulti
|
|
function! VEConf_multiFileActions['openMultiFilesWithVim'](fileList)
|
|
if empty(a:fileList)
|
|
return
|
|
endif
|
|
for i in a:fileList
|
|
exec "tabe " . g:VEPlatform.escape(i)
|
|
endfor
|
|
endfunction
|
|
|
|
"#######################################################################
|
|
"Syntax and highlight configuration.
|
|
function! VEConf.treePanelSyntax()
|
|
syn clear
|
|
syn match Question "^.*Press ? for help.*$" "Host name
|
|
syn match WarningMsg "\[[A-Z]:[\\/]\]" "root node name
|
|
syn match Identifier "^\s*\zs[+-]" "+-
|
|
syn match SpecialKey "^.*\[current\]$" "current folder
|
|
endfunction
|
|
|
|
function! VEConf.filePanelSyntax()
|
|
syntax clear
|
|
syn match Type "\[ .* \]" "group
|
|
syn match Comment '\t.\{10}' "file size
|
|
syn match Comment '\d\{4}-\d\{2}-\d\{2}\ \d\{2}:\d\{2}:\d\{2}' "time
|
|
syn match Special '^Path: .*$' "path
|
|
syn match WarningMsg '^\~*$' "line
|
|
syn match Function '^.*[\\/]' "directory
|
|
syn match Search '^\*.*$' "selectedFiles
|
|
syn match LineNr '[rwx-]\{9}' "perm
|
|
endfunction
|
|
|
|
"#######################################################################
|
|
|
|
" classes relationship
|
|
"
|
|
" VEFrameWork
|
|
" VETreePanel
|
|
" VETree
|
|
" VENode
|
|
" VEFilePanel
|
|
" VEPlatform
|
|
|
|
" class VEPlatform {{{1
|
|
"=============================
|
|
let VEPlatform = {}
|
|
|
|
"it's a static class, no constructor
|
|
|
|
"has win
|
|
function! VEPlatform.haswin32()
|
|
if (has("win32") || has("win95") || has("win64") || has("win16") || has("dos32"))
|
|
return 1
|
|
else
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
"return a path always end with slash.
|
|
function! VEPlatform.getcwd()
|
|
let path = getcwd()
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if path[-1:] != "\\"
|
|
let path = path . "\\"
|
|
endif
|
|
else
|
|
if path[-1:] != "/"
|
|
let path = path . "/"
|
|
endif
|
|
endif
|
|
return path
|
|
endfunction
|
|
|
|
"get home path, end with a slash
|
|
function! VEPlatform.getHome()
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if $HOME[-1:] != "\\"
|
|
return $HOME . "\\"
|
|
else
|
|
return $HOME
|
|
endif
|
|
else
|
|
if $HOME[-1:] != "/"
|
|
return $HOME . "/"
|
|
else
|
|
return $HOME
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.escape(path)
|
|
if g:VEPlatform.haswin32()
|
|
return escape(a:path,'%#')
|
|
else
|
|
return escape(a:path,' %#')
|
|
endif
|
|
endfunction
|
|
|
|
"start a program and then return to vim, no wait.
|
|
function! VEPlatform.start(path)
|
|
let convPath = self.escape(a:path)
|
|
"escape() function will do iconv to the string, so call it
|
|
"before iconv().
|
|
if g:VEPlatform.haswin32()
|
|
let convPath = substitute(convPath,'/',"\\",'g')
|
|
let convPath = " start \"\" \"" . convPath . "\""
|
|
let ret = self.system(convPath)
|
|
else
|
|
if g:VEConf_usingKDE
|
|
let convPath = "kfmclient exec " . convPath
|
|
let ret = self.system(convPath)
|
|
elseif g:VEConf_usingGnome
|
|
let convPath = "gnome-open " . convPath
|
|
let ret = self.system(convPath)
|
|
else " default using gnome-open.
|
|
let convPath = "gnome-open " . convPath
|
|
let ret = self.system(convPath)
|
|
endif
|
|
endif
|
|
if !ret
|
|
echohl ErrorMsg | echomsg "Failed to start " . a:path | echohl None
|
|
return 0
|
|
endif
|
|
return 1
|
|
endfunction
|
|
|
|
function! VEPlatform.system(cmd)
|
|
"can not escape here! example: 'rm -r blabla\ bbb'
|
|
"let convCmd = escape(a:cmd,' %#')
|
|
let convCmd = a:cmd
|
|
if g:VEConf.systemEncoding != ''
|
|
let convCmd = iconv(convCmd,&encoding,g:VEConf.systemEncoding)
|
|
endif
|
|
call system(convCmd)
|
|
return !(v:shell_error)
|
|
endfunction
|
|
|
|
" Return successful copyed file list.
|
|
function! VEPlatform.copyMultiFile(fileList,topath)
|
|
let boverWrite = g:VEConf.overWriteExisting
|
|
let retList = []
|
|
for i in a:fileList
|
|
"boverWrite 0 ask, 1 allyes, 2 allno
|
|
if boverWrite == 0
|
|
if i[-1:] == "\\" || i[-1:] == "/"
|
|
let i = i[:-2]
|
|
endif
|
|
let tofile = a:topath . matchstr(i,'[\\/]\zs[^\\/]\+$')
|
|
if findfile(tofile) != ''
|
|
"echohl WarningMsg
|
|
"let result = tolower(input("File [ " . tofile . " ] exists! Over write ? (Y)es/(N)o/(A)llyes/A(L)lno/(C)ancel ","Y"))
|
|
let result = confirm("File [ " . matchstr(i,'[\\/]\zs[^\\/]\+$') .
|
|
\" ] exists! Over write ? ","&Yes\n&No\nYes to &All\nNo &To All\n&Cancel ",1)
|
|
"echohl None
|
|
if result == 1
|
|
if !self.copyfile(i,a:topath)
|
|
echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None
|
|
else
|
|
let retList += [i]
|
|
endif
|
|
elseif result == 2
|
|
continue
|
|
elseif result == 3
|
|
let boverWrite = 1
|
|
if !self.copyfile(i,a:topath)
|
|
echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None
|
|
else
|
|
let retList += [i]
|
|
endif
|
|
elseif result == 4
|
|
let boverWrite = 2
|
|
else
|
|
break
|
|
endif
|
|
else
|
|
if !self.copyfile(i,a:topath)
|
|
echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None
|
|
else
|
|
let retList += [i]
|
|
endif
|
|
endif
|
|
elseif boverWrite == 1
|
|
if !self.copyfile(i,a:topath)
|
|
echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None
|
|
else
|
|
let retList += [i]
|
|
endif
|
|
elseif boverWrite == 2
|
|
if i[-1:] == "\\" || i[-1:] == "/"
|
|
let i = i[:-2]
|
|
endif
|
|
let tofile = a:topath . matchstr(i,'[\\/]\zs[^\\/]\+$')
|
|
if findfile(tofile) != ''
|
|
continue
|
|
endif
|
|
if !self.copyfile(i,a:topath)
|
|
echohl ErrorMsg | echomsg "Copy file error: " . i | echohl None
|
|
else
|
|
let retList += [i]
|
|
endif
|
|
endif
|
|
endfor
|
|
echohl Special | echomsg " " . len(retList) . " file(s) pasted!" | echohl None
|
|
return retList
|
|
endfunction
|
|
|
|
function! VEPlatform.copyfile(filename,topath)
|
|
"return
|
|
let filename = self.escape(a:filename)
|
|
let topath = self.escape(a:topath)
|
|
if g:VEPlatform.haswin32()
|
|
let filename = substitute(a:filename,'/',"\\",'g')
|
|
let topath = substitute(a:topath,'/',"\\",'g')
|
|
if isdirectory(filename)
|
|
if filename[-1:] == "\\"
|
|
let filename = filename[:-2]
|
|
endif
|
|
let topath = "\"" . topath . matchstr(filename,'[^\\]*$') . "\""
|
|
let filename = "\"" . filename . "\""
|
|
let cmd = "xcopy ".filename . " " . topath . " /E /I /H /R /Y"
|
|
else
|
|
let topath = "\"" . topath . "\""
|
|
let filename = "\"" . filename . "\""
|
|
let cmd = "xcopy ". filename . " " . topath . " /I /H /R /Y"
|
|
endif
|
|
return self.system(cmd)
|
|
else
|
|
let cmd = "cp -r " . filename . " " . topath . "&"
|
|
return self.system(cmd)
|
|
endif
|
|
endfunction
|
|
|
|
" The "move" command in win32 is so poor..
|
|
" So I have no choice but copy then delete.
|
|
"function! VEPlatform.movefile(filename,topath)
|
|
" let filename = self.escape(a:filename)
|
|
" let topath = self.escape(a:topath)
|
|
" if executable("mv")
|
|
" let cmd = "mv -f " . filename . " " . topath
|
|
" return self.system(cmd)
|
|
" else
|
|
" if self.copyfile(a:filename,a:topath)
|
|
" return self.delete(a:filename,1)
|
|
" else
|
|
" return 0
|
|
" endif
|
|
" endif
|
|
"endfunction
|
|
|
|
function! VEPlatform.mkdir(path)
|
|
if g:VEConf.systemEncoding != ''
|
|
let convPath = iconv(a:path,&encoding,g:VEConf.systemEncoding)
|
|
else
|
|
let convPath = a:path
|
|
endif
|
|
return mkdir(convPath,'p')
|
|
endfunction
|
|
|
|
function! VEPlatform.mkfile(filename)
|
|
if findfile(a:filename) != '' || isdirectory(a:filename)
|
|
return 0
|
|
endif
|
|
if writefile([],a:filename) == 0 "here it is not need to convert filename
|
|
return 1
|
|
else
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.executable(filename)
|
|
if isdirectory(a:filename)
|
|
return 0
|
|
endif
|
|
if getfperm(a:filename)[2] == 'x'
|
|
return 1
|
|
else
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.search(filename,path)
|
|
if a:filename == '.' || a:filename == '..'
|
|
return []
|
|
else
|
|
return split(globpath(a:path,"**/" . a:filename),"\n")
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.globpath(path)
|
|
if g:VEConf.showHiddenFiles
|
|
let tmp = globpath(a:path,"*") . "\n" . globpath(a:path,".[^.]*") "need to cut . and ..
|
|
" can not show files start with .. such as ..foo , :(
|
|
" I do not know how to write the shell regexp.
|
|
if tmp == "\n"
|
|
return ''
|
|
else
|
|
return tmp
|
|
endif
|
|
else
|
|
return globpath(a:path,"*")
|
|
endif
|
|
endfunction
|
|
|
|
"globpath used in file panel, including filter.
|
|
function! VEPlatform.globpath_file(path)
|
|
if g:VEConf.filePanelFilter != ''
|
|
return globpath(a:path,g:VEConf.filePanelFilter)
|
|
endif
|
|
if g:VEConf.showHiddenFiles
|
|
let tmp = globpath(a:path,"*") . "\n" . globpath(a:path,".[^.]*") "need to cut . and ..
|
|
" can not show files start with .. such as ..foo , :(
|
|
" I do not know how to write the shell regexp.
|
|
if tmp == "\n"
|
|
return ''
|
|
else
|
|
return tmp
|
|
endif
|
|
else
|
|
return globpath(a:path,"*")
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.cdToPath(path)
|
|
try
|
|
"In win32, VE can create folder starts with space. So ...
|
|
exec "lcd " . escape(a:path,' %#')
|
|
catch
|
|
echohl ErrorMsg | echomsg "Can not cd to path: " . a:path | echohl None
|
|
endtry
|
|
endfunction
|
|
|
|
function! VEPlatform.startShell()
|
|
if g:VEPlatform.haswin32()
|
|
!start cmd.exe
|
|
else
|
|
shell
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.startExplorer()
|
|
let pwd = self.escape(g:VEPlatform.getcwd())
|
|
if g:VEPlatform.haswin32()
|
|
let pwd = substitute(pwd,'/',"\\",'g')
|
|
endif
|
|
if !self.system(g:VEConf.externalExplorer . " " . pwd)
|
|
"echohl ErrorMsg | echomsg "Failed to start external explorer: " . g:VEConf.externalExplorer | echohl None
|
|
" M$ windows Explorer.exe always return 1 even it starts successfully, shit!
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.getRoot(rootDict)
|
|
if g:VEPlatform.haswin32()
|
|
"Create new root list.
|
|
let newRootList = []
|
|
for i in g:VEConf.win32Disks
|
|
if &ssl
|
|
let i = i . "/"
|
|
else
|
|
let i = i . "\\"
|
|
endif
|
|
if g:VEPlatform.globpath(i) != ''
|
|
call add(newRootList,i)
|
|
endif
|
|
endfor
|
|
"Remove nolonger exist root nodes.
|
|
for i in keys(a:rootDict)
|
|
if index(newRootList,i) == -1
|
|
call remove(a:rootDict,i)
|
|
endif
|
|
endfor
|
|
"Create new root nodes.
|
|
for i in newRootList
|
|
if !has_key(a:rootDict,i)
|
|
let a:rootDict[i] = deepcopy(s:VENode)
|
|
call a:rootDict[i].init(i)
|
|
let a:rootDict[i].hasOwnChilds = 1
|
|
endif
|
|
endfor
|
|
else "Assert the other platform acts like UNIX
|
|
let newRootList = ["/"] " ~/
|
|
for i in newRootList
|
|
if !has_key(a:rootDict,i)
|
|
let a:rootDict[i] = deepcopy(s:VENode)
|
|
call a:rootDict[i].init(i)
|
|
let a:rootDict[i].hasOwnChilds = 1
|
|
endif
|
|
endfor
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.pathToName(path)
|
|
let time = strftime("%Y-%m-%d %H:%M:%S",getftime(a:path))
|
|
let size = getfsize(a:path)
|
|
let perm = getfperm(a:path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if a:path[-1:] != "\\"
|
|
let name = substitute(a:path,'^.*\\','','g')
|
|
else
|
|
let name = substitute(a:path,'^.*\\\ze.\+\\$','','g')
|
|
endif
|
|
else
|
|
if a:path[-1:] != "/"
|
|
let name = substitute(a:path,'^.*\/','','g')
|
|
else
|
|
let name = substitute(a:path,'^.*\/\ze.\+\/$','','g')
|
|
endif
|
|
endif
|
|
if g:VEConf.showFileSizeInMKB
|
|
if size > (1024 * 1024)
|
|
let size = (size / 1024 / 1024) . ' M'
|
|
elseif size > 1024
|
|
let size = (size / 1024) . ' K'
|
|
elseif size > 0
|
|
let size = size . ' B'
|
|
endif
|
|
endif
|
|
let tail = printf("%10.10s ".perm . ' ' .time,size==0?'':size)
|
|
return name . "\t" . tail
|
|
endfunction
|
|
|
|
function! VEPlatform.getUpperDir(path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
return substitute(a:path,'\\\zs[^\\]\+\\$','','g')
|
|
else
|
|
return substitute(a:path,'\/\zs[^/]\+\/$','','g')
|
|
endif
|
|
endfunction
|
|
|
|
"default choice and return value: 1:YES 0:NO
|
|
function! VEPlatform.confirm(text,defaultChoice)
|
|
if a:defaultChoice
|
|
let ret = confirm(a:text,"&Yes\n&No",1)
|
|
else
|
|
let ret = confirm(a:text,"&Yes\n&No",2)
|
|
endif
|
|
if ret == 1
|
|
return 1
|
|
else
|
|
return 0
|
|
endif
|
|
"if a:defaultChoice
|
|
" echohl WarningMsg
|
|
" let result = tolower(input(a:text . " ","Y"))
|
|
" echohl None
|
|
"else
|
|
" echohl WarningMsg
|
|
" let result = tolower(input(a:text . " "),"N")
|
|
" echohl None
|
|
"endif
|
|
"if result == "y" || result == "ye" || result == "yes"
|
|
" return 1
|
|
"else
|
|
" return 0
|
|
"endif
|
|
endfunction
|
|
|
|
"delete a single file or directory
|
|
"return 0:failed 1:success
|
|
function! VEPlatform.deleteSingle(path,bforce)
|
|
if !isdirectory(a:path)
|
|
if g:VEConf.fileDeleteConfirm && !self.confirm("Delete \n\"".a:path."\" ?",1)
|
|
echo " "
|
|
"clear the command line
|
|
return 0
|
|
endif
|
|
if self.delete(a:path,a:bforce)
|
|
echohl Special | echomsg "File: [" . a:path . "] deleted!" | echohl None
|
|
return 1
|
|
else
|
|
echohl ErrorMsg | echomsg "Can not delete the file! [" . a:path . "]" | echohl None
|
|
return 0
|
|
endif
|
|
else
|
|
if g:VEConf.fileDeleteConfirm && !self.confirm("Remove the folder \n\"".a:path."\" and all its contents?",1)
|
|
echo " "
|
|
return 0
|
|
endif
|
|
echo " "
|
|
return self.delete(a:path,a:bforce)
|
|
endif
|
|
endfunction
|
|
|
|
"delete multiple files/directory.
|
|
"return 0:failed 1:success
|
|
function! VEPlatform.deleteMultiple(fileList,bforce)
|
|
if g:VEConf.fileDeleteConfirm && !self.confirm("Delete selected file(s) ?",1)
|
|
echo " "
|
|
return 0
|
|
endif
|
|
for i in a:fileList
|
|
if !self.delete(i,a:bforce)
|
|
echohl ErrorMsg | echomsg "Failed to delete: " . i | echohl None
|
|
endif
|
|
endfor
|
|
return 1
|
|
endfunction
|
|
|
|
function! VEPlatform.delete(name,bforce)
|
|
if g:VEPlatform.haswin32()
|
|
let recPath = tolower(g:VEConf.recyclePath)
|
|
let delName = tolower(a:name)
|
|
else
|
|
let recPath = g:VEConf.recyclePath
|
|
let delName = a:name
|
|
endif
|
|
if !a:bforce && g:VEConf.recyclePath != '' && (stridx(delName,recPath) == -1)
|
|
if !isdirectory(g:VEConf.recyclePath)
|
|
if !self.mkdir(g:VEConf.recyclePath) || !isdirectory(g:VEConf.recyclePath)
|
|
echohl ErrorMsg | echomsg "Can not access recycle bin!" | echohl None
|
|
return 0
|
|
endif
|
|
endif
|
|
if !self.copyfile(a:name,g:VEConf.recyclePath)
|
|
echohl ErrorMsg | echomsg "Failed to move the file: [" . a:name . "] to recycle bin." | echohl None
|
|
return 0
|
|
"else
|
|
" return 1
|
|
endif
|
|
endif
|
|
if isdirectory(a:name)
|
|
if g:VEPlatform.haswin32()
|
|
return g:VEPlatform.system(" rmdir /S /Q \"" . self.escape(a:name) . "\"")
|
|
else
|
|
return g:VEPlatform.system("rm -r " . self.escape(a:name) . "&")
|
|
endif
|
|
else
|
|
if delete(a:name) == 0
|
|
return 1
|
|
else
|
|
return 0
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! VEPlatform.select(list,title)
|
|
let selectList = deepcopy(a:list)
|
|
if len(selectList) == 0
|
|
return
|
|
endif
|
|
call insert(selectList,a:title,0)
|
|
for i in range(1,len(selectList)-1)
|
|
let selectList[i] = i . " " . selectList[i]
|
|
endfor
|
|
let result = inputlist(selectList)
|
|
if result > len(a:list) || result <= 0
|
|
return -1
|
|
else
|
|
return result-1
|
|
endif
|
|
endfunction
|
|
|
|
" This is not a member of VEPlatform, because sort()
|
|
" can not use dict function.
|
|
function! VEPlatform_sortCompare(t1,t2)
|
|
if g:VEConf.sortCaseSensitive
|
|
return a:t1 ==# a:t2 ? 0 : a:t1 ># a:t2 ? 1 : -1
|
|
else
|
|
return a:t1 ==? a:t2 ? 0 : a:t1 >? a:t2 ? 1 : -1
|
|
endif
|
|
endfunction
|
|
|
|
|
|
" class VENode {{{1
|
|
"=============================
|
|
let s:VENode = {}
|
|
let s:VENode.name = ''
|
|
let s:VENode.path = ''
|
|
let s:VENode.isopen = 0
|
|
let s:VENode.hasOwnChilds = 0
|
|
let s:VENode.childs = {}
|
|
|
|
"Object Constructor
|
|
function! s:VENode.init(path)
|
|
let self.path = a:path
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let self.name = matchstr(a:path,'[^\\]*\\$','','g')
|
|
else
|
|
let self.name = matchstr(a:path,'[^/]*\/$','','g')
|
|
endif
|
|
endfunction
|
|
|
|
"Refresh tree node
|
|
function! s:VENode.updateNode()
|
|
"Once a node is updated, it means that the node has been opened.
|
|
let self.isopen = 1
|
|
"Create new dir list
|
|
let newDirList = []
|
|
for i in split(g:VEPlatform.globpath(self.path),"\n")
|
|
if isdirectory(i) == 1
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let i = matchstr(i,'[^\\]*$','','g') . "\\"
|
|
else
|
|
let i = matchstr(i,'[^/]*$','','g') . "/"
|
|
endif
|
|
call add(newDirList,i)
|
|
endif
|
|
endfor
|
|
"Remove nolonger exist dirs.
|
|
for i in keys(self.childs)
|
|
if index(newDirList,i) == -1
|
|
call remove(self.childs,i)
|
|
endif
|
|
endfor
|
|
"Create new nodes
|
|
for i in newDirList
|
|
if !has_key(self.childs,i)
|
|
let self.childs[i] = deepcopy(s:VENode)
|
|
call self.childs[i].init(self.path . i)
|
|
endif
|
|
endfor
|
|
"find out which child has their own childs
|
|
if !empty(self.childs)
|
|
let self.hasOwnChilds = 1
|
|
else
|
|
let self.hasOwnChilds = 0
|
|
return
|
|
endif
|
|
if g:VEConf.showFolderStatus == 0
|
|
for i in keys(self.childs)
|
|
let self.childs[i].hasOwnChilds = 1
|
|
endfor
|
|
else
|
|
for i in keys(self.childs)
|
|
let _hasOwnChilds = 0
|
|
for j in split(g:VEPlatform.globpath(self.childs[i].path),"\n")
|
|
if isdirectory(j) == 1
|
|
let _hasOwnChilds = 1
|
|
break
|
|
endif
|
|
endfor
|
|
if _hasOwnChilds == 1
|
|
let self.childs[i].hasOwnChilds = 1
|
|
endif
|
|
endfor
|
|
endif
|
|
"update opened child nodes
|
|
for i in keys(self.childs)
|
|
if self.childs[i].isopen == 1
|
|
call self.childs[i].updateNode()
|
|
endif
|
|
endfor
|
|
endfunction
|
|
|
|
"Toggle open/close status of one node
|
|
"the path should end with '\' such as c:\aaa\bbb\
|
|
"example "c:\\aaa\\bbb\\" "aaa\\bbb\\" "bbb\\"
|
|
function! s:VENode.toggle(path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let childPath = substitute(a:path,'^.\{-}\\','','g')
|
|
else
|
|
let childPath = substitute(a:path,'^.\{-}\/','','g')
|
|
endif
|
|
if childPath == ''
|
|
let self.isopen = !self.isopen
|
|
if self.isopen == 1
|
|
call self.updateNode()
|
|
endif
|
|
else
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let nodeName = matchstr(childPath,'^.\{-}\\')
|
|
else
|
|
let nodeName = matchstr(childPath,'^.\{-}\/')
|
|
endif
|
|
if !has_key(self.childs,nodeName)
|
|
echoerr "path error"
|
|
endif
|
|
let self.isopen = 1
|
|
call self.childs[nodeName].toggle(childPath)
|
|
endif
|
|
endfunction
|
|
|
|
"Open the giving path
|
|
"the path should end with '\' such as c:\aaa\bbb\
|
|
"example "c:\\aaa\\bbb\\" "aaa\\bbb\\" "bbb\\"
|
|
function! s:VENode.openPath(path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let childPath = substitute(a:path,'^.\{-}\\','','g')
|
|
else
|
|
let childPath = substitute(a:path,'^.\{-}\/','','g')
|
|
endif
|
|
if childPath == ''
|
|
if empty(self.childs)
|
|
call self.updateNode()
|
|
endif
|
|
return
|
|
else
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let nodeName = matchstr(childPath,'^.\{-}\\')
|
|
else
|
|
let nodeName = matchstr(childPath,'^.\{-}\/')
|
|
endif
|
|
if !has_key(self.childs,nodeName)
|
|
call self.updateNode()
|
|
endif
|
|
if !has_key(self.childs,nodeName) "refreshed and still can not find the path.
|
|
echoerr "Path error!"
|
|
return
|
|
else
|
|
let self.isopen = 1
|
|
call self.childs[nodeName].openPath(childPath)
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
|
|
"Draw the tree, depend on the status of every tree node.
|
|
function! s:VENode.draw(tree,depth)
|
|
if self.hasOwnChilds == 0
|
|
let name = repeat(' ',a:depth*2).' '.self.name
|
|
call add(a:tree,[name,self.path])
|
|
return
|
|
endif
|
|
if self.isopen
|
|
let name = repeat(' ',a:depth*2).'- '.self.name
|
|
if a:depth == 0 "let the root node looks different
|
|
let name = '- [' . self.name . ']'
|
|
endif
|
|
call add(a:tree,[name,self.path])
|
|
let keys = sort(keys(self.childs),"VEPlatform_sortCompare")
|
|
if !g:VEConf.treeSortDirection
|
|
call reverse(keys)
|
|
endif
|
|
for i in keys
|
|
call self.childs[i].draw(a:tree,a:depth+1)
|
|
endfor
|
|
else
|
|
let name = repeat(' ',a:depth*2).'+ '.self.name
|
|
if a:depth == 0 "let the root node looks different
|
|
let name = '+ [' . self.name . ']'
|
|
endif
|
|
call add(a:tree,[name,self.path])
|
|
endif
|
|
endfunction
|
|
|
|
" class VETree {{{1
|
|
"=============================
|
|
let s:VETree = {}
|
|
let s:VETree.content = []
|
|
let s:VETree.rootNodes = {}
|
|
|
|
"Object Constructor
|
|
function! s:VETree.init()
|
|
call g:VEPlatform.getRoot(self.rootNodes)
|
|
"for i in keys(self.rootNodes)
|
|
" call self.rootNodes[i].updateNode()
|
|
"endfor
|
|
endfunction
|
|
|
|
function! s:VETree.togglePath(path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let rootNodeName = matchstr(a:path,'^.\{-}\\')
|
|
else
|
|
let rootNodeName = matchstr(a:path,'^.\{-}\/')
|
|
endif
|
|
call self.rootNodes[rootNodeName].toggle(a:path)
|
|
endfunction
|
|
|
|
function! s:VETree.openPath(path)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let rootNodeName = matchstr(a:path,'^.\{-}\\')
|
|
else
|
|
let rootNodeName = matchstr(a:path,'^.\{-}\/')
|
|
endif
|
|
call self.rootNodes[rootNodeName].openPath(a:path)
|
|
endfunction
|
|
|
|
" fill self.content
|
|
function! s:VETree.draw()
|
|
let keys = sort(keys(self.rootNodes),"VEPlatform_sortCompare")
|
|
if g:VEConf.treeSortDirection == 0
|
|
call reverse(keys)
|
|
endif
|
|
for i in keys
|
|
call self.rootNodes[i].draw(self.content,0)
|
|
endfor
|
|
endfunction
|
|
|
|
function! s:VETree.update(path)
|
|
call g:VEPlatform.getRoot(self.rootNodes)
|
|
"toggle twice to update current directory
|
|
call self.togglePath(a:path)
|
|
call self.togglePath(a:path)
|
|
" costs too much time.
|
|
"for i in keys(self.rootNodes)
|
|
" call self.rootNodes[i].updateNode()
|
|
"endfor
|
|
endfunction
|
|
|
|
" class VETreePanel {{{1
|
|
"=============================
|
|
let s:VETreePanel = {}
|
|
let s:VETreePanel.tree = {}
|
|
let s:VETreePanel.name = ''
|
|
let s:VETreePanel.path = ''
|
|
let s:VETreePanel.width = 0
|
|
let s:VETreePanel.splitMode = ''
|
|
let s:VETreePanel.splitLocation = ''
|
|
|
|
"Object Constructor
|
|
function! s:VETreePanel.init(name,path)
|
|
let self.name = "VETreePanel" . a:name
|
|
let self.path = a:path
|
|
let self.width = g:VEConf.treePanelWidth
|
|
let self.splitMode = g:VEConf.treePanelSplitMode
|
|
let self.splitLocation = g:VEConf.treePanelSplitLocation
|
|
let self.tree = deepcopy(s:VETree)
|
|
call self.tree.init()
|
|
call self.tree.openPath(a:path)
|
|
endfunction
|
|
|
|
function! s:VETreePanel.setFocus()
|
|
let VETreeWinNr = bufwinnr(self.name)
|
|
if VETreeWinNr != -1
|
|
exec VETreeWinNr . " wincmd w"
|
|
return 1
|
|
else
|
|
let bufNr = bufnr(self.name)
|
|
if bufNr != -1
|
|
exec "bwipeout " . bufNr
|
|
endif
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
"Sync the tree with filesystem and refresh the tree panel
|
|
function! s:VETreePanel.refresh()
|
|
if !self.setFocus()
|
|
return
|
|
endif
|
|
call self.tree.update(self.path)
|
|
call self.drawTree()
|
|
endfunction
|
|
|
|
"Draw the dir tree but do not sync the tree with filesystem
|
|
function! s:VETreePanel.drawTree()
|
|
if !self.setFocus()
|
|
return
|
|
endif
|
|
if !empty(self.tree.content)
|
|
call remove(self.tree.content,0,-1)
|
|
endif
|
|
call add(self.tree.content,[hostname() . " (Press ? for help)",""])
|
|
call self.tree.draw()
|
|
let tree = []
|
|
let lineNr = line(".")
|
|
for i in self.tree.content
|
|
if i[1] == self.path
|
|
let i[0] = i[0] . " [current]"
|
|
let lineNr = index(self.tree.content,i) + 1
|
|
endif
|
|
call add(tree,i[0])
|
|
endfor
|
|
setlocal noreadonly
|
|
setlocal modifiable
|
|
"Let the cursor go back to right line and right position in
|
|
"the screen.
|
|
normal! H
|
|
let Hline = line(".")
|
|
silent normal! ggdG
|
|
call append(0,tree)
|
|
silent normal! Gddgg
|
|
exec "normal! " . Hline . "G"
|
|
normal! zt
|
|
exec "normal! " . lineNr . "G"
|
|
setlocal readonly
|
|
setlocal nomodifiable
|
|
endfunction
|
|
|
|
"Show tree panel
|
|
function! s:VETreePanel.show()
|
|
if self.setFocus()
|
|
return
|
|
endif
|
|
let cmd = self.splitLocation . " " . self.splitMode . ' ' . self.width . ' new ' . self.name
|
|
silent! execute cmd
|
|
let VETreeWinNr = bufwinnr(self.name)
|
|
if VETreeWinNr != -1
|
|
exec VETreeWinNr . " wincmd w"
|
|
setlocal winfixwidth
|
|
setlocal noswapfile
|
|
setlocal buftype=nowrite
|
|
setlocal bufhidden=delete
|
|
setlocal nowrap
|
|
setlocal foldcolumn=0
|
|
setlocal nobuflisted
|
|
setlocal nospell
|
|
setlocal nonumber
|
|
setlocal cursorline
|
|
setlocal readonly
|
|
setlocal nomodifiable
|
|
"call self.refresh()
|
|
call self.drawTree()
|
|
call self.createActions()
|
|
call self.createSyntax()
|
|
else
|
|
echoerr "create tree window failed!"
|
|
endif
|
|
endfunction
|
|
|
|
"Hide tree panel
|
|
function! s:VETreePanel.hide()
|
|
if !self.setFocus()
|
|
return
|
|
else
|
|
"make sure there are no more than 1 buffer has the same name
|
|
let bufNr = bufnr('%')
|
|
"exec "wincmd c"
|
|
quit
|
|
exec "bwipeout ".bufNr
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VETreePanel.getPathUnderCursor(num)
|
|
return self.tree.content[a:num][1]
|
|
endfunction
|
|
|
|
function! s:VETreePanel.nodeClicked(num)
|
|
if self.tree.content[a:num][1] == ""
|
|
return
|
|
endif
|
|
let path = self.tree.content[a:num][1]
|
|
if self.path != path
|
|
"let self.path = path
|
|
call VE_GotoPath(path)
|
|
"Do not toggle if it is the first time switch to another tree node.
|
|
call self.setFocus()
|
|
return
|
|
endif
|
|
call self.tree.togglePath(path)
|
|
call self.drawTree()
|
|
endfunction
|
|
|
|
function! s:VETreePanel.pathChanged(path)
|
|
if self.path == a:path
|
|
return
|
|
endif
|
|
call g:VEPlatform.cdToPath(a:path)
|
|
let self.path = g:VEPlatform.getcwd()
|
|
call self.tree.openPath(self.path)
|
|
call self.drawTree()
|
|
endfunction
|
|
|
|
function! s:VETreePanel.createActions()
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.help . " :tab h VimExplorer<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.toggleNode . " :call VE_OnTreeNodeClick()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.toggleNodeMouse. " :call VE_OnTreeNodeClick()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.refresh . " :call VE_TreeRefresh()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.toggleFilePanel ." :call VE_ToggleFilePanel()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.toUpperDir . " :call VE_ToUpperDir()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.switchPanel . " <c-w><c-w>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.favorite . " :call VE_GotoFavorite()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.addToFavorite . " :call VE_AddToFavorite('treePanel')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.browseHistory . " :call VE_BrowseHistory()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.gotoPath . " :call VE_OpenPath()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.treePanelHotkey.quitVE . " :call VEDestroy()<cr>"
|
|
" autocmd
|
|
au! * <buffer>
|
|
au BufEnter <buffer> call VE_SyncDir()
|
|
" Status line
|
|
setlocal statusline=%{getcwd()}
|
|
endfunction
|
|
|
|
function! s:VETreePanel.createSyntax()
|
|
if !self.setFocus()
|
|
return
|
|
endif
|
|
call g:VEConf.treePanelSyntax()
|
|
endfunction
|
|
|
|
|
|
" class VEFilePanel {{{1
|
|
"=============================
|
|
let s:VEFilePanel = {}
|
|
let s:VEFilePanel.fileList = []
|
|
let s:VEFilePanel.displayList = []
|
|
" displayList [
|
|
" [ "display name", "real path" ],
|
|
" ...
|
|
" ]
|
|
let s:VEFilePanel.selectedFiles = []
|
|
let s:VEFilePanel.leavePosition = {}
|
|
let s:VEFilePanel.name = ''
|
|
let s:VEFilePanel.path = ''
|
|
let s:VEFilePanel.width = 0
|
|
let s:VEFilePanel.splitMode = ""
|
|
let s:VEFilePanel.splitLocation = ""
|
|
|
|
function! s:VEFilePanel.init(name,path)
|
|
let self.name = "VEFilePanel".a:name
|
|
let self.path = a:path
|
|
let self.splitMode = g:VEConf.filePanelSplitMode
|
|
let self.splitLocation = g:VEConf.filePanelSplitLocation
|
|
let self.width = g:VEConf.filePanelWidth
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.show()
|
|
if self.setFocus()
|
|
return
|
|
endif
|
|
let cmd = self.splitLocation . " " . self.splitMode . ' ' . self.width . ' new ' . self.name
|
|
silent! exec cmd
|
|
if !self.setFocus()
|
|
echoerr "create file window failed!"
|
|
endif
|
|
setlocal winfixwidth
|
|
setlocal noswapfile
|
|
setlocal buftype=nowrite
|
|
setlocal bufhidden=delete
|
|
setlocal nowrap
|
|
setlocal foldcolumn=0
|
|
setlocal nobuflisted
|
|
setlocal nospell
|
|
setlocal nonumber
|
|
setlocal cursorline
|
|
setlocal readonly
|
|
setlocal nomodifiable
|
|
setlocal tabstop=40
|
|
"This is used to display file list more orderliness.
|
|
call self.refresh()
|
|
call self.createActions()
|
|
call self.createSyntax()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.only()
|
|
if !self.setFocus()
|
|
return
|
|
endif
|
|
only
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.hide()
|
|
if !self.setFocus()
|
|
return
|
|
else
|
|
let bufNr = bufnr('%')
|
|
exec "wincmd c"
|
|
exec "bwipeout ".bufNr
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.refresh()
|
|
call self.getFileListFromCwd()
|
|
call self.updateDisplayList()
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
"Draw the displayList on the screen.
|
|
function! s:VEFilePanel.drawList()
|
|
if !self.setFocus()
|
|
return
|
|
endif
|
|
"calculate window width
|
|
let VEFileWinNr = bufwinnr(self.name)
|
|
let winWidth = winwidth(VEFileWinNr)
|
|
exec "setlocal tabstop=" . ((winWidth-41)<20?20:(winWidth-41))
|
|
setlocal noreadonly
|
|
setlocal modifiable
|
|
let curLine = line(".")
|
|
normal! H
|
|
let Hline = line(".")
|
|
silent normal! ggdG
|
|
let displayContent = []
|
|
for i in self.displayList "here i is reference,not copy
|
|
if index(self.selectedFiles,i[1]) != -1
|
|
let tmpi = '*' . substitute(i[0],'^.','','g')
|
|
else
|
|
let tmpi = i[0]
|
|
endif
|
|
call add(displayContent,tmpi)
|
|
endfor
|
|
call append(0,displayContent)
|
|
normal! Gddgg
|
|
exec "normal! " . Hline . "G"
|
|
normal! zt
|
|
exec "normal! " . curLine . "G"
|
|
setlocal readonly
|
|
setlocal nomodifiable
|
|
endfunction
|
|
|
|
"Update the displayList.
|
|
function! s:VEFilePanel.updateDisplayList()
|
|
if g:VEConf.filePanelSortType == 1
|
|
call self.sortByName()
|
|
elseif g:VEConf.filePanelSortType == 2
|
|
call self.sortByTime()
|
|
else
|
|
call self.sortByType()
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.toggleModes()
|
|
if g:VEConf.filePanelSortType < 2
|
|
let g:VEConf.filePanelSortType = g:VEConf.filePanelSortType + 1
|
|
else
|
|
let g:VEConf.filePanelSortType = 0
|
|
endif
|
|
call self.updateDisplayList()
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.getFileListFromCwd()
|
|
let self.fileList = split(g:VEPlatform.globpath_file(self.path),"\n")
|
|
endfunction
|
|
|
|
" 1
|
|
function! s:VEFilePanel.sortByName()
|
|
let fileGroup = {}
|
|
" example
|
|
" {
|
|
" "name" : "path"
|
|
" }
|
|
for i in self.fileList
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let name = matchstr(i,'[^\\]*$','','g')
|
|
else
|
|
let name = matchstr(i,'[^/]*$','','g')
|
|
endif
|
|
if isdirectory(i)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if i[-1:] != "\\"
|
|
let i = i . "\\"
|
|
endif
|
|
else
|
|
if i[-1:] != "/"
|
|
let i = i . "/"
|
|
endif
|
|
endif
|
|
" add # before directory to sort separately.
|
|
let name = '#' . name
|
|
endif
|
|
let fileGroup[name] = i
|
|
endfor
|
|
let keys = sort(keys(fileGroup),"VEPlatform_sortCompare")
|
|
if !g:VEConf.fileGroupSortDirection
|
|
call reverse(keys)
|
|
endif
|
|
let self.displayList = []
|
|
call add(self.displayList,["Path: ".self.path,''])
|
|
call add(self.displayList,[repeat("~",100),''])
|
|
call add(self.displayList,['[ Sort by name ]',''])
|
|
for i in keys
|
|
call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]])
|
|
endfor
|
|
endfunction
|
|
|
|
" 2
|
|
function! s:VEFilePanel.sortByTime()
|
|
let fileGroup = {}
|
|
" example
|
|
" {
|
|
" "name" : "path"
|
|
" }
|
|
for i in self.fileList
|
|
let time = strftime("%Y-%m-%d %H:%M:%S",getftime(i))
|
|
let time = time . i "let the key of dict unique
|
|
if isdirectory(i)
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if i[-1:] != "\\"
|
|
let i = i . "\\"
|
|
endif
|
|
else
|
|
if i[-1:] != "/"
|
|
let i = i . "/"
|
|
endif
|
|
endif
|
|
endif
|
|
let fileGroup[time] = i
|
|
endfor
|
|
let keys = sort(keys(fileGroup),"VEPlatform_sortCompare")
|
|
if !g:VEConf.fileGroupSortDirection
|
|
call reverse(keys)
|
|
endif
|
|
let self.displayList = []
|
|
call add(self.displayList,["Path: ".self.path,''])
|
|
call add(self.displayList,[repeat("~",100),''])
|
|
call add(self.displayList,['[ Sort by time ]',''])
|
|
for i in keys
|
|
call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]])
|
|
endfor
|
|
endfunction
|
|
|
|
" 3 not implemented yet
|
|
"function! s:VEFilePanel.sortBySize()
|
|
" let fileGroup = {}
|
|
" " example
|
|
" " {
|
|
" " "name" : "path"
|
|
" " }
|
|
" for i in self.fileList
|
|
" let time = strftime("%Y-%m-%d %H:%M:%S",getftime(i))
|
|
" let time = time . i "let the key of dict unique
|
|
" if isdirectory(i)
|
|
" " add # before directory to sort separately.
|
|
" " need??
|
|
" "let time = '#' . time
|
|
" if i[-1:] != "\\"
|
|
" let i = i . "\\"
|
|
" endif
|
|
" endif
|
|
" let fileGroup[time] = i
|
|
" endfor
|
|
" let keys = sort(keys(fileGroup))
|
|
" if !g:VEConf.fileGroupSortDirection
|
|
" call reverse(keys)
|
|
" endif
|
|
" let self.displayList = []
|
|
" call add(self.displayList,["Path: ".self.path,''])
|
|
" call add(self.displayList,[repeat("~",100),''])
|
|
" call add(self.displayList,['[ Sort by time ]',''])
|
|
" for i in keys
|
|
" call add(self.displayList,[" " . g:VEPlatform.pathToName(fileGroup[i]),fileGroup[i]])
|
|
" endfor
|
|
"endfunction
|
|
|
|
" 0
|
|
function! s:VEFilePanel.sortByType()
|
|
let fileGroup = {}
|
|
" example
|
|
" {
|
|
" "directory" : [
|
|
" "c:\\aaa\\",
|
|
" "c:\\bbb\\"
|
|
" ]
|
|
" "txt" : [
|
|
" "c:\\mm.txt",
|
|
" "c:\\nn.txt"
|
|
" ]
|
|
" }
|
|
for i in self.fileList
|
|
" i ("c:\\ddd\\eee.fff")
|
|
if isdirectory(i)
|
|
"if the group dos not exist,create it first
|
|
if !has_key(fileGroup,'#Directory') "assert file name does not contain '#'
|
|
let fileGroup['#Directory'] = []
|
|
endif
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
if i[-1:] != "\\"
|
|
let i = i . "\\"
|
|
endif
|
|
else
|
|
if i[-1:] != "/"
|
|
let i = i . "/"
|
|
endif
|
|
endif
|
|
call add(fileGroup['#Directory'],i)
|
|
continue
|
|
endif
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let matchStr = '\\\.[^\\]\+$'
|
|
else
|
|
let matchStr = '\/\.[^/]\+$'
|
|
endif
|
|
if matchstr(i,matchStr) != ''
|
|
if !has_key(fileGroup,'#Hidden files')
|
|
let fileGroup['#Hidden files'] = []
|
|
endif
|
|
call add(fileGroup['#Hidden files'],i)
|
|
continue
|
|
endif
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let fileExtension = matchstr(substitute(i,'^.*\\','','g'),'\.[^.]\{-}$')
|
|
else
|
|
let fileExtension = matchstr(substitute(i,'^.*\/','','g'),'\.[^.]\{-}$')
|
|
endif
|
|
if fileExtension == '' "files have no extensions
|
|
if !has_key(fileGroup,'#Files')
|
|
let fileGroup['#Files'] = []
|
|
endif
|
|
call add(fileGroup['#Files'],i)
|
|
continue
|
|
else "group the file by it's ext.name
|
|
" # is always smaller than $
|
|
" so it can keep dir in the top
|
|
if !has_key(fileGroup,"$".fileExtension)
|
|
let fileGroup["$".fileExtension] = []
|
|
endif
|
|
call add(fileGroup["$".fileExtension],i)
|
|
endif
|
|
endfor
|
|
"update self.displayList
|
|
let self.displayList = []
|
|
call add(self.displayList,["Path: ".self.path,''])
|
|
call add(self.displayList,[repeat("~",100),''])
|
|
let keys = sort(keys(fileGroup),"VEPlatform_sortCompare")
|
|
if !g:VEConf.fileGroupSortDirection
|
|
call reverse(keys)
|
|
endif
|
|
for i in keys
|
|
call add(self.displayList,['[ '.i[1:].' ]',''])
|
|
call sort(fileGroup[i],"VEPlatform_sortCompare")
|
|
if !g:VEConf.fileGroupSortDirection
|
|
call reverse(fileGroup[i])
|
|
endif
|
|
for j in fileGroup[i]
|
|
call add(self.displayList,[" " . g:VEPlatform.pathToName(j),j])
|
|
endfor
|
|
call add(self.displayList,[" ",''])
|
|
endfor
|
|
if self.displayList[-1][0] == " "
|
|
call remove(self.displayList,-1) "remove last empty line
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.pathChanged(path)
|
|
call self.setFocus()
|
|
if self.path == a:path
|
|
return
|
|
endif
|
|
"store the current mouse position.
|
|
let linePos = line('.')
|
|
normal! H
|
|
let topPos = line('.')
|
|
let self.leavePosition[self.path] = [topPos,linePos]
|
|
"
|
|
call g:VEPlatform.cdToPath(a:path)
|
|
let self.selectedFiles = [] "clear the selectedFile list
|
|
let self.path = g:VEPlatform.getcwd()
|
|
call self.refresh()
|
|
"restore position
|
|
if has_key(self.leavePosition,self.path)
|
|
exec "normal! " . self.leavePosition[self.path][0] . "G"
|
|
normal! zt
|
|
exec "normal! " . self.leavePosition[self.path][1] . "G"
|
|
else
|
|
normal! ggM
|
|
if line('.') < 4 "put the cursor to first dir.
|
|
normal! 4G
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.setFocus()
|
|
let VEFileWinNr = bufwinnr(self.name)
|
|
if VEFileWinNr != -1
|
|
exec VEFileWinNr . " wincmd w"
|
|
return 1
|
|
else
|
|
"If the window of buffer was closed by hand and the
|
|
"buffer still in buffer list, wipeout it.
|
|
"In case of bufnr() returns empty when there are two
|
|
"buffers have the same name.
|
|
let bufNr = bufnr(self.name)
|
|
if bufNr != -1
|
|
exec "bwipeout " . bufNr
|
|
endif
|
|
return 0
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.itemClicked(line)
|
|
let path = self.displayList[a:line][1]
|
|
if path == ''
|
|
return
|
|
endif
|
|
if isdirectory(path)
|
|
call VE_GotoPath(path)
|
|
call self.setFocus()
|
|
return
|
|
else
|
|
call g:VEPlatform.start(path)
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.itemPreview(line)
|
|
let path = self.displayList[a:line][1]
|
|
if path == ''
|
|
return
|
|
endif
|
|
exec g:VEConf.previewSplitLocation . " pedit " . g:VEPlatform.escape(path)
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.singleFileAction(line,actionName)
|
|
let path = self.displayList[a:line][1]
|
|
if path == ''
|
|
return
|
|
endif
|
|
call g:VEConf_singleFileActions[a:actionName](path)
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.normalAction(actionName)
|
|
call g:VEConf_normalActions[a:actionName]()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.multiAction(actionName)
|
|
call g:VEConf_multiFileActions[a:actionName](self.selectedFiles)
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.deleteSingle(line,bForce)
|
|
let path = self.displayList[a:line][1]
|
|
if path == ''
|
|
return
|
|
endif
|
|
if g:VEPlatform.deleteSingle(path,a:bForce)
|
|
if index(self.selectedFiles,path) != -1
|
|
call remove(self.selectedFiles,index(self.selectedFiles,path))
|
|
endif
|
|
call self.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.deleteSelectedFiles(bForce)
|
|
if empty(self.selectedFiles)
|
|
return
|
|
endif
|
|
if g:VEPlatform.deleteMultiple(self.selectedFiles,a:bForce)
|
|
let self.selectedFiles = []
|
|
call self.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.toggleSelect(direction)
|
|
if a:direction == "up"
|
|
exec "norm " . "\<up>"
|
|
endif
|
|
let line = line(".") - 1
|
|
let path = self.displayList[line][1]
|
|
if path != ''
|
|
let idx = index(self.selectedFiles,path)
|
|
if idx == -1
|
|
call add(self.selectedFiles,path)
|
|
else
|
|
call remove(self.selectedFiles,idx)
|
|
endif
|
|
call self.drawList()
|
|
endif
|
|
if a:direction == "down"
|
|
exec "norm " . "\<down>"
|
|
endif
|
|
endfunction!
|
|
|
|
function! s:VEFilePanel.clearSelect()
|
|
let self.selectedFiles = []
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.visualSelect(firstLine,lastLine)
|
|
for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine))
|
|
let path = self.displayList[line][1]
|
|
if path == ''
|
|
continue
|
|
endif
|
|
let idx = index(self.selectedFiles,path)
|
|
if idx == -1
|
|
call add(self.selectedFiles,path)
|
|
else
|
|
call remove(self.selectedFiles,idx)
|
|
endif
|
|
endfor
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.visualDelete(firstLine,lastLine,bForce)
|
|
let displayList = []
|
|
for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine))
|
|
let path = self.displayList[line][1]
|
|
if path == ''
|
|
continue
|
|
endif
|
|
call add(displayList,path)
|
|
endfor
|
|
if empty(displayList)
|
|
return
|
|
endif
|
|
if g:VEPlatform.deleteMultiple(displayList,a:bForce)
|
|
call self.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.visualYank(firstLine,lastLine,mode)
|
|
let displayList = []
|
|
for line in range(a:firstLine,(a:lastLine>=len(self.displayList)?(len(self.displayList)-1):a:lastLine))
|
|
let path = self.displayList[line][1]
|
|
if path == ''
|
|
continue
|
|
endif
|
|
call add(displayList,path)
|
|
endfor
|
|
if empty(displayList)
|
|
return
|
|
endif
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
let s:VEContainer.yankMode = a:mode
|
|
let s:VEContainer.clipboard = displayList
|
|
call s:VEContainer.showClipboard()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.yankSingle(mode)
|
|
let line = line(".") - 1
|
|
let path = self.displayList[line][1]
|
|
if path != ''
|
|
let s:VEContainer.yankMode = a:mode
|
|
let s:VEContainer.clipboard = []
|
|
call add(s:VEContainer.clipboard,path)
|
|
endif
|
|
call s:VEContainer.showClipboard()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.paste()
|
|
if s:VEContainer.yankMode == '' || s:VEContainer.clipboard == []
|
|
return
|
|
endif
|
|
let retList = g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path)
|
|
if s:VEContainer.yankMode == 'cut' && len(retList) != 0
|
|
"let tmpRec = g:VEConf.recyclePath " save recycle path
|
|
"let g:VEConf.recyclePath = ''
|
|
for i in retList
|
|
call g:VEPlatform.delete(i,1) "force delete
|
|
endfor
|
|
"let g:VEConf.recyclePath = tmpRec
|
|
let s:VEContainer.yankMode = ''
|
|
let s:VEContainer.clipboard = []
|
|
endif
|
|
"if s:VEContainer.yankMode == 'cut'
|
|
" call g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path,1)
|
|
"else
|
|
" call g:VEPlatform.copyMultiFile(s:VEContainer.clipboard,self.path,0)
|
|
"endif
|
|
let s:VEContainer.yankMode = ''
|
|
let s:VEContainer.clipboard = []
|
|
call self.refresh()
|
|
"call s:VEContainer.showClipboard()
|
|
endfunction!
|
|
|
|
function! s:VEFilePanel.markViaRegexp(regexp)
|
|
if a:regexp == ''
|
|
echohl Special
|
|
let regexp = input("Mark files (regexp): ")
|
|
echohl None
|
|
else
|
|
let regexp = a:regexp
|
|
endif
|
|
let self.selectedFiles = []
|
|
for i in self.displayList
|
|
if g:VEPlatform.haswin32() && !&ssl
|
|
let name = matchstr(i[1],'[^\\]*.$','','g')
|
|
else
|
|
let name = matchstr(i[1],'[^/]*.$','','g')
|
|
endif
|
|
if matchstr(name,regexp) != ''
|
|
call add(self.selectedFiles,i[1])
|
|
endif
|
|
endfor
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.markExecutable()
|
|
let self.selectedFiles = []
|
|
for i in self.displayList
|
|
if g:VEPlatform.executable(i[1])
|
|
call add(self.selectedFiles,i[1])
|
|
endif
|
|
endfor
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.newFile()
|
|
echohl Special
|
|
let filename = input("Create file : ",self.path,"file")
|
|
echohl None
|
|
if filename == ''
|
|
echo " "
|
|
return
|
|
endif
|
|
if g:VEPlatform.mkfile(filename)
|
|
echohl Special | echomsg "OK" | echohl None
|
|
call self.refresh()
|
|
else
|
|
echohl ErrorMsg | echomsg "Can not create file!" | echohl None
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.newDirectory()
|
|
if !exists("*mkdir")
|
|
echoerr "mkdir feature not found!"
|
|
endif
|
|
echohl Special
|
|
let dirname = input("Create directory : ",self.path,"file")
|
|
echohl None
|
|
if dirname == ''
|
|
echo " "
|
|
return
|
|
endif
|
|
if findfile(dirname) == '' && g:VEPlatform.mkdir(dirname)
|
|
echohl Special | echomsg "OK" | echohl None
|
|
call self.refresh()
|
|
else
|
|
echohl ErrorMsg | echomsg "Can not create directory!" | echohl None
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.rename(line)
|
|
let path = self.displayList[a:line][1]
|
|
if path == ''
|
|
return
|
|
endif
|
|
echohl Special
|
|
let name = input("Rename to: ",path,"file")
|
|
echohl None
|
|
if name == ''
|
|
echo " "
|
|
return
|
|
endif
|
|
if findfile(name) != ''
|
|
echohl ErrorMsg | echomsg "File exists!" | echohl None
|
|
return
|
|
endif
|
|
if rename(path,name) == 0
|
|
echohl Special | echomsg "OK" | echohl None
|
|
call self.refresh()
|
|
else
|
|
echohl ErrorMsg | echomsg "Can not rename!" | echohl None
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.search()
|
|
echohl Special
|
|
let filename = input("Search : ")
|
|
echohl None
|
|
if filename == ''
|
|
echo " "
|
|
return
|
|
endif
|
|
echohl Special | echomsg "Searching [" . filename . "] in " . self.path . ", please wait...(Ctrl-C to break)" | echohl None
|
|
let self.fileList = g:VEPlatform.search(filename,self.path)
|
|
call self.updateDisplayList()
|
|
call self.drawList()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.statusFileName()
|
|
let line = line(".") - 1
|
|
let fname = self.displayList[line][1]
|
|
"let fname = substitute(fname,self.path,'','g')
|
|
let fname = fname[len(self.path):]
|
|
return fname
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.createActions()
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.help . " :tab h VimExplorer<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.switchPanel . " <c-w><c-w>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.itemClicked . " :call VE_OnFileItemClick()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.itemClickMouse. " :call VE_OnFileItemClick()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleTreePanel ." :call VE_ToggleTreePanel()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toUpperDir . " :call VE_ToUpperDir()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.gotoForward . " :call VE_GotoForward()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.gotoBackward . " :call VE_GotoBackward()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.openPreview . " :call VE_OnFileOpenPreview()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.closePreview . " :call VE_ClosePreviewPanel()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.deleteSingle . " :call VE_DeleteSingle(0)<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.deleteSingleF. " :call VE_DeleteSingle(1)<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.rename . " :call VE_Rename()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.refresh . " :call VE_RefreshFilePanel()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleSelectUp ." :call VE_ToggleSelectFile(\"up\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleSelectDown." :call VE_ToggleSelectFile(\"down\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.clearSelect . " :call VE_ClearSelectFile()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.deleteSelected . " :call VE_DeleteSelectedFiles(0)<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.deleteSelectedF. " :call VE_DeleteSelectedFiles(1)<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.yankSelected . " :call VE_YankSelectedFiles(\"copy\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.cutSelected . " :call VE_YankSelectedFiles(\"cut\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.yankSingle . " :call VE_YankSingle(\"copy\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.cutSingle . " :call VE_YankSingle(\"cut\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.showYankList . " :call VE_ShowYankList()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleModes . " :call VE_ToggleModes()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.paste . " :call VE_Paste()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markViaRegexp . " :call VE_MarkViaRegexp('')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markExecutable . " :call VE_MarkExecutable()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markVimFiles . " :call VE_MarkViaRegexp('.*.vim$')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markDirectory . " :call VE_MarkViaRegexp('.*[\\/]$')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.newFile . " :call VE_NewFile()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.newDirectory . " :call VE_NewDirectory()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markViaRegexp . " :call VE_MarkViaRegexp('')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.favorite . " :call VE_GotoFavorite()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.addToFavorite . " :call VE_AddToFavorite('filePanel')<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.browseHistory . " :call VE_BrowseHistory()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.gotoPath . " :call VE_OpenPath()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.diff2files . " :call VE_Diff()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.quitVE . " :call VEDestroy()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleHidden . " :call VE_ToggleHidden()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.search . " :call VE_FileSearch()<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.toggleSelMouse . " <leftmouse>:call VE_ToggleSelectFile(\"\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.contextMenuN . " <leftmouse>:popup ]FilePanelPopup<cr>"
|
|
|
|
let letter = char2nr('a')
|
|
while letter <= char2nr('z')
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.markPlace . nr2char(letter) .
|
|
\" :call VE_MarkPlace(\"" . nr2char(letter) . "\")<cr>"
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.gotoPlace . nr2char(letter) .
|
|
\" :call VE_MarkSwitchTo(\"" . nr2char(letter) . "\")<cr>"
|
|
let letter = letter + 1
|
|
endwhile
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.viewMarks . " :call VE_MarkList()<cr>"
|
|
|
|
" visual mode map
|
|
exec "vnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.visualSelect . " :call VE_VisualSelect()<cr>"
|
|
exec "vnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.visualDelete . " :call VE_VisualDelete(0)<cr>"
|
|
exec "vnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.visualDeleteF. " :call VE_VisualDelete(1)<cr>"
|
|
exec "vnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.visualYank . " :call VE_VisualYank(\"copy\")<cr>"
|
|
exec "vnoremap <silent> <buffer> " . g:VEConf.filePanelHotkey.visualCut . " :call VE_VisualYank(\"cut\")<cr>"
|
|
|
|
" User defined map
|
|
for i in keys(g:VEConf_normalHotKeys)
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf_normalHotKeys[i] .
|
|
\" :call VE_NormalAction(\"" . i . "\")<cr>"
|
|
endfor
|
|
for i in keys(g:VEConf_singleFileHotKeys)
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf_singleFileHotKeys[i] .
|
|
\" :call VE_SingleFileAction(\"" . i . "\")<cr>"
|
|
endfor
|
|
for i in keys(g:VEConf_multiFileHotKeys)
|
|
exec "nnoremap <silent> <buffer> " . g:VEConf_multiFileHotKeys[i] .
|
|
\" :call VE_MultiFileAction(\"" . i . "\")<cr>"
|
|
endfor
|
|
" Auto commands
|
|
au! * <buffer>
|
|
au BufEnter <buffer> call VE_SyncDir()
|
|
" Status line
|
|
setlocal statusline=%{VE_GetStatusFileName()}%=[%{getcwd()}]\ %{strftime(\"\%Y-\%m-\%d\ \%H:\%M\")}
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.createSyntax()
|
|
let VEFileWinNr = bufwinnr(self.name)
|
|
if VEFileWinNr != -1
|
|
exec VEFileWinNr . " wincmd w"
|
|
else
|
|
return
|
|
endif
|
|
call g:VEConf.filePanelSyntax()
|
|
endfunction
|
|
|
|
function! s:VEFilePanel.getPathUnderCursor(num)
|
|
return self.displayList[a:num][1]
|
|
endfunction
|
|
|
|
" class VEPreviewPanel {{{1
|
|
"=============================
|
|
"let s:VEPreviewPanel = {}
|
|
"let s:VEPreviewPanel.name = ''
|
|
"let s:VEPreviewPanel.width = 0
|
|
"let s:VEPreviewPanel.splitMode = ''
|
|
"let s:VEPreviewPanel.splitLocation = ''
|
|
"
|
|
"function! s:VEPreviewPanel.init(name)
|
|
" let self.name = "VEPreviewPanel" . a:name
|
|
" let self.width = g:VEConf.previewPanelWidth
|
|
" let self.splitMode = g:VEConf.previewPanelSplitMode
|
|
" let self.splitLocation = g:VEConf.previewPanelSplitLocation
|
|
"endfunction
|
|
|
|
"function! s:VEPreviewPanel.show()
|
|
" if self.setFocus()
|
|
" return
|
|
" endif
|
|
" let cmd = self.splitLocation . " " . self.splitMode . self.width . ' new '
|
|
" exec cmd
|
|
" if !self.setFocus()
|
|
" echoerr "create file window failed!"
|
|
" else
|
|
" edit self.name
|
|
" endif
|
|
"endfunction
|
|
|
|
"function! s:VEPreviewPanel.setFocus()
|
|
" let VEPreviewWinNr = bufwinnr(self.name)
|
|
" if VEPreviewWinNr != -1
|
|
" exec VEPreviewWinNr . " wincmd w"
|
|
" return 1
|
|
" else
|
|
" "If the window of buffer was closed by hand and the
|
|
" "buffer still in buffer list, wipeout it.
|
|
" "In case of bufnr() returns empty when there are two
|
|
" "buffers have the same name.
|
|
" let bufNr = bufnr(self.name)
|
|
" if bufNr != -1
|
|
" exec "bwipeout " . bufNr
|
|
" endif
|
|
" return 0
|
|
" endif
|
|
"endfunction
|
|
"
|
|
"function! s:VEPreviewPanel.hide()
|
|
" if !self.setFocus()
|
|
" return
|
|
" else
|
|
" let bufNr = bufnr('%')
|
|
"" exec "wincmd c"
|
|
" exec "bwipeout ".bufNr
|
|
" endif
|
|
"endfunction
|
|
"
|
|
"function! s:VEPreviewPanel.preview(path)
|
|
" if !self.setFocus()
|
|
" let self.name = a:path
|
|
" let cmd = self.splitLocation . " " . self.splitMode . self.width . ' new'
|
|
" exec cmd
|
|
" exec "edit " . self.name
|
|
" return
|
|
" else
|
|
" let self.name = a:path
|
|
" exec "edit " . self.name
|
|
" endif
|
|
"endfunction
|
|
|
|
|
|
|
|
" class VEFrameWork {{{1
|
|
"=============================
|
|
let s:VEFrameWork = {}
|
|
let s:VEFrameWork.name = ''
|
|
let s:VEFrameWork.treePanel = {}
|
|
let s:VEFrameWork.filePanel = {}
|
|
"let s:VEFrameWork.previewPanel = {}
|
|
let s:VEFrameWork.pathHistory = []
|
|
let s:VEFrameWork.pathPosition = -1
|
|
|
|
"Object Constructor
|
|
function! s:VEFrameWork.init(name,path)
|
|
let self.name = "VEFrameWork".a:name
|
|
let self.filePanel = deepcopy(s:VEFilePanel)
|
|
let self.treePanel = deepcopy(s:VETreePanel)
|
|
"let self.previewPanel = deepcopy(s:VEPreviewPanel)
|
|
call self.filePanel.init(a:name,a:path)
|
|
call self.treePanel.init(a:name,a:path)
|
|
"call self.previewPanel.init(a:name)
|
|
call add(self.pathHistory,a:path)
|
|
let self.pathPosition += 1
|
|
endfunction
|
|
|
|
function! s:VEFrameWork.show()
|
|
tabnew
|
|
call self.filePanel.show()
|
|
call self.filePanel.only() "so,here it means filePanel should be displayed first
|
|
call self.treePanel.show()
|
|
call self.filePanel.setFocus()
|
|
call self.filePanel.refresh()
|
|
normal! M
|
|
endfunction
|
|
|
|
"Switch to another path, it will change the forward/backward
|
|
"history.
|
|
function! s:VEFrameWork.gotoPath(path)
|
|
call self.treePanel.pathChanged(a:path)
|
|
call self.filePanel.pathChanged(a:path)
|
|
if len(self.pathHistory) > self.pathPosition+1
|
|
call remove(self.pathHistory,self.pathPosition+1,-1)
|
|
endif
|
|
call add(self.pathHistory,a:path)
|
|
if len(self.pathHistory) > g:VEConf.browseHistory
|
|
call remove(self.pathHistory,0)
|
|
else
|
|
let self.pathPosition += 1
|
|
endif
|
|
endfunction
|
|
|
|
"Forward and backward
|
|
function! s:VEFrameWork.gotoForward()
|
|
if self.pathPosition >= len(self.pathHistory) ||
|
|
\ self.pathPosition < 0 ||
|
|
\ empty(self.pathHistory)
|
|
return
|
|
endif
|
|
if self.pathPosition+1 == len(self.pathHistory) "Can not forward
|
|
return
|
|
endif
|
|
let self.pathPosition += 1
|
|
"Do not call VE_GotoPath here! It will change pathHistory.
|
|
"Call the follows instead.
|
|
call self.treePanel.pathChanged(self.pathHistory[self.pathPosition])
|
|
call self.filePanel.pathChanged(self.pathHistory[self.pathPosition])
|
|
endfunction
|
|
|
|
function! s:VEFrameWork.gotoBackward()
|
|
if self.pathPosition >= len(self.pathHistory) ||
|
|
\ self.pathPosition < 0 ||
|
|
\ empty(self.pathHistory)
|
|
return
|
|
endif
|
|
if self.pathPosition == 0 "Can not go back.
|
|
return
|
|
endif
|
|
let self.pathPosition -= 1
|
|
"Do not call VE_GotoPath here! It will change pathHistory.
|
|
"Call the follows instead.
|
|
call self.treePanel.pathChanged(self.pathHistory[self.pathPosition])
|
|
call self.filePanel.pathChanged(self.pathHistory[self.pathPosition])
|
|
endfunction
|
|
|
|
"Object destructor
|
|
function! s:VEFrameWork.destroy()
|
|
call self.filePanel.hide()
|
|
call self.treePanel.hide()
|
|
endfunction
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"####################################################
|
|
"global variables and functions {{{1
|
|
|
|
let s:VEContainer = {} "contains all VEFrameWorks
|
|
let s:VEContainer.clipboard = [] "shared clipboard
|
|
let s:VEContainer.yankMode = '' "cut or yank
|
|
let s:VEContainer.markPlaces = {}
|
|
|
|
function! s:VECreatePopMenu()
|
|
silent! unmenu ]FilePanelPopup
|
|
menu ]FilePanelPopup.&Open :call VE_OnFileItemClick()<cr>
|
|
menu ]FilePanelPopup.-sep0- :
|
|
menu ]FilePanelPopup.&Copy :call VE_YankSingle("copy")<cr>
|
|
menu ]FilePanelPopup.C&ut :call VE_YankSingle("cut")<cr>
|
|
menu ]FilePanelPopup.-sep1- :
|
|
menu ]FilePanelPopup.&Rename :call VE_Rename()<cr>
|
|
menu ]FilePanelPopup.&Delete :call VE_DeleteSingle(0)<cr>
|
|
menu ]FilePanelPopup.Pre&view :call VE_OnFileOpenPreview()<cr>
|
|
menu ]FilePanelPopup.&Mark :call VE_ToggleSelectFile("")<cr>
|
|
menu ]FilePanelPopup.-sep2- :
|
|
menu ]FilePanelPopup.&Paste :call VE_Paste()<cr>
|
|
menu ]FilePanelPopup.&New.&File :call VE_NewFile()<cr>
|
|
menu ]FilePanelPopup.&New.&Directory :call VE_NewDirectory()<cr>
|
|
menu ]FilePanelPopup.-sep3- :
|
|
menu ]FilePanelPopup.Re&fresh :call VE_RefreshFilePanel()<cr>
|
|
endfunction
|
|
|
|
function! VENew(path)
|
|
call s:VECreatePopMenu()
|
|
let frameName = '_' . substitute(reltimestr(reltime()),'\.','','g')
|
|
if a:path == ''
|
|
echohl Special
|
|
let workPath = input("VimExplorer (directory): ",g:VEPlatform.getcwd(),"file")
|
|
echohl None
|
|
if workPath == ''
|
|
return
|
|
endif
|
|
else
|
|
let workPath = a:path
|
|
endif
|
|
call g:VEPlatform.cdToPath(workPath)
|
|
let workPath = g:VEPlatform.getcwd() "Conversions capitalisations
|
|
"does not work here.
|
|
if !isdirectory(workPath)
|
|
echohl ErrorMsg | echomsg "Directory not exist!" | echohl None
|
|
return
|
|
endif
|
|
let s:VEContainer[frameName] = deepcopy(s:VEFrameWork)
|
|
call s:VEContainer[frameName].init(frameName,workPath)
|
|
call s:VEContainer[frameName].show()
|
|
let letter = char2nr('a')
|
|
while letter <= char2nr('z')
|
|
let s:VEContainer.markPlaces[nr2char(letter)] = ''
|
|
let letter = letter + 1
|
|
endwhile
|
|
endfunction
|
|
|
|
function! VEDestroy()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].destroy()
|
|
call remove(s:VEContainer,winName)
|
|
endif
|
|
endfunction
|
|
|
|
function! s:VEContainer.showClipboard()
|
|
echohl Special
|
|
let msg = len(self.clipboard) . " files in clipboard, Mode: " . self.yankMode . ", "
|
|
let msg = msg . '(press ' . g:VEConf.filePanelHotkey.showYankList . ' to show file list)'
|
|
echomsg msg
|
|
echohl None
|
|
endfunction
|
|
|
|
" Get path name under cursor
|
|
function! VE_getPathUnderCursor(where)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
let path = ''
|
|
if has_key(s:VEContainer,winName)
|
|
if a:where == 'treePanel'
|
|
let path = s:VEContainer[winName].treePanel.getPathUnderCursor(line(".")-1)
|
|
elseif a:where == 'filePanel'
|
|
let path = s:VEContainer[winName].filePanel.getPathUnderCursor(line(".")-1)
|
|
endif
|
|
endif
|
|
|
|
if !isdirectory(path)
|
|
return ''
|
|
else
|
|
return path
|
|
endif
|
|
endfunction
|
|
|
|
|
|
"Command handlers
|
|
"===================================
|
|
|
|
"TreePanel command handlers
|
|
"----------------------------
|
|
"Node click event
|
|
function! VE_OnTreeNodeClick()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].treePanel.nodeClicked(line(".")-1)
|
|
endif
|
|
endfunction
|
|
|
|
"Refresh tree command
|
|
function! VE_TreeRefresh()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].treePanel.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
"FilePanel command handlers
|
|
"----------------------------
|
|
"Item click event.
|
|
function! VE_OnFileItemClick()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.itemClicked(line(".")-1)
|
|
endif
|
|
endfunction
|
|
|
|
"Open preview.
|
|
function! VE_OnFileOpenPreview()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.itemPreview(line(".")-1)
|
|
endif
|
|
endfunction
|
|
|
|
"Refresh the panel.
|
|
function! VE_RefreshFilePanel()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
"User defined single file actions.
|
|
function! VE_SingleFileAction(actionName)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.singleFileAction((line(".")-1),a:actionName)
|
|
endif
|
|
endfunction
|
|
|
|
"User defined normal actions.
|
|
function! VE_NormalAction(actionName)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.normalAction(a:actionName)
|
|
endif
|
|
endfunction
|
|
|
|
"Multiple file actions.
|
|
function! VE_MultiFileAction(actionName)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.multiAction(a:actionName)
|
|
endif
|
|
endfunction
|
|
|
|
"Delete single file or directory.
|
|
function! VE_DeleteSingle(bForce)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.deleteSingle(line(".")-1,a:bForce)
|
|
endif
|
|
endfunction
|
|
|
|
"Rename file or dir
|
|
function! VE_Rename()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.rename(line(".")-1)
|
|
endif
|
|
endfunction
|
|
|
|
"Toggle select a file in file panel.
|
|
function! VE_ToggleSelectFile(direction)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.toggleSelect(a:direction)
|
|
endif
|
|
endfunction
|
|
|
|
"Clear selection.
|
|
function! VE_ClearSelectFile()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.clearSelect()
|
|
endif
|
|
endfunction
|
|
|
|
"Toggle sort mode
|
|
function! VE_ToggleModes()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.toggleModes()
|
|
endif
|
|
endfunction
|
|
|
|
"Mark via regexp
|
|
function! VE_MarkViaRegexp(regexp)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.markViaRegexp(a:regexp)
|
|
endif
|
|
endfunction
|
|
|
|
"Mark executable files.
|
|
function! VE_MarkExecutable()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.markExecutable()
|
|
endif
|
|
endfunction
|
|
|
|
"create file
|
|
function! VE_NewFile()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.newFile()
|
|
endif
|
|
endfunction
|
|
|
|
"create directory
|
|
function! VE_NewDirectory()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.newDirectory()
|
|
endif
|
|
endfunction
|
|
|
|
"delete selected files.
|
|
function! VE_DeleteSelectedFiles(bForce)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.deleteSelectedFiles(a:bForce)
|
|
endif
|
|
endfunction
|
|
|
|
"delete selected files.
|
|
function! VE_YankSelectedFiles(mode)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let s:VEContainer.clipboard = s:VEContainer[winName].filePanel.selectedFiles
|
|
let s:VEContainer.yankMode = a:mode
|
|
endif
|
|
call s:VEContainer.showClipboard()
|
|
endfunction
|
|
|
|
function! VE_YankSingle(mode)
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.yankSingle(a:mode)
|
|
endif
|
|
endfunction
|
|
|
|
function! VE_Paste()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.paste()
|
|
endif
|
|
endfunction
|
|
|
|
function! VE_FileSearch()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.search()
|
|
endif
|
|
endfunction
|
|
|
|
|
|
"visual mode functions.
|
|
"visual select
|
|
function! VE_VisualSelect() range
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.visualSelect(a:firstline-1,a:lastline-1)
|
|
endif
|
|
endfunction
|
|
|
|
"visual delete
|
|
function! VE_VisualDelete(bForce) range
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.visualDelete(a:firstline-1,a:lastline-1,a:bForce)
|
|
endif
|
|
endfunction
|
|
|
|
"visual yank
|
|
function! VE_VisualYank(mode) range
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].filePanel.visualYank(a:firstline-1,a:lastline-1,a:mode)
|
|
endif
|
|
endfunction
|
|
|
|
function! VE_ShowYankList()
|
|
if s:VEContainer.clipboard == []
|
|
return
|
|
endif
|
|
for i in s:VEContainer.clipboard
|
|
echo i
|
|
endfor
|
|
endfunction
|
|
|
|
"Common command handlers
|
|
"--------------------------
|
|
"get file name for status line.
|
|
function! VE_GetStatusFileName()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
return s:VEContainer[winName].filePanel.statusFileName()
|
|
else
|
|
return ''
|
|
endif
|
|
endfunction
|
|
|
|
"mark palce
|
|
function! VE_MarkPlace(char)
|
|
let s:VEContainer.markPlaces[a:char] = g:VEPlatform.getcwd()
|
|
endfunction
|
|
|
|
"goto marked place
|
|
function! VE_MarkSwitchTo(char)
|
|
call VE_GotoPath(s:VEContainer.markPlaces[a:char])
|
|
endfunction
|
|
|
|
function! VE_MarkList()
|
|
let list = []
|
|
let letter = char2nr('a')
|
|
while letter <= char2nr('z')
|
|
if s:VEContainer.markPlaces[nr2char(letter)] != ''
|
|
echo nr2char(letter) . " " . s:VEContainer.markPlaces[nr2char(letter)]
|
|
endif
|
|
let letter = letter + 1
|
|
endwhile
|
|
endfunction
|
|
|
|
"Toggle tree panel.
|
|
function! VE_ToggleTreePanel()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
if s:VEContainer[winName].treePanel.setFocus()
|
|
call s:VEContainer[winName].treePanel.hide()
|
|
else
|
|
call s:VEContainer[winName].treePanel.show()
|
|
endif
|
|
endif
|
|
exec "wincmd p"
|
|
endfunction
|
|
|
|
"Toggle file panel.
|
|
function! VE_ToggleFilePanel()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
if s:VEContainer[winName].filePanel.setFocus()
|
|
call s:VEContainer[winName].filePanel.hide()
|
|
else
|
|
call s:VEContainer[winName].filePanel.show()
|
|
endif
|
|
endif
|
|
call s:VEContainer[winName].treePanel.setFocus()
|
|
exec g:VEConf.treePanelWidth . " wincmd |"
|
|
endfunction
|
|
|
|
function! VE_ClosePreviewPanel()
|
|
pclose
|
|
endfunction
|
|
|
|
|
|
"Go to upper directory.
|
|
function! VE_ToUpperDir()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let path = s:VEContainer[winName].filePanel.path
|
|
" Assert filePanel.path == treePanel.path
|
|
let upperPath = g:VEPlatform.getUpperDir(path)
|
|
if upperPath == path
|
|
return
|
|
endif
|
|
call VE_GotoPath(upperPath)
|
|
let dir = split(path,'/')
|
|
call search(" " . dir[-1] . "/\t")
|
|
endif
|
|
exec winNr . "wincmd w"
|
|
endfunction
|
|
|
|
"Path change event
|
|
function! VE_GotoPath(path)
|
|
if !isdirectory(a:path)
|
|
return
|
|
endif
|
|
call g:VEPlatform.cdToPath(a:path)
|
|
let path = g:VEPlatform.getcwd()
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].gotoPath(path)
|
|
endif
|
|
endfunction
|
|
|
|
"Used in <c-g>
|
|
function! VE_OpenPath()
|
|
echohl Special
|
|
let workPath = input("Change path to (directory): ",'',"file")
|
|
echohl None
|
|
if workPath == ''
|
|
return
|
|
endif
|
|
call g:VEPlatform.cdToPath(workPath)
|
|
let workPath = g:VEPlatform.getcwd()
|
|
call VE_GotoPath(workPath)
|
|
endfunction
|
|
|
|
"Goto forward
|
|
function! VE_GotoForward()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].gotoForward()
|
|
endif
|
|
exec winNr . "wincmd w"
|
|
endfunction
|
|
|
|
"Goto backward
|
|
function! VE_GotoBackward()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
call s:VEContainer[winName].gotoBackward()
|
|
endif
|
|
exec winNr . "wincmd w"
|
|
endfunction
|
|
|
|
"Favorite
|
|
function! VE_GotoFavorite()
|
|
let fav_filename = g:VEPlatform.getHome() . g:VEConf.favorite
|
|
if findfile(fav_filename)=='' || !filereadable(fav_filename)
|
|
return
|
|
endif
|
|
let fav = readfile(fav_filename)
|
|
let result = g:VEPlatform.select(fav,"Favorite folder list:")
|
|
if result == -1
|
|
return
|
|
endif
|
|
call VE_GotoPath(fav[result])
|
|
endfunction
|
|
|
|
function! VE_AddToFavorite(where)
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let cwd = s:VEContainer[winName].filePanel.path
|
|
else
|
|
return
|
|
endif
|
|
let pathUnderCursor = VE_getPathUnderCursor(a:where)
|
|
if pathUnderCursor != ''
|
|
" if no path name under cursor, use current working path
|
|
let cwd = pathUnderCursor
|
|
endif
|
|
let fav_filename = g:VEPlatform.getHome() . g:VEConf.favorite
|
|
let fav = []
|
|
if findfile(fav_filename) != ''
|
|
if !filereadable(fav_filename)
|
|
echoerr "Can not read favorite folder list!"
|
|
return
|
|
endif
|
|
if !filewritable(fav_filename)
|
|
echoerr "Can not write favorite folder list to file!"
|
|
return
|
|
endif
|
|
let fav = readfile(fav_filename)
|
|
endif
|
|
if index(fav,cwd) != -1
|
|
"echohl WarningMsg | echomsg "Current directory already in the favorite list." | echohl None
|
|
echohl WarningMsg | echomsg "[ ".cwd." ] already in the favorite!" | echohl None
|
|
return
|
|
endif
|
|
call add(fav,cwd)
|
|
if writefile(fav,fav_filename) == 0
|
|
echohl Special | echomsg "[ ".cwd." ] added to favorite." | echohl None
|
|
else
|
|
echoerr "Can not write favorite folder list to file!"
|
|
endif
|
|
endfunction
|
|
|
|
"forward and backward history
|
|
function! VE_BrowseHistory()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let pathlist = s:VEContainer[winName].pathHistory
|
|
let result = g:VEPlatform.select(pathlist,"Browse history:")
|
|
if result == -1
|
|
return
|
|
else
|
|
call s:VEContainer[winName].treePanel.pathChanged(pathlist[result])
|
|
call s:VEContainer[winName].filePanel.pathChanged(pathlist[result])
|
|
let s:VEContainer[winName].pathPosition = result
|
|
endif
|
|
endif
|
|
endfunction
|
|
|
|
"sync directory
|
|
function! VE_SyncDir()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let path = s:VEContainer[winName].filePanel.path
|
|
call g:VEPlatform.cdToPath(path)
|
|
endif
|
|
endfunction
|
|
|
|
"diff 2 files
|
|
function! VE_Diff()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let diffFiles = s:VEContainer[winName].filePanel.selectedFiles
|
|
if len(diffFiles) != 2 || isdirectory(diffFiles[0]) || isdirectory(diffFiles[1])
|
|
echohl WarningMsg | echo "Please select 2 files to diff!" | echohl None
|
|
return
|
|
endif
|
|
exec "tabe " . g:VEPlatform.escape(diffFiles[0])
|
|
exec "vertical diffsplit " . g:VEPlatform.escape(diffFiles[1])
|
|
endif
|
|
endfunction
|
|
|
|
"toggle show hidden files
|
|
function! VE_ToggleHidden()
|
|
let winNr = bufwinnr('%')
|
|
let winName = matchstr(bufname("%"),'_[^_]*$')
|
|
if has_key(s:VEContainer,winName)
|
|
let g:VEConf.showHiddenFiles = !g:VEConf.showHiddenFiles
|
|
call s:VEContainer[winName].treePanel.refresh()
|
|
call s:VEContainer[winName].filePanel.refresh()
|
|
endif
|
|
endfunction
|
|
|
|
command! -nargs=? -complete=file VE call VENew('<args>')
|
|
command! -nargs=0 -complete=file VEC call VEDestroy()
|
|
|
|
|
|
"====================================================================
|
|
"
|
|
" Function: s:InstallDocumentation(full_name, revision)
|
|
" Install help documentation.
|
|
" Arguments:
|
|
" full_name: Full name of this vim plugin script, including path name.
|
|
" revision: Revision of the vim script. #version# mark in the document file
|
|
" will be replaced with this string with 'v' prefix.
|
|
" Return:
|
|
" 1 if new document installed, 0 otherwise.
|
|
" Note: Cleaned and generalized by guo-peng Wen.
|
|
"
|
|
" Note about authorship: this function was taken from the vimspell plugin
|
|
" which can be found at http://www.vim.org/scripts/script.php?script_id=465
|
|
"
|
|
function! s:InstallDocumentation(full_name, revision)
|
|
" Name of the document path based on the system we use:
|
|
if has("vms")
|
|
" No chance that this script will work with
|
|
" VMS - to much pathname juggling here.
|
|
return 1
|
|
elseif (has("unix"))
|
|
" On UNIX like system, using forward slash:
|
|
let l:slash_char = '/'
|
|
let l:mkdir_cmd = ':silent !mkdir -p '
|
|
else
|
|
" On M$ system, use backslash. Also mkdir syntax is different.
|
|
" This should only work on W2K and up.
|
|
let l:slash_char = '\'
|
|
let l:mkdir_cmd = ':silent !mkdir '
|
|
endif
|
|
|
|
let l:doc_path = l:slash_char . 'doc'
|
|
let l:doc_home = l:slash_char . '.vim' . l:slash_char . 'doc'
|
|
|
|
" Figure out document path based on full name of this script:
|
|
let l:vim_plugin_path = fnamemodify(a:full_name, ':h')
|
|
let l:vim_doc_path = fnamemodify(a:full_name, ':h:h') . l:doc_path
|
|
if (!(filewritable(l:vim_doc_path) == 2))
|
|
"Doc path: " . l:vim_doc_path
|
|
echo "Doc path: " . l:vim_doc_path
|
|
execute l:mkdir_cmd . '"' . l:vim_doc_path . '"'
|
|
if (!(filewritable(l:vim_doc_path) == 2))
|
|
" Try a default configuration in user home:
|
|
let l:vim_doc_path = expand("~") . l:doc_home
|
|
if (!(filewritable(l:vim_doc_path) == 2))
|
|
execute l:mkdir_cmd . '"' . l:vim_doc_path . '"'
|
|
if (!(filewritable(l:vim_doc_path) == 2))
|
|
" Put a warning:
|
|
echo "Unable to open documentation directory"
|
|
echo "type :help add-local-help for more information."
|
|
echo l:vim_doc_path
|
|
return 0
|
|
endif
|
|
endif
|
|
endif
|
|
endif
|
|
|
|
" Exit if we have problem to access the document directory:
|
|
if (!isdirectory(l:vim_plugin_path) || !isdirectory(l:vim_doc_path) || filewritable(l:vim_doc_path) != 2)
|
|
return 0
|
|
endif
|
|
|
|
" Full name of script and documentation file:
|
|
let l:script_name = fnamemodify(a:full_name, ':t')
|
|
let l:doc_name = fnamemodify(a:full_name, ':t:r') . '.txt'
|
|
let l:plugin_file = l:vim_plugin_path . l:slash_char . l:script_name
|
|
let l:doc_file = l:vim_doc_path . l:slash_char . l:doc_name
|
|
|
|
" Bail out if document file is still up to date:
|
|
if (filereadable(l:doc_file) && getftime(l:plugin_file) < getftime(l:doc_file))
|
|
return 0
|
|
endif
|
|
|
|
" Prepare window position restoring command:
|
|
if (strlen(@%))
|
|
let l:go_back = 'b ' . bufnr("%")
|
|
else
|
|
let l:go_back = 'enew!'
|
|
endif
|
|
|
|
" Create a new buffer & read in the plugin file (me):
|
|
setl nomodeline
|
|
exe 'enew!'
|
|
exe 'r ' . l:plugin_file
|
|
|
|
setl modeline
|
|
let l:buf = bufnr("%")
|
|
setl noswapfile modifiable
|
|
|
|
norm zR
|
|
norm gg
|
|
|
|
" Delete from first line to a line starts with
|
|
" === START_DOC
|
|
1,/^=\{3,}\s\+START_DOC\C/ d
|
|
|
|
" Delete from a line starts with
|
|
" === END_DOC
|
|
" to the end of the documents:
|
|
/^=\{3,}\s\+END_DOC\C/,$ d
|
|
|
|
" Add modeline for help doc: the modeline string is mangled intentionally
|
|
" to avoid it be recognized by VIM:
|
|
call append(line('$'), '')
|
|
call append(line('$'), ' v' . 'im:tw=78:ts=8:ft=help:norl:')
|
|
|
|
" Replace revision:
|
|
"exe "normal :1s/#version#/ v" . a:revision . "/\<CR>"
|
|
exe "normal :%s/#version#/ v" . a:revision . "/\<CR>"
|
|
|
|
" Save the help document:
|
|
exe 'w! ' . l:doc_file
|
|
exe l:go_back
|
|
exe 'bw ' . l:buf
|
|
|
|
" Build help tags:
|
|
exe 'helptags ' . l:vim_doc_path
|
|
|
|
return 1
|
|
endfunction
|
|
|
|
" Doc installation call {{{1
|
|
silent call s:InstallDocumentation(expand('<sfile>:p'),"0.99")
|
|
"============================================================
|
|
finish
|
|
|
|
"Manual {{{1
|
|
=== START_DOC
|
|
*VimExplorer* A powerful file manager #version#
|
|
|
|
|
|
VimExplorer Reference Manual
|
|
by Ming Bai (mbbill AT gmail.com)
|
|
|
|
|
|
==============================================================================
|
|
CONTENTS *VimExplorer-contents*
|
|
|
|
1. Intro.......................................|VimExplorer-start|
|
|
2. Functionality...............................|VimExplorer-functionality|
|
|
2.1 Tree Panel Hotkeys.....................|VimExplorer-treehotkey|
|
|
2.2 File Panel Hotkeys.....................|VimExplorer-filehotkey|
|
|
2.3 Commands...............................|VimExplorer-commands|
|
|
3. Directory Browsing..........................|VimExplorer-browse|
|
|
3.1 Tree Browsing..........................|VimExplorer-treebrowse|
|
|
3.2 File Browsing..........................|VimExplorer-filebrowse|
|
|
3.3 Forward and Backward...................|VimExplorer-forbackward|
|
|
3.4 Favorites..............................|VimExplorer-favorite|
|
|
3.5 Temp Marks.............................|VimExplorer-tempmark|
|
|
4. Marks.......................................|VimExplorer-mark|
|
|
4.1 Single File Marks......................|VimExplorer-marksingle|
|
|
4.2 Visual Marks...........................|VimExplorer-markvisual|
|
|
4.3 Regexp Marks...........................|VimExplorer-markregexp|
|
|
5. File operations.............................|VimExplorer-fileoperation|
|
|
5.1 Create.................................|VimExplorer-new|
|
|
5.2 Move...................................|VimExplorer-move|
|
|
5.3 Delete.................................|VimExplorer-delete|
|
|
5.4 Diff...................................|VimExplorer-diff|
|
|
5.5 Search.................................|VimExplorer-search|
|
|
5.6 Other Operations.......................|VimExplorer-otherfileopt|
|
|
6. Other Functionalities.......................|VimExplorer-otherfuncs|
|
|
7. Customization...............................|VimExplorer-customize|
|
|
7.1 Normal Options.........................|VimExplorer-custnormal|
|
|
7.2 Hotkey Customization...................|VimExplorer-custhotkey|
|
|
7.3 Command Customization..................|VimExplorer-custcommand|
|
|
8. The Author..................................|VimExplorer-author|
|
|
9. Problems and Fixes..........................|VimExplorer-problems|
|
|
10. Changelog...................................|VimExplorer-changelog|
|
|
11. TODO........................................|VimExplorer-todo|
|
|
|
|
|
|
==============================================================================
|
|
1. Intro *VimExplorer-start*
|
|
|
|
What is VimExplorer ?
|
|
VimExplorer is a file manager, it can do a lot of file operations such as
|
|
copy, delete, move, preview, search and so on. Also it has a variety of other
|
|
capacities and customization abilities.
|
|
|
|
You can start VimExplorer by the following command:
|
|
>
|
|
:VE
|
|
<
|
|
Then it will ask you for the starting directory, default is the current path.
|
|
>
|
|
VimExplorer (directory): /home/username/
|
|
<
|
|
You can change it to some other directories or just push "Enter" to start it.
|
|
|
|
The second approach to start VimExplorer:
|
|
>
|
|
:VE [directory]
|
|
<
|
|
Example:
|
|
>
|
|
:VE /usr/src/
|
|
<
|
|
Now, VimExplorer will start using the path '/usr/src/'. When you are typing
|
|
the path, <tab> and <ctrl-d> will help you to complete the path automatically.
|
|
After all of these operations, you can see a new tab which has two panels
|
|
within it, one is the "Tree Panel" and the other is "File Panel". From now you
|
|
will have a happy journey using the powerful file manager.
|
|
|
|
|
|
==============================================================================
|
|
2. Functionality *VimExplorer-functionality*
|
|
|
|
2.1 Tree Panel Hotkeys *VimExplorer-treehotkey*
|
|
|
|
Member of |VEConf_treeHotkey|, refer to section 7.2 .
|
|
|
|
Mapping Key Description~
|
|
help ? Help.
|
|
toggleNode <cr> Open/Close/Switch to current node.
|
|
toggleNodeMouse <2-LeftMouse> Open/Close/Switch to current node.
|
|
refresh r Refresh the tree panel.
|
|
favorite f View favorite folder list.
|
|
addToFavorite F Add the folder under cursor to
|
|
favorite list. If no path under
|
|
cursor, use current working path.
|
|
browseHistory b View browse history.
|
|
toggleFilePanel t Toggle the file panel.
|
|
toUpperDir <bs> Go to upper directory.
|
|
switchPanel <c-tab> Switch to File Panel.
|
|
gotoPath <c-g> Change to another path.
|
|
quitVE Q Quit VimExplorer.
|
|
|
|
2.2 File Panel Hotkeys *VimExplorer-filehotkey*
|
|
|
|
Member of |VEConf_fileHotkey|, refer to section 7.2 .
|
|
|
|
Mapping Default Description~
|
|
help ? Help.
|
|
itemClicked <cr> Enter the directory or open the file
|
|
by default association.
|
|
itemClickMouse <2-LeftMouse> Enter the directory or open the file
|
|
by default association.
|
|
refresh r Refresh.
|
|
toggleTreePanel t Toggle the Tree Panel.
|
|
toggleModes i Toggle file sort mode (type/data/file
|
|
extension).
|
|
newFile +f Create a new file.
|
|
newDirectory +d Create a new directory.
|
|
switchPanel <c-tab> Switch to the Tree Panel.
|
|
quitVE Q Quit VimExplorer.
|
|
toggleHidden H Toggle show hidden files.(files start
|
|
with '.')
|
|
search g/ Search.
|
|
markPlace m{a-z} Put current path to register(a-z).
|
|
gotoPlace '{a-z} Jump to path in register(a-z).
|
|
viewMarks J View path in register.
|
|
contextMenuN <rightmouse> File panel context menu in normal mode.
|
|
toUpperDir <bs> Go to upper directory.
|
|
gotoForward <c-i> Forward.
|
|
gotoBackward <c-o> Backward.
|
|
favorite f View favorite folder list.
|
|
addToFavorite F Add the folder under cursor to
|
|
favorite list. If no path under
|
|
cursor, use current working path.
|
|
browseHistory b View browse history.
|
|
gotoPath <c-g> Change to another path.
|
|
rename R Rename the file under cursor.
|
|
yankSingle yy Copy file under cursor.
|
|
cutSingle xx Cut file under cursor.
|
|
showYankList yl Show clipboard.
|
|
deleteSingle dd Delete file under cursor to recycle bin.
|
|
deleteSingle DD Force delete file under cursor.
|
|
openPreview u Preview.
|
|
closePreview U Close the preview panel.
|
|
toggleSelectUp <s-space> Move the cursor up and mark/unmark the
|
|
file under cursor.
|
|
toggleSelectDown <space> Mark/unmark the file under cursor and
|
|
move the cursor down.
|
|
toggleSelMouse <c-leftmouse> Mark/unmark the file under cursor.
|
|
markViaRegexp Mr Mark via regular expression.
|
|
markVimFiles Mv Mark all vim files.
|
|
markDirectory Md Mark all directories.
|
|
markExecutable Me Mark all executable files.
|
|
clearSelect Mc Clear all marks.
|
|
deleteSelected sd Delete marked files to recycle bin.
|
|
deleteSelected sD Force delete marked files.
|
|
yankSelected sy Copy marked files.
|
|
cutSelected sx Cut marked files.
|
|
tabViewMulti se Edit every marked file in separate
|
|
tabs.
|
|
paste p Paste.
|
|
diff2files = Diff two files.
|
|
tabView e Edit file in new tab.
|
|
openRenamer ;r Open Renamer (Note 1)
|
|
startShell ;c Start a shell from current path.
|
|
startExplorer ;e Start another file
|
|
manager(nautilus,konquer,explorer.exe).
|
|
|
|
Visual Mode Hotkeys~
|
|
visualSelect <space> Mark files.
|
|
visualDelete d Delete files to recycle bin.
|
|
visualDelete D Force delete files.
|
|
visualYank y Copy files.
|
|
visualCut x Cut files.
|
|
tabView e View files in new tabs.
|
|
|
|
2.3 Commands *VimExplorer-commands*
|
|
>
|
|
VE
|
|
<
|
|
Start VimExplorer.
|
|
|
|
>
|
|
VEC
|
|
<
|
|
Close VimExplorer, Hotkey |Q| has the same ability.
|
|
|
|
==============================================================================
|
|
3. Directory Browsing *VimExplorer-browse*
|
|
|
|
3.1 Tree Browsing *VimExplorer-treebrowse*
|
|
|
|
Press "Enter" on one tree node will change the path and add the new path to
|
|
browse history. By default, if a directory has it's own child directories, |+|
|
|
will be displayed before it's name, and It will cause a little performance
|
|
lost. If you don't need this feature ,set the following variable to zero can
|
|
disable it.
|
|
>
|
|
let VEConf_showFolderStatus = 0
|
|
<
|
|
There are some differences between win32 and other platforms. In win32, there
|
|
are several root nodes (such as C:\,D:\), but one root node (/) in other
|
|
platforms.
|
|
|
|
3.2 File Browsing *VimExplorer-filebrowse*
|
|
|
|
The file panel consist of two parts: the path in the top and the following
|
|
file list. Every line of the file list consist from the following regions:
|
|
|
|
[*] {file-name} [file-size] {permission} {modify-time}
|
|
|
|
The file panel can sort by type, file name and date. Hotkey |i| is used to
|
|
cycle between these modes. Default sort mode controlled by following variable:
|
|
>
|
|
VEConf_filePanelSortType
|
|
|
|
<
|
|
See Customization section for more details.
|
|
|
|
3.3 Forward and Backward *VimExplorer-forbackward*
|
|
|
|
When using "Enter" switch to an new folder, the path will be add to browse
|
|
history. Then you can use |<c-o>| and |<c-i>| to go backward and forward.
|
|
Hotkey |b| is used to list all browse history, select by number or mouse can
|
|
take you directory to that path.
|
|
|
|
By default, the depth of browse history is 100. Controled by this variable:
|
|
>
|
|
VEConf_browseHistory
|
|
<
|
|
VimExplorer can remember the cursor position every time leaving a directory,
|
|
so it can restore the cursor when return to it. If a directory is newly
|
|
entered, the cursor will be put in the middle of the screen.
|
|
|
|
3.4 Favorites *VimExplorer-favorite*
|
|
|
|
The favorite folder list is saved to the file $HOME/.ve_favorite . It will be
|
|
updated when new folder is added to favorite by hotkey |F|. The format of
|
|
".ve_favorite" is very simple: every line is a path, so edit it is quite
|
|
easy.
|
|
|
|
3.5 Temp Marks *VimExplorer-tempmark*
|
|
|
|
Just like the favorites, |ma| put current path into register 'a', and |'a| can
|
|
jump to the path. |J| is used to list every non empty register. All paths in
|
|
register will disappear after VimExplorer exists.
|
|
|
|
==============================================================================
|
|
4. Marks *VimExplorer-mark*
|
|
|
|
The simplest way is to press <space> upon a file. There will be a '*' before
|
|
marked files and also be displayed in a different color.
|
|
There are three way to mark files:
|
|
|
|
4.1 Single File Marks *VimExplorer-marksingle*
|
|
|
|
<space> Invert selection, move the cursor down.
|
|
<s-space> Move the cursor up, then invert selection.
|
|
Just like most of vim commands, 5<space> will mark 5 files start from current
|
|
cursor.
|
|
|
|
4.2 Visual Marks *VimExplorer-markvisual*
|
|
|
|
<space> in visual mode will invert selected these files.
|
|
|
|
4.3 Regexp Marks *VimExplorer-markregexp*
|
|
|
|
Hotkey: |Mr|
|
|
Only the file name is the target of regexp match. Example:
|
|
>
|
|
Mark file (regexp): ^abc.*\.vim$
|
|
<
|
|
It will mark all vim scripts start with abc. The following functionalities is
|
|
derived from this feature:
|
|
|Mv| mark all vim scripts.
|
|
|Me| mark all executable files.
|
|
|Md| mark all directories.
|
|
and |Mc| to clear all marks.
|
|
|
|
==============================================================================
|
|
5. File Operations *VimExplorer-fileoperation*
|
|
|
|
5.1 Create *VimExplorer-new*
|
|
|
|
|+f| and |+d| is used to create new files and directories.
|
|
|
|
5.2 Move *VimExplorer-move*
|
|
|
|
There are several hotkey used to copy/cut files:
|
|
|yy| and |sy| in normal mode ,|y| in visual mode is to copy file.
|
|
|xx| and |sx| in normal mode ,|x| in visual mode is to cut file.
|
|
|p| paste file.
|
|
Note that the clipboard is shared between all VimExplorers ,you can cut in one
|
|
VE tab and paste in another.
|
|
If you want to view the clipboard, |yl| can be help.
|
|
|
|
5.3 Delete *VimExplorer-delete*
|
|
|
|
|dd|,|sd| in normal mode and |d| in visual mode can delete file(s) to recycle bin.
|
|
Corresponding |DD|,|sD| and |D| are used to force delete file(s).
|
|
|
|
5.4 Diff *VimExplorer-diff*
|
|
|
|
|=| is used to diff 2 files, so make sure you have selected 2 files before
|
|
using this command.
|
|
|
|
5.5 Search *VimExplorer-search*
|
|
|
|
Just like / ,but the pattern here is not the regexp in vim, it will be
|
|
expended by shell.
|
|
|
|
5.6 Other Operations *VimExplorer-otherfileopt*
|
|
|
|
|e| |R| |u| and so on ... Refer to section 2.2
|
|
|
|
==============================================================================
|
|
6. Other Functionalities *VimExplorer-otherfuncs*
|
|
|
|
|;r| |;c| |;e| and so on ...Rever to section 2.2
|
|
|
|
==============================================================================
|
|
7. Customization *VimExplorer-customize*
|
|
|
|
7.1 Normal Options *VimExplorer-custnormal*
|
|
|
|
Common Options~
|
|
|
|
|g:VEConf_systemEncoding| It controls the encoding of vim calling
|
|
function system(). If your system encoding
|
|
is different from '&encoding', set this
|
|
value to system encoding. Example: let
|
|
g:VEConf_systemEncoding = 'utf-8'
|
|
,Default: '' (empty)
|
|
|
|
|g:VEConf_win32Disks| The default value is all 26 volumes. Set this
|
|
value to fit your system can increase the
|
|
startup speed. If you are not using
|
|
Microsoft Windows, ignore it. Example:
|
|
let VEConf_win32Disks =
|
|
["A:","B:","C:","D:"]
|
|
|
|
|g:VEConf_browseHistory| Depth of browse history. Default: 100
|
|
|
|
|g:VEConf_previewSplitLocation| Split location of preview panel. Optional
|
|
parameters are:
|
|
"belowright","topleft","leftabove","botright".
|
|
Default: "belowright"
|
|
|
|
|g:VEConf_showHiddenFiles| Show hidden files, 1: show,0: hide. Default: 1
|
|
|
|
|g:VEConf_externalExplorer| Name of the external file explorer. You can
|
|
set this value according to you system.
|
|
Default: "explorer.exe"(win32) "nautilus"
|
|
(gnome)
|
|
|
|
|g:VEConf_sortCaseSensitive| 0: not case sensitive 1: case sensitive
|
|
Default: 1
|
|
|
|
|g:VEConf_favorite| Favorite folder file name. Always stored in
|
|
$HOME. Default: ".ve_favorite"
|
|
|
|
|g:VEConf_overWriteExisting| Ask when over write existing files.
|
|
0: ask 1: always over write 2: always
|
|
not over write Default: 0
|
|
|
|
|g:VEConf_usingKDE| If set to 1, use "kfmclient"
|
|
|g:VEConf_usingGnome| If set to 1, use "gnome-open"
|
|
|
|
|g:VEConf_recyclePath| Recycle path. Example:
|
|
let g:VEConf_recyclePath = 'C:\VErecycle\'
|
|
|
|
Tree Panel Options~
|
|
|
|
|g:VEConf_showFolderStatus| It controls whether show '+' before the
|
|
folders which have their own child
|
|
folders. If it is set to 1, every folder
|
|
will have a '+'. Default: 1
|
|
|
|
|g:VEConf_treePanelWidth| Width of tree panel. Default: 30
|
|
|
|
|g:VEConf_treePanelSplitMode| Split mode of tree panel. Default: "vertical"
|
|
|
|
|g:VEConf_treePanelSplitLocation| Split location of tree panel, Optional
|
|
parameters: "belowright" , "topleft" ,
|
|
"leftabove" , "botright", Default:
|
|
"leftabove"
|
|
|
|
|g:VEConf_treeSortDirection| Sort direction. 1: A-Z 0: Z-A. Default: 1
|
|
|
|
File Panel Options~
|
|
|
|
|g:VEConf_fileGroupSortDirection| Sort direction. 1: A-Z 0: Z-A, Default: 1
|
|
|
|
|g:VEConf_fileDeleteConfirm| Confirm when deleting a file. 1: confirm 2:
|
|
no confirm. Default: 1
|
|
|
|
|g:VEConf_filePanelWidth| Width of file panel. Default: 40
|
|
|
|
|g:VEConf_filePanelSplitMode| Split mode of file panel. Default: "vertical"
|
|
|
|
|g:VEConf_filePanelSplitLocation| Split location of file panel, Optional
|
|
parameters: "belowright" , "topleft" ,
|
|
"leftabove" , "botright" ,Default:
|
|
"leftabove"
|
|
|
|
|g:VEConf_filePanelSortType| File sort type. 1: sort by name 2: sort by
|
|
time 3: sort by type, Default: 3
|
|
|
|
|g:VEConf_showFileSizeInMKB| 1: Show file size in MKB format. 0: always
|
|
show file size in byte.
|
|
|
|
|g:VEConf_filePanelFilter| Filter of the file panel, which will be
|
|
passed to glob() function. Example:
|
|
let g:VEConf_filePanelFilter = '*.txt'
|
|
|
|
7.2 Hotkey Customization *VimExplorer-custhotkey*
|
|
|
|
All user defined hotkeys are controlled by the two dicts:
|
|
|g:VEConf_treeHotkey| and |g:VEConf_fileHotkey|
|
|
Example:
|
|
>
|
|
let g:VEConf_treeHotkey = {}
|
|
let g:VEConf_treeHotkey.help = '??'
|
|
let g:VEConf_treeHotkey.quitVE = 'qq'
|
|
let g:VEConf_treeHotkey.switchPanel = '<s-tab>'
|
|
<
|
|
All definable hotkeys and their default bindings refer to section 2 .
|
|
|
|
7.3. Command Customization *VimExplorer-custcommand*
|
|
|
|
VimExplorer supports three types of command interface:
|
|
single file hotkeys and actions, multi file hotkeys and actions and normal
|
|
hotkeys and actions.
|
|
They are controlled by these variables:
|
|
|
|
|g:VEConf_singleFileActions| |g:VEConf_singleFileHotKeys|
|
|
|
|
|g:VEConf_multiFileActions| |g:VEConf_multiFileHotKeys|
|
|
|
|
|g:VEConf_normalActions| |g:VEConf_normalHotKeys|
|
|
|
|
All of them are dicts. Example:
|
|
>
|
|
let g:VEConf_normalActions = {}
|
|
let g:VEConf_normalHotKeys = {}
|
|
let g:VEConf_normalHotKeys['test1'] = 'T1'
|
|
function! VEConf_normalActions['test1']()
|
|
Renamer
|
|
endfunction
|
|
<
|
|
"test1" is the key. VimExplorer will bind the hotkey and corresponding actions
|
|
automatically.
|
|
>
|
|
let g:VEConf_singleFileActions = {}
|
|
let g:VEConf_singleFileHotKeys = {}
|
|
let g:VEConf_singleFileHotKeys['test2'] = 'T2'
|
|
function! VEConf_singleFileActions['test2'](path)
|
|
call g:VEPlatform.system("notepad.exe " . g:VEPlatform.escape(a:path))
|
|
endfunction
|
|
<
|
|
Here, parameter "path" is the path of file under cursor.
|
|
>
|
|
let g:VEConf_multiFileActions = {}
|
|
let g:VEConf_multiFileHotKeys = {}
|
|
let g:VEConf_multiFileHotKeys['test3'] = 'T3'
|
|
function! VEConf_multiFileActions['test3'](fileList)
|
|
for i in a:fileList
|
|
call g:VEPlatform.start("nautilus " . i)
|
|
endfor
|
|
endfunction
|
|
<
|
|
Parameter "fileList" consists of all paths of marked files.
|
|
In addition, VimExplorer provides some platform independent functions:
|
|
>
|
|
g:VEPlatform.start(path)
|
|
g:VEPlatform.system(cmd)
|
|
g:VEPlatform.copyfile(filename,topath)
|
|
g:VEPlatform.search(filename,path)
|
|
g:VEPlatform.deleteSingle(path)
|
|
<
|
|
These functions can be used in user defined actions.
|
|
|
|
|
|
|
|
|
|
==============================================================================
|
|
8. The Author *VimExplorer-author*
|
|
|
|
If you have find a bug, or have some suggestions , mail me.
|
|
|
|
mail: mbbill<AT>gmail<Dot>com
|
|
|
|
==============================================================================
|
|
9. Problems and Fixes *VimExplorer-problems*
|
|
|
|
*VimExplorer-p1*
|
|
P1. Case sensitive in Win32.
|
|
At present, the path in win32 is case sensitive. Pay attention to this
|
|
when starting VE, editing the favorite list or using <c-g> to change
|
|
path. A good suggestion is using <tab> or <ctrl-d> to complete path
|
|
automatically.
|
|
|
|
*VimExplorer-p2*
|
|
P2. 'wildignre' option cause some files disappeared.
|
|
If 'wildignore' is not empty, glob() function will not return files
|
|
matching the file pattern listed in it, then you may find some files
|
|
disappeared in the file panel.
|
|
|
|
|
|
|
|
==============================================================================
|
|
10. Changelog *VimExplorer-changelog*
|
|
|
|
0.95
|
|
- Initial release.
|
|
|
|
0.96
|
|
- BUG: VE_normalAction not found.
|
|
|
|
0.97
|
|
- NEW: Add options |g:VEConf_usingKDE| and |g:VEConf_usingGnome| for
|
|
starting program in *nix environment.
|
|
- NEW: Check if the script is already loaded, thanks to Dennis Hostetler.
|
|
- BUG: Escape ' %#' for path.
|
|
- BUG: Favorite selection out of range.
|
|
- CHG: Change the behaviour of hotkey 'F', now it adds the path under
|
|
cursor to favorite list. If no path under cursor, use current
|
|
working path instead.(Thanks to Vincent Wang)
|
|
- CHG: Change default g:VEConf_systemEncoding to '' (empty).
|
|
0.98
|
|
- NEW: Add option VEConf_filePanelFilter.
|
|
- BUG: Escape <space> in command 'e' 'se' 'u' and '='.
|
|
- BUG: 'Cut' and 'Paste' command causes file lost.
|
|
- CHG: Change the default hotkey 'M' and 'B' to 'm','J'.
|
|
- CHG: Change forward and backward hotkey to |<c-o>| and |<c-i>|(<tab>).
|
|
- CHG: Change hotkey |<tab>| to |<c-tab>|.
|
|
- CHG: Change hotkey |mr| |mv| |md| |me| |mc| to |Mr| |Mv| |Md| |Me| |Mc|.
|
|
- CHG: When GUI is running, use confirm() to pop a dialog instead of input().
|
|
0.99
|
|
- NEW: Add toggle selection hotkey <c-leftmouse>.
|
|
- NEW: Add a context menu in file panel, right click on a file to popup it.
|
|
- NEW: Add "delete to recycle",hotkey |dd|,|sd| and |d| in visual mode
|
|
are used to delete file(s) to recycle bin.The curresponding
|
|
|DD|,|sD|,|D| hotkey are used to force delete files.
|
|
- NEW: Now VE can remember the cursor position when reenter a directory.
|
|
- BUG: All files are put to "Hidden Files" group in a hidden directory.
|
|
- BUG: 'sd' twice after selection will cause an error.
|
|
|
|
==============================================================================
|
|
11. TODO *VimExplorer-todo*
|
|
- More clipboard.
|
|
- Diff files in different directories.
|
|
- Two panel mode, just like TotalCommand.
|
|
- Diff directories.
|
|
- Browse via e.g. FTP, SCP ... directorys on a server.
|
|
- Rename file when file exsits in copy operation.
|
|
- Compress file.
|
|
- Send to.
|
|
|
|
|
|
==============================================================================
|
|
Note 1:
|
|
Renamer is a good plugin, which is used to rename group of files. The author
|
|
is John Orr. It can be found here:
|
|
http://www.vim.org/scripts/script.php?script_id=1721
|
|
|
|
|
|
=== END_DOC
|
|
" vim: set et fdm=marker sts=4 sw=4 tw=78:
|