" Documentation {{{1 " Name: vimExplorer.vim " Version: 1.0 " Description: Directory and file explorer for vim. " Author: Alexandre Viau (alexandreviau@gmail.com) " Installation: Copy the plugin to the vim plugin directory. " " Usage {{{2 " " Mappings: {{{3 " " Open vimExplorer using the last accessed path {{{4 " vb Start vimExplorer in the current window " vs Start vimExplorer in a new split (horizontal) window " vv Start vimExplorer in a new vsplit (vertical) window " vt Start vimExplorer in a new tab " Open vimExplorer using a the current file's path {{{4 " VB Start vimExplorer in the current window " VS Start vimExplorer in a new split (horizontal) window " VV Start vimExplorer in a new vsplit (vertical) window " VT Start vimExplorer in a new tab " " The following plugins use "" as as leader key, you may change it by setting the "s:MapLeader" variable to another key. " " Directory browsing {{{5 " " l Open the selected directory " h Go to the parent directory " " a Write the path (like an address bar, / or \ may be used) " f Set filter to show only certain files " F Remove the filter and show all files " L Open the selected directory recursively " o Reload directory " p Copy path " P Show current path in different formats and to the clipboard " x Open directory in external file manager " NOTE: You may change the path of the external file manager in the x mapping. " " Directory bookmarks {{{5 " " ma to mz Directory marks like similar to marks in vim using the m key but to mark directories instead of positions in files and ' or ` or ; to return to that directory. The maps are automatically activated on a directory listing. For example, press mw to mark the c:\windows directory, then do 'w (or `w or ;w) to return to that directory. All letters may be used from a to z, A to Z and 0 to 9. Press '' to view a list of all the bookmarked directories sorted by mark, or press ;; to view the same list but sorted by paths. When '' or ;; is pressed, the list is shown and a mark is asked as input to goto to its directory, this is another way that marks are used. " m0 to m9 Same like ma to mz but using numbers as marks " 'a to 'z or `a to `z To return to the directories marked by ma to mz " '0 to '9 or `0 to `9 Same like ma to mz but using numbers as marks " ' Show all marked directories sorted by marks " [ Show all marked directories sorted by directories " " Directory file grep {{{5 " G Simple grep command to search the files in the current directory and subdirectories. The results are appended at the end of the buffer. After the results are appended, if you want to open a file that appears in the grep results do l on the line where that file is, the file will be opened on a split window at the line number where that grep found the keywords. " NOTE: The UnxUtils grep command dosen't seems to be able to do file filtering when doing a recursive grep, so no "include" will be prompted and all files will be grepped) " " Directory file search {{{5 " L To search files in a directory, open the selected directory recursively using L and then search the buffer for the file using vim's "/" command or use vimgrep. " " Directory sorting {{{5 " " 1 Sort by name " 2 Sort by type " 3 Sort by size " 4 Sort by date " " Browsing history {{{5 " " l or Go to one of the history path shown at the top of the buffer, put cursor on one of the paths and execute this mapping. Tip: W or B to move from one path to another in the history. " ; Go to the history list (then do ; or , (from the vim 'f' command) to move forward and backward from one path to another, then when on the desired path, do g to goto the directory.) " , Go to the end of the history list (then do ; or , (from the vim 'f' command) to move forward and backward from one path to another, then when on the desired path, do g to goto the directory.) " H Delete the browsing history " NOTE: 1. The maximum length of the history bar may be changed by setting the "s:HistoryMaxLength" variable " 2. You may use the "set wrap" command to see all history if the list is long " " File operations {{{5 " " d New directory " l or Open file in horizontal split window " v Open file in vertical split window " t Open file in new tab " c Clone file " D Delete file/directory " n New file " R Rename file " r Run file " " Shell operations {{{5 " " Execute a command and insert its output in the buffer " C Open directory in shell " " Configuration file operations {{{5 " " o Reload configuration from file (useful if the .config.vim file was edited manually and you want to reload it in the vimExplorer window that is currently opened) " s Save configuration file " NOTE: The configuration is automatically loaded when vim starts, and it is automatically closed when vim quits. " " How to get the current path and filename for usage in external scripts {{{5 " " If you want to get the current path and filename from vimExplorer first call the "g:VeGetPath()" then use the following variables as needed. " These paths variables may be used for example if you do new mappings or some kind of menu to execute operations on the current file or directory. " Note that the current path and filename are copied when leaving the plugin window for another window so the following variables could be used from there. " " Filename " g:VeFileName (filename only without path) " g:VeFileNameQ (filename only without path + quotes) " g:VeFileName2Q (filename only without path + double quotes) " Path with / (slash) " g:VePath (without filename) " g:VePathSQ (without filename + quotes) " g:VePathS2Q (without filename + double quotes) " g:VeFullPathS (with filename) " g:VeFullPathSQ (with filename + quotes) " g:VeFullPathS2Q (with filename + double quotes) " Path with \ (B = backslash) " g:VePathB (without filename) " g:VePathBQ (without filename + quotes) " g:VePathB2Q (without filename + double quotes) " g:VeFullPathB (with filename) " g:VeFullPathBQ (with filename + quotes) " g:VeFullPathB2Q (with filename + double quotes) " Path with \\ (2B = double backslash) " g:VePath2B " g:VePath2BQ = (without filename + quotes) " g:VePath2B2Q = (without filename + double quotes) " g:VeFullPath2B (with filename) " g:VeFullPath2BQ (with filename + quotes) " g:VeFullPath2B2Q (with filename + double quotes) " " How to open vimExplorer from another script {{{5 " " Call the function "g:VeDirectoryGoto()" and pass the path as parameter. " Example: cal g:VeDirectoryGoto('/usr/bin') or cal g:VeDirectoryGoto('c:/windows') " You may have to do a "split", "vsplit" or "tabnew" before calling "g:VeDirectoryGoto()" " " Commands: {{{3 " " Open vimExplorer using the last accessed path {{{5 " " VimExplorerB Start vimExplorer in the current window " VimExplorerS Start vimExplorer in a new split (horizontal) window " VimExplorerV Start vimExplorer in a new vsplit (vertical) window " VimExplorerT Start vimExplorer in a new tab " " Open vimExplorer using a the current file's path {{{5 " " VimExplorerBF Start vimExplorer in the current window " VimExplorerSF Start vimExplorer in a new split (horizontal) window " VimExplorerVF Start vimExplorer in a new vsplit (vertical) window " VimExplorerTF Start vimExplorer in a new tab " Open vimExplorer using a path specified on the command line {{{5 " VimExplorerBP Start vimExplorer in the current window " VimExplorerSP Start vimExplorer in a new split (horizontal) window " VimExplorerVP Start vimExplorer in a new vsplit (vertical) window " VimExplorerTP Start vimExplorer in a new tab " " Tips {{{2 " " - You may use the "set wrap" command to see all history if the list is long. " - To search files in a directory, open the selected directory recursively using L and then search the buffer for the file using vim's "/" command or use vimgrep. " - I use also the MRU plugin in combination with vimExplorer to have a list of the last opened files, I find it extremely useful for vim editing. " - If you need to do file operations like copy or move files, since these are not implemented in the plugin, vimExplorer to move quickly between directories and then do x to open you file manager or C to open the console, also to run a command. " Todo {{{2 " " test delete file/dir in linux " trouver comment mettre des end-of-line dans substitute est utiliser afin d'avoir des end-of-line dans le fichier .conf.vim j'ai essayer avec \n mais ca fait des @^ dans le fichier et quand je reload le fichier apres l'avoir saver je n'ai pas access a ses info entre autre les bookmark list " The mappings could probably be activated and deactivated using the instruction and placed in the AddMaps function. I tried to put one directly there with the instruction but it was still activated when I changed window, there is probably another option to set... But one advantage of having the mappings to a dictionnary is to be able to change the leader key for mappings dynamically and even change the mappings dynamically...maybe this could be done too without dictionnary... Different sets of mappings could be loaded/unloaded dynamically using a dictionnary this is another advantage... see later if there is time. Mappings could be also changed individually as a function to add the mappings would do them all at once. " put in the autocommands so onenter and onleave will be executed only for a vimexplorer buffer and then no need for the ispluginwindow perhaps " I tried to put to the TabEnter,WinEnter,BufEnter autocommands but it didn't work " see if autocommands functions called multiple times...if yes then find a way not to execute the code called multiple times, maybe by using a script counter...or a boolean " mettre le save config sur cursorHold autoevent " continue commands to open in vsplit, new tab etc j'ai fait des type de window dans buildwindow() faire des commandes correspondantes sans trop dupliquer de code si possible " concernant ce qui suit a propos des tags...peut-etre pas le faire, les operations de copie se font mieux en windows et ca vaudrait pas la peine...c'est pas un file manager mais pour editer des fichiers...peut-etre ajouter t pour tagger les fichier, ajouter les fichiers tagges dans un dictionnaire (dans le g:VeCfg) dans un section "taggedFiles". lorsqu'un fichier est tagge, appender un "*" apres le filename, et ajouter un highlight dans setcolor() pour highlighte les lignes qui se termine par "*". Le fullpath serait la cle de l'item de dictionnaire et le filename la value. avec ces deux si une commande demande un full path on l'aura et si une autre command demande seulement le filename (comme dans la command grep) on l'aura aussi. faire une fonction qui update la liste des fichier et ajoute les asterisque "*" apres les filename (avec un loop des values du dictionnaire et search replace les filename du buffer) et ajout le highligh (appelle setcolor()) utiliser pour grep, move et copy " " Bugs {{{2 " " 1. le config file a ete overwrite pour une raison que j'ignore... a surveiller " 2. ne fonctionne pas dans cygwin console et xconsole " 3. On dirait qu'il a sauvegarder des endroit qui ne sont pas des lignes du listing comme emplacement de repertoire...voir si c'est pas des anciennes donnees " exemple " 'C:/Documents and Settings': 'otal 0' " 4. Le config file n'est pas loader pour une raison que j'ignore... " " History {{{2 " " 1.0 First release " Variables: Plugin {{{1 " Flag indicating that the plugin is starting for the first time and not already opened and accessed from another window let g:VeOpening = 0 " To add debug information after a directory listing let g:Debug = '' " Variables: Configuration {{{1 let g:VeCfgFile = $home . '/vimExplorer.conf.vim' " The declaration of the variable 'g:VeCfg' is in the g:VeLoadFromFile() function, this is to avoid to erase its content when developing and sourcing (so %) this file, but otherwise it should be here like this "let g:VeCfg = {}". " Variables: Directory browsing {{{1 " The column position where the file name starts let s:FileNameColNum = 0 " The line number where the directory listing is starting let s:DirectoryListLineNum = 7 " The history bar at the top of the buffer let s:History = '' " The maximum lenght for the history bar the top of the buffer let s:HistoryMaxLength = 1000 " Variables: Paths {{{2 " The declaration of the variable 'g:VePath' is in the g:VeLoadFromFile() function, this is to avoid to erase its content when developing and sourcing (so %) this file, but otherwise it should be here like this "let g:VePath = ''". " Filename let g:VeFileName = '' let g:VeFileNameQ = '' " (with quotes) let g:VeFileName2Q = '' " (with quotes) " Path with / " No g:VePathS because g:VePath is already with "/" let g:VePathSQ = '' " (without filename + quotes) let g:VePathS2Q = '' " (without filename + double quotes) let g:VeFullPathS = '' " (with filename) let g:VeFullPathSQ = '' " (with filename + quotes) let g:VeFullPathS2Q = '' " (with filename + double quotes) " Path with \ let g:VePathB = '' " (without filename) let g:VePathBQ = '' " (without filename + quotes) let g:VePathB2Q = '' " (without filename + double quotes) let g:VeFullPathB = '' " (with filename) let g:VeFullPathBQ = '' " (with filename + quotes) let g:VeFullPathB2Q = '' " (with filename + double quotes) " Path with \\ let g:VePath2B = '' " (without filename) let g:VePath2BQ = '' " (without filename + quotes) let g:VePath2B2Q = '' " (without filename + double quotes) let g:VeFullPath2B = '' " (with filename) let g:VeFullPath2BQ = '' " (with filename + quotes) let g:VeFullPath2B2Q = '' " (with filename + double quotes) " Variables: Ls command {{{2 " Default filter (all files) let g:VeFilter = '' " Default sorting let g:VeSort = '-U' let g:VeSortLabel = 'Name' " Defaut recursive let g:VeRecursive = '' " Windows if has('Win32') " Cygwin ls command "let s:LsCmdPath = 'c:\cygwin\bin\ls.exe' " UnixUtils ls command path (The version I tested dosen't show Windows7 links as links but shows them as regular directories, and it produce an error when changing to it and produces errors if russian directory name. It seems also more faster than cygwin ls but cygwin ls displays everything correctly.) let s:LsCmdPath = 'C:\Usb\z_white\Apps\Portable\CmdUtils\ls.exe' " Linux else " ls command let s:LsCmdPath = 'ls' endif " Variables: Directory grep {{{1 " Windows if has('Win32') " Select the grep command: c = cygwin, u = UnxUtils (the options are not the same for both grep commands) " Cygwin grep command let s:GrepCmdType = 'c' let g:VeGrepCmdPath = 'c:\cygwin\bin\grep.exe' " UnxUtils command (it seems this version of the grep command dosen't seem to be able to do file filtering when doing a recursive grep, so no "include" will be prompted and all files will be grepped) "let s:GrepCmdType = 'u' "let g:VeGrepCmdPath = 'C:\Usb\z_white\Apps\Portable\CmdUtils\grep.exe' " Linux else let g:VeGrepCmdPath = 'grep' endif " Autocommands {{{1 au! VimEnter * cal g:VeLoadFromFile(1) au! VimLeave * cal g:VeSaveToFile() au! TabEnter,WinEnter,BufEnter * cal s:OnEnter() au! TabLeave,WinLeave,BufLeave * cal s:OnLeave() " Mappings: To start the plugin {{{1 " Open vimExplorer using the last accessed path {{{2 " Create the window in the current window map vb :VimExplorerB " Create the window in a new split (horizontal) window map vs :VimExplorerS " Create the window in a new vsplit (vertical) window map vv :VimExplorerV " Create the window in a new tab map vt :VimExplorerT " Open vimExplorer using a the current file's path {{{2 " Create the window in the current window map VB :VimExplorerBF " Create the window in a new split (horizontal) window map VS :VimExplorerSF " Create the window in a new vsplit (vertical) window map VV> :VimExplorerVF " Create the window in a new tab map VT :VimExplorerTF " Commands: To start the plugin {{{1 " Open vimExplorer using the last accessed path {{{2 " Create the window in the current window command! -nargs=0 VimExplorerB let g:VeOpening = 1 | cal g:BuildWindow('b') | cal g:VeDirectoryGoto(g:VePath) | let g:VeOpening = 0 " Create the window in a new split (horizontal) window command! -nargs=0 VimExplorerS let g:VeOpening = 1 | cal g:BuildWindow('s') | cal g:VeDirectoryGoto(g:VePath) | let g:VeOpening = 0 " Create the window in a new vsplit (vertical) window command! -nargs=0 VimExplorerV let g:VeOpening = 1 | cal g:BuildWindow('v') | cal g:VeDirectoryGoto(g:VePath) | let g:VeOpening = 0 " Create the window in a new tab command! -nargs=0 VimExplorerT let g:VeOpening = 1 | cal g:BuildWindow('t') | cal g:VeDirectoryGoto(g:VePath) | let g:VeOpening = 0 " Open vimExplorer using a the current file's path {{{2 " Create the window in the current window command! -nargs=0 VimExplorerBF let g:VeOpening = 1 | let p = expand('%:p:h') | cal g:BuildWindow('b') | cal g:VeDirectoryGoto(p) | let g:VeOpening = 0 " Create the window in a new split (horizontal) window command! -nargs=0 VimExplorerSF let g:VeOpening = 1 | let p = expand('%:p:h') | cal g:BuildWindow('s') | cal g:VeDirectoryGoto(p) | let g:VeOpening = 0 " Create the window in a new vsplit (vertical) window command! -nargs=0 VimExplorerVF let g:VeOpening = 1 | let p = expand('%:p:h') | cal g:BuildWindow('v') | cal g:VeDirectoryGoto(p) | let g:VeOpening = 0 " Create the window in a new tab command! -nargs=0 VimExplorerTF let g:VeOpening = 1 | let p = expand('%:p:h') | cal g:BuildWindow('t') | cal g:VeDirectoryGoto(p) | let g:VeOpening = 0 " Open vimExplorer using a path specified on the command line {{{2 " Create the window in the current window command! -nargs=1 VimExplorerBP let g:VeOpening = 1 | cal g:BuildWindow('b') | cal g:VeDirectoryGoto() | let g:VeOpening = 0 " Create the window in a new split (horizontal) window command! -nargs=1 VimExplorerSP let g:VeOpening = 1 | cal g:BuildWindow('s') | cal g:VeDirectoryGoto() | let g:VeOpening = 0 " Create the window in a new vsplit (vertical) window command! -nargs=1 VimExplorerVP let g:VeOpening = 1 | cal g:BuildWindow('v') | cal g:VeDirectoryGoto() | let g:VeOpening = 0 " Create the window in a new tab command! -nargs=1 VimExplorerTP let g:VeOpening = 1 | cal g:BuildWindow('t') | cal g:VeDirectoryGoto() | let g:VeOpening = 0 " Functions: Plugin {{{1 " s:IsPluginWindow() {{{2 " Check if currently in this plugin window fu! s:IsPluginWindow() " Get first line where there is the name of the plugin let lines = getline(1, 1) " If the first line contains the name of the plugin then it is a plugin window if lines[0] == 'vimExplorer' retu 1 else retu 0 endif endfu " OnEnter() {{{2 fu! s:OnEnter() if g:VeOpening == 0 " The window is a vimExplorer window {{{ if s:IsPluginWindow() == 1 " Get the instance path {{{ " Don't check for current path if plugin is opening. OnEnter() is triggered when the window is builded by BuildWindow() and the path should not be copied at this point. " These lines of code below allow to use multiple windows of the plugin, getting the "instance" current path by copying the path at the top of the buffer and changing to it when changing from one window to another. " Copy path on the top of the plugin window let tmpReg = @" exe 'norm ggjWy$' let path = @" let @" = tmpReg " Go back to previous position exe "norm \" " Change to this instance path directory cal s:ChangeDirectory(path) "}}} "}}} endif endif endfu " OnLeave() {{{2 fu! s:OnLeave() " The window is a vimExplorer window if s:IsPluginWindow() == 1 " Keep a copy of the current path and filename variables to use from another window cal g:VeGetPath() endif endfu " BuildWindow() (window creation, options and mappings) {{{2 fu! g:BuildWindow(winType) " Create the window in the current window {{{3 if a:winType == 'b' enew " Create the window in a new split (horizontal) window elseif a:winType == 's' new " Create the window in a new vsplit (vertical) window elseif a:winType == 'v' vsplit enew " Create the window in a new tab elseif a:winType == 't' tabnew endif " Options: Local {{{3 " Check help for information on these options setlocal fdc=0 setlocal nonu setlocal nornu setlocal buftype=nofile setlocal bufhidden=delete setlocal noswapfile setlocal nowrap setlocal nobuflisted " Mappings: Common to all OSes {{{3 " Execute a command and insert its output in the buffer nmap :cal g:VeGetPath() \| let f = input('r! ', '') \| if f != '' \| exe 'norm G' \| exe 'r! ' . f \| endif " Open the selected item nmap :cal g:VeOpenItem(0) " Go to the parent directory nmap :cal g:VeDirectoryGoto('..') " Execute a command and insert its output in the buffer nmap :cal g:VeGetPath() \| let f = input('r! ', '') \| if f != '' \| exe 'norm G' \| exe 'r! ' . f \| endif " ' Show all marked directories sorted by marks nmap ' :cal g:VeShowMarks(0) " [ Show all marked directories sorted by directories nmap [ :cal g:VeShowMarks(1) " 1 Sort by name nmap 1 :let g:VeSort = '-U' \| let g:VeSortLabel = 'Name' \| cal g:VeLs() " 2 Sort by type nmap 2 :let g:VeSort = '-X' \| let g:VeSortLabel = 'Type' \| cal g:VeLs() " 3 Sort by size nmap 3 :let g:VeSort = '-S' \| let g:VeSortLabel = 'Size' \| cal g:VeLs() " 4 Sort by date nmap 4 :let g:VeSort = '-t' \| let g:VeSortLabel = 'Date' \| cal g:VeLs() " a Write the path (like an address bar, / or \ may be used) nmap a :cal g:VeGetPath() \| let p = input('Enter a path: ', g:VePath) \| if p != '' \| cal g:VeDirectoryGoto(p) \| endif " f Set filter to show only certain files nmap f :let g:VeFilter = input('Filter: ', g:VeFilter) \| cal g:VeLs() " F Remove the filter and show all files nmap F :let g:VeFilter = '' \| cal g:VeLs() " g Simple grep command to search the files in the current directory (not searching the subdirectories). The results are appended at the end of the buffer. After the results are appended, if you want to open a file that appears in the grep results do l on the line where that file is, the file will be opened on a split window at the line number where that grep found the keywords. nmap g :cal g:VeGetPath() \| let k = input('grep files keywords: ') \| let i = input('include files: ', '*') \| if k != '' \| exe 'norm G' \| let n = line('.') \| exe 'r! ' . g:VeGrepCmdPath . ' -n -i ' . k . ' ' . g:VePathS2Q . '/' . i \| exe 'normal zR' . n . 'G' \| exe 'let @/="' . k . '"' \| exe 'normal n' \| endif " G Simple grep command to search the files in the current directory and subdirectories. The results are appended at the end of the buffer. After the results are appended, if you want to open a file that appears in the grep results do l on the line where that file is, the file will be opened on a split window at the line number where that grep found the keywords. if s:GrepCmdType == 'c' nmap G :cal g:VeGetPath() \| let k = input('+grep files keywords: ') \| let i = input('include files: ', '*') \| if k != '' \| exe 'norm G' \| let n = line('.') \| exe 'r! ' . g:VeGrepCmdPath . ' -n -i -r ' . k . ' ' . g:VePathS2Q \| exe 'normal zR' . n . 'G' \| exe 'let @/="' . k . '"' \| exe 'normal n' \| endif elseif s:GrepCmdType == 'u' nmap G :cal g:VeGetPath() \| let k = input('+grep files keywords: ') \| if k != '' \| exe 'norm G' \| let n = line('.') \| exe 'r! ' . g:VeGrepCmdPath . ' -n -i -r ' . k . ' ' . g:VePathS2Q \| exe 'normal zR' . n . 'G' \| exe 'let @/="' . k . '"' \| exe 'normal n' \| endif endif " h Go to the parent directory nmap h :cal g:VeDirectoryGoto('..') " ; Go to the history list (then do ; or , (from the vim 'f' command) to move forward and backward from one path to another, then when on the desired path, do g to goto the directory.) nmap ; :exe 'norm gg' \| call search('History') \| exe 'norm f[' " , Go to the end of the history list (then do ; or , (from the vim 'f' command) to move forward and backward from one path to another, then when on the desired path, do g to goto the directory.) nmap , :exe 'norm gg' \| call search('History') \| exe 'norm $f[' \| norm , " l Open the selected item nmap l :cal g:VeOpenItem(0) " L Open the selected item recursively (only the directory will open recursively, if the item is a file it will be opened like with l) nmap L :let g:VeRecursive = '-R' \| cal g:VeOpenItem(0) " n New tab nmap n :tabnew " o Reload directory nmap o :cal g:VeLs() " o Reload configuration from file (useful if the .config.vim file was edited manually and you want to reload it in the vimExplorer window that is currently opened) nmap O :cal g:VeLoadFromFile(0) " P Show current path nmap P :pwd " r Run file nmap r :cal g:VeGetPath() \| exe '! ' . g:VeFullPathB2Q " t Open file in new tab nmap t :cal g:VeGetPath() \| exe 'tabe ' . g:VeFullPathS " v Open the selected item (in vertical split window) nmap v :cal g:VeOpenItem(1) " s Save configuration file nmap s :cal g:VeSaveToFile() " H Delete the browsing history nmap H :cal g:CfgSetItem(g:VeCfg, 'history', '') \| :cal g:VeDirectoryGoto(g:VePath) " Mappings: Windows specific {{{3 if has('Win32') == 1 " c Clone file nmap c :cal g:VeGetPath() \| let t = g:VeFileName . '_' . substitute(strftime('%x_%X'), ':', '-', 'g') \| exe '!copy ' . g:VeFileName2Q . ' "' . t . '"' \| cal g:VeLs() \| cal search(t) " C Open directory in shell nmap C :exe '!cmd /k' " d New directory nmap d :let t = input('Directory name: ') \| cal mkdir(t) \| cal g:VeLs() \| cal search(t) " D Delete file/directory nmap D :cal g:VeGetPath() \| let r = input('Delete this directory/file [(y)es/(n)o]? ', '') \| if r == 'y' \| exe '!del /S/Q ' . g:VeFullPathB2Q \| exe '!rmdir /S/Q ' . g:VeFullPathB2Q \| endif \| cal g:VeLs() " p Copy path nmap p :cal g:VeGetPath() \| let @* = g:VeFullPathB \| echo 'Path copied to clipboard: ' . g:VeFullPathB " R Rename file nmap R :cal g:VeGetPath() \| let t = input('rename to: ', g:VeFileName) \| exe '!ren ' . g:VeFileName2Q . ' "' . t . '"' \| cal g:VeLs() \| cal search(t) " x Open directory in windows explorer nmap x :cal g:VeGetPath() \| exe '!start explorer.exe ' . g:VePathB2Q) " Mappings: Linux specific {{{3 else " c Clone file nmap c :cal g:VeGetPath() \| let t = g:VeFileName . "_' . substitute(strftime('%x_%X'), ':', '-', 'g') \| exe '!cp ' . g:VeFileName2Q . ' "' . t . '"' \| cal g:VeLs() \| cal search(t) " C Open directory in shell nmap C :sh") " c New directory nmap c :let t = input("Directory name: ') \| cal mkdir(t) \| cal g:VeLs() \| cal search(t) " D Delete file/directory nmap D :cal g:VeGetPath() \| let r = input("Delete this directory/file [(y)es/(n)o]? ', '') \| if r == 'y' \| exe '!rm ' . g:VeFullPathB2Q \| exe '!rmdir ' . g:VeFullPathB2Q \| endif \| cal g:VeLs() " p Copy path nmap p :cal g:VeGetPath() \| let @* = g:VeFullPathS \| echo "Path copied to clipboard: ' . g:VeFullPathS') " R Rename file nmap R :cal g:VeGetPath() \| let t = input("rename to: ', g:VeFileName) \| exe '! mv ' . g:VeFileName2Q . ' "' . t . '"' \| cal g:VeLs() \| cal search(t) " x Open directory in thunar nmap x :cal g:VeGetPath() \| exe "!thunar ' . g:VePathS2Q endif " Mappings: For marks (bookmarks) {{{3 " Add mappings to mark directories (bookmark them) using vim markers style for n in range(0, 9) exe "nmap m" . n . " :cal g:VeMarkPath('" . n . "')" exe "nmap '" . n . " :cal g:VeGotoMark('" . n . "')" exe "nmap `" . n . " :cal g:VeGotoMark('" . n . "')" endfor for n in range(1, 26) " uppercase let l = nr2char(n + 64) exe "nmap m" . l . " :cal g:VeMarkPath('" . l . "')" exe "nmap '" . l . " :cal g:VeGotoMark('" . l . "')" exe "nmap `" . l . " :cal g:VeGotoMark('" . l . "')" " lowercase let l = nr2char(n + 96) exe "nmap m" . l . " :cal g:VeMarkPath('" . l . "')" exe "nmap '" . l . " :cal g:VeGotoMark('" . l . "')" exe "nmap `" . l . " :cal g:VeGotoMark('" . l . "')" endfor "}}} endfu " Functions: Directory browsing {{{1 " s:GetFileName() {{{2 " Get the file name on the current line fu! s:GetFileName() " Check if currently inside the directory listing, if the line is before the first line of the directory listing, return nothing if line('.') < s:DirectoryListLineNum return '' endif let t = @" let fileNameColNum = str2nr(s:FileNameColNum) - 1 exe "norm 0" . fileNameColNum . "ly$" let fileName = @" let @" = t retu fileName endfu " s:GetRecursivePath() {{{2 " Gets the current subdirectory path of a recursive listing that is displayed when the -R option is used " For example if the following subdirectory listing is displayed, then the c:/Temp\test path will be copied " C:/Temp\test=: " total 1 " drwxrwxrwx 1 user group 0 Nov 20 21:49 . " drwxrwxrwx 1 user group 0 Dec 11 21:25 .. " -rw-rw-rw- 1 user group 15 Nov 19 21:45 test2.txt fu! s:GetRecursivePath() " Remember current position norm m' " Search backwards if there is a place where there is a recusive path let match = search('^.*=:$', 'bW') " Not found if match == 0 let path = '' " Found else " Backup register " let tmpReg = @" " Copy the path to the " register norm yt= let path = @" " Set back register " let @" = tmpReg " Go back to previous position norm '' endif return path endfu " s:ChangeDirectory(path) {{{2 " Change directory fu! s:ChangeDirectory(path) let path = a:path " If the path contains double / in case of root paths (c:/, d:/ etc) where usually paths don't end with a trailling /, root paths always have trailling /, so they may be one to many if has("Win32") && len(g:VePath) == 3 let path = substitute(path, '//', '/', 'g') endif " Change to the directory in vim exe 'cd ' . path " Get real path from vim without /../.. etc let path = getcwd() " Change to the directory in shell exe 'r! cd "' . path . '"' " If the path is with "\" the change them for "/" if stridx(path, '\') != -1 let path = substitute(path, '\', '/', 'g') endif " Set the global path let g:VePath = path endfu " g:VeGetPath() {{{2 " To get the paths for external use fu! g:VeGetPath() " Attempt to get the current subdirectory path of a recursive listing that is displayed when the -R option is used let path = s:GetRecursivePath() " If a path is found if path != '' " Set g:VePath to the current subdirectory path of the recursive listing let g:VePath = path endif " If root path in windows example c:/, then remove trailing slash, other paths don't have trailing slashes if has("Win32") && len(g:VePath) == 3 let path = strpart(g:VePath, 0, 2) else let path = g:VePath endif let g:VeFileName = s:GetFileName() let g:VeFileNameQ = "'" . g:VeFileName . "'" let g:VeFileName2Q = '"' . g:VeFileName . '"' " With / " No g:VePathS because g:VePath is already with "/" let g:VePathSQ = "'" . g:VePath . "'" let g:VePathS2Q = '"' . g:VePath . '"' let g:VeFullPathS = g:VePath . '/' . g:VeFileName let g:VeFullPathSQ = "'" . g:VeFullPathS . "'" let g:VeFullPathS2Q = '"' . g:VeFullPathS . '"' " With \ let g:VePathB = substitute(path, '/', '\', 'g') let g:VePathBQ = "'" . g:VePathB . "'" let g:VePathB2Q = '"' . g:VePathB . '"' let g:VeFullPathB = g:VePathB . '\' . g:VeFileName let g:VeFullPathBQ = "'" . g:VeFullPathB . "'" let g:VeFullPathB2Q = '"' . g:VeFullPathB . '"' " With \\ let g:VePath2B = substitute(path, '/', '\', 'g') let g:VePath2B = substitute(g:VePath2B, '\', '\\\\', 'g') let g:VePath2BQ = "'" . g:VePathB . "'" let g:VePath2B2Q = '"' . g:VePathB . '"' let g:VeFullPath2B = g:VePath2B . '\\' . g:VeFileName let g:VeFullPath2BQ = "'" . g:VeFullPath2B . "'" let g:VeFullPath2B2Q = '"' . g:VeFullPath2B . '"' endfu " g:VeLs() {{{2 " List the directory fu! g:VeLs() " Clear buffer norm ggVGd " List the directory " If not root path c:\ or another root, add quotes. Root path quoted ("c:\") will give an error. " Or if there is a filter, then don't put quotes, quotes don't work in a filter if (has("Win32") && len(g:VePath) == 3) || g:VeFilter != '' " Set filter let filter = '' if g:VeFilter != '' let filter = '/' . g:VeFilter endif exe 'r! ' . s:LsCmdPath . ' -al ' . g:VeSort . ' ' . g:VeRecursive . ' ' . g:VePath . filter else " Don't use g:VePathS2Q here because the paths in g:VeGetPath() are not updated at this point, the listing as to be completed first because the function attempts to get the recursive paths is any exe 'r! ' . s:LsCmdPath . ' -al ' . g:VeSort . ' ' . g:VeRecursive . ' "' . g:VePath . '"' endif " Show the plugin name to identify the window as a vimExplorer window (the name could be shown in the status bar doing split vimExplorer but then a enew after it would remove the name, and without enew only two or more vimExplorer window would display the same content at the same time, being refreshed at the same time) cal append(0, 'vimExplorer') " Show path at the top of the buffer cal append(1, 'Path: ' . g:VePath) " Show the history bar cal append(2, 'History: ' . g:CfgGetItem(g:VeCfg, 'history')) " Show the current sort order cal append(3, 'Sorted by: ' . g:VeSortLabel) " Find the column number where the file names start {{{ " Get the column position where the file name starts " UnixUtils " -rw-rw-rw- 1 user group 43420 Nov 14 12:03 calendar.vim " -rw-rw-rw- 1 user group 1384 Jan 24 2012 getscriptPlugin.vim " Cygwin " -rw-r--r-- 1 User None 40960 Dec 7 14:46 vimExplorer.vim " -rw-r--r-- 1 User None 1969 Sep 14 2011 gzip.vim " Go to first directory or first file exe 'norm gg' . s:DirectoryListLineNum . 'j' " Regex to find the filename column number (searching for .. could work only with unixutils ls, when on root dir c:\ for example, . and .. are not displayed) try " Keep previous search register let tmpReg = @/ " When a filter is used, then the file names become full paths, so 2 regex are needed, one to match when there is a filter, and another when there a filter is not used " No filter used " -rw-r--r-- 1 User None 40960 Dec 7 14:46 vimExplorer.vim " Test from here ------------^ until here -^ if g:VeFilter == '' let @/ = '[0-9]\s\w\{3\}\s\(\s\|[0-9]\)[0-9]\s\([0-9][0-9]:[0-9][0-9]\|\s[0-9]\{4\}\)\s\zs.*' " A filter is used " -rwxr-xr-x 1 User None 536064 Feb 3 2009 C:/Usb/z_white/Apps/Portable/CmdUtils/7z.exe "^----- Test from here until here -------------------------------------------------^ else let @/ = '^.*\/\zs.*$' endif silent norm n " Set back search register let @/ = tmpReg catch " If no files then error, try-catch block is here not to show the error message endtry " The column number where the file name starts let s:FileNameColNum = col('.') " retu to previous position (2 times , first time returns to gg position) exe "norm \" exe "norm \" "}}} " Go to first directory or first file exe 'norm gg' . s:DirectoryListLineNum . 'j' " Find remembered cursor line position in that directory and position the cursor there let fileName = g:CfgSectionGetItem(g:VeCfg, 'cursorPos', g:VePath) if fileName != '' cal search('\s' . fileName . '$') normal l endif " Set colors on specific items in the window {{{ " The color constants are defined in the selected colorscheme. " Plugin name cal matchadd('Constant', '^vimExplorer$') " Path cal matchadd('Todo', '^Path: \zs.\{-}\ze$') " Path label cal matchadd('Constant', '^Path:') " History label cal matchadd('Constant', '^History:') " History paths cal matchadd('htmlLink', '\[\zs.\{-}\ze\]') " Sort order label cal matchadd('Constant', '^Sorted by:') " Sort order cal matchadd('Comment', '^Sorted by: \zs.\{-}\ze$') " Directories cal matchadd('Directory', '^d.*$') " Some files colors cal matchadd('Number', '^.\{-}.\(exe\|EXE\)$') cal matchadd('Statement', '^.\{-}.\(txt\|TXT\)$') "}}} " Reinitialize the recursive option let g:VeRecursive = '' " Append debug info at the end of buffer cal append(line('$'), g:Debug) endfu " g:VeOpenItem(vSplit) {{{2 " Open the selected item fu! g:VeOpenItem(vSplit) " Get the type of the current item {{{3 " Get the line to check for patterns let line = getline(line('.')) " Variables used to check for a link let start = 0 let end = 0 " Check for directory pattern {{{4 " Example: 'drwxrwxrwx ' if line =~ '^d.\{9}\s\s' let itemType = 'd' " Check for file pattern {{{4 " Example: '-rwxrwxrwx ' elseif line =~ '^-.\{9}\s\s' let itemType = 'f' " Check for a grep result pattern {{{4 " Example: 'C:/vim/vim73/plugin/dbext.vim:66:command! -range -nargs=0 DBExecRangeSQL ,call dbext#DB_execRangeSql()' elseif line =~ '^.*\/.\{-}:[0-9]\+:.*$' let itemType = 'g' " Check for a link {{{4 " Example of links are the history bar at the top of the buffer, it contains the visited paths each one enclosed in []. These links could be elsewhere. " Example: ' [C:/Temp] [C:/vim/vim73/plugin]' elseif line =~ '\s\[.\{-}/.\{-}]' " Save cursor postion let previous = col('.') " Search for start "[" and end "]" of path call search('[', 'b') let start = col('.') call search(']', '') let end = col('.') " Return to previous column (position) exe 'norm ' . previous . '|' if start != 0 && end != 0 let itemType = 'l' endif " Item type undefined else let itemType = '' endif " Do actions according to the item type {{{3 " Item is not undefined {{{4 if itemType == '' " Simply load or reload with current path cal g:VeLs() " Item is a directory or a file {{{4 elseif itemType == 'd' || itemType == 'f' let fileName = s:GetFileName() " Attempt to get the current subdirectory path of a recursive listing that is displayed when the -R option is used let path = s:GetRecursivePath() " If a path is found if path != '' " Set g:VePath to the current subdirectory path of the recursive listing let g:VePath = path endif " Item is a directory {{{5 if itemType == 'd' " Go to the directory cal g:VeDirectoryGoto(g:VePath . '/' . fileName) " Item is a file open the file {{{5 elseif itemType == 'f' if a:vSplit == 1 exe 'vsplit ' g:VePath . '/' . fileName else exe 'split ' g:VePath . '/' . fileName endif endif " Item is a grep result {{{4 elseif itemType == 'g' " Get the file path from the line let path = matchstr(line, '^\zs.*\/.\{-}\ze:[0-9]\+:.*$') " Get the line number from the line let lineNum = matchstr(line, '^.*\/.\{-}:\zs[0-9]\+\ze:.*$') " Open the file to the line number where the match was found exe 'split +' . lineNum . ' ' . path " Item is a link {{{4 elseif itemType == 'l' let path = strpart(line, start, abs(end - start) - 1) " Check if path exists if isdirectory(path) == 1 " Go to the directory cal g:VeDirectoryGoto(path) endif endif endfu " g:VeDirectoryGoto(path) {{{2 " Go to specified directory fu! g:VeDirectoryGoto(path) " Remember cursor line (name) position in that directory {{{ let fileName = s:GetFileName() if fileName != '' cal g:CfgSectionSetItem(g:VeCfg, 'cursorPos', g:VePath, fileName) endif "}}} " Change directory cal s:ChangeDirectory(a:path) " Add the path to the browsing history {{{ " The paths are appended in the reverse order so the newest paths appear first in the list let tmp = '[' . g:VePath . ']' . ' ' . g:CfgGetItem(g:VeCfg, 'history') " Check if history dosen't become too much long if len(tmp) > s:HistoryMaxLength " If history is more long than max length allowed, then empty it and put the last path inside let history = '[' . g:VePath . ']' else " If history not too long, then add the last path let history = tmp endif "}}} " Add history to configuration dictionnary cal g:CfgSetItem(g:VeCfg, 'history', history) " List the directory cal g:VeLs() endfu " Functions: Directory marks {{{1 " g:VeMarkPath(mark) {{{2 " Mark the current directory with the specified mark, keep the directory in memory fu! g:VeMarkPath(mark) cal g:CfgSectionSetItem(g:VeCfg, 'marks', a:mark, g:VePath) endfu " g:VeGotoMark(mark) {{{2 " Change directory according to the path for specified mark fu! g:VeGotoMark(mark) let path = g:CfgSectionGetItem(g:VeCfg, 'marks', a:mark) if path != '' " Go to the directory cal g:VeDirectoryGoto(path) endif endfu " g:VeShowMarks(sortByPath) {{{2 " Show all marked directories " Listing may be shown sorted by marks or by path fu! g:VeShowMarks(sortByPath) let marks = g:CfgGetSection(g:VeCfg, 'marks') if !empty(marks) if a:sortByPath == 0 for key in sort(keys(marks)) echo key . ' = ' . marks[key] endfor else " a:sortByPath == 1 let sortList = [] " Put vals and keys to a list for sorting, because in a dictionary its impossible it seems to sort with both key AND val at the same time for [key, val] in items(marks) call add(sortList, val . ' = ' . key) endfor " Echo the sorted list for val in sort(sortList) echo val endfor endif let m = input("Enter mark:" ) if m != '' exe "cal g:VeGotoMark('" . m . "')" endif endif endfu " Functions: Configuration {{{1 " g:VeLoadFromFile() {{{2 " Load configuration from file fu! g:VeLoadFromFile(restoreLastPath) " Load the configuration from a file let g:VeCfg = g:CfgLoadFromFile(g:VeCfgFile) " The last path is only restore when the plugin is loaded with vim, not when the user load it using the mapping if a:restoreLastPath == 1 " Restore the last accessed path, do VE to start the plugin using this path let g:VePath = g:CfgGetItem(g:VeCfg, 'lastPath') endif echo 'Configuration loaded from: ' . g:VeCfgFile endfu " g:VeSaveToFile() {{{2 " Save configuration to file fu! g:VeSaveToFile() " Add last accessed path so next time VE will open on that path cal g:CfgSetItem(g:VeCfg, 'lastPath', g:VePath) " Save the configuration to a file cal g:CfgSaveToFile(g:VeCfg, g:VeCfgFile) echo 'Configuration saved to: ' . g:VeCfgFile endfu " Functions: Configuration Utility: Persistance {{{1 " g:CfgLoadFromFile(file) {{{2 " Load a configuration from file (.vim file) fu! g:CfgLoadFromFile(file) if filereadable(a:file) try exe "source " . a:file let cfg = deepcopy(g:Cfg) catch let cfg = {} finally unlet! g:Cfg " Free memory return cfg endtry else return {} endif endfu " g:CfgSaveToFile(cfg, file) {{{2 " Save a dictionnary to file (.vim file) fu! g:CfgSaveToFile(cfg, file) let file = substitute(a:file, '/', '\', 'g') let file = substitute(file, '\', '\\', 'g') " Echo the configuration dictionary to file exe "redir! > " . file silent echo a:cfg redir END " Read the file back to a variable let cfg = readfile(file) " Add the global g:Cfg variable name let cfg[1] = 'let g:Cfg = ' . cfg[1] " Make the config file multiline " NOTE: \n dosen't seem to work, when the file is reloaded the data is not accessible from the dictionnary "let cfg[1] = substitute(cfg[1], ',', '\n\,', 'g') "let cfg[1] = substitute(cfg[1], '{', '\n\', 'g') " Add comment to the config file let cfg[0] = '" Configuration file used by vim "configFile.vim" plugin. "g:Cfg" is a global dictionary that is used to load and save configurations from files.' cal writefile(cfg, file, 'b') endfu " Functions: Configuration Utility: Item {{{1 " g:CfgGetItem(dict, itemKey) {{{2 " Get an item value fu! g:CfgGetItem(dict, itemKey) if has_key(a:dict, a:itemKey) return a:dict[a:itemKey] else return '' endif endfu " g:CfgSetItem(dict, itemKey, itemValue) {{{2 " Set a value to a item fu! g:CfgSetItem(dict, itemKey, itemValue) let itemValue = a:itemValue " Double ' if any because values are delimited by '' if stridx(a:itemValue, "'") != -1 let itemValue = substitute(itemValue, "'", "''", "g") endif cal extend(a:dict, {a:itemKey : a:itemValue}, 'force')" endfu " Functions: Configuration Utility: Section {{{1 " g:CfgGetSection(dict, sectionKey) {{{2 " Get a entire section fu! g:CfgGetSection(dict, sectionKey) if has_key(a:dict, a:sectionKey) return a:dict[a:sectionKey] else return {} endif endfu " g:CfgSectionGetItem(dict, sectionKey, itemKey) {{{2 " Get a value from a section fu! g:CfgSectionGetItem(dict, sectionKey, itemKey) if !has_key(a:dict, a:sectionKey) return '' endif if !has_key(a:dict[a:sectionKey], a:itemKey) return '' endif let section = a:dict[a:sectionKey] return section[a:itemKey] endfu " g:CfgSectionSetItem(dict, sectionKey, itemKey, itemValue) {{{2 " Set a value to a section fu! g:CfgSectionSetItem(dict, sectionKey, itemKey, itemValue) " Add the section if it dosen't exist if !has_key(a:dict, a:sectionKey) cal extend(a:dict, {a:sectionKey : {}}, 'force')" endif " Get the section let section = a:dict[a:sectionKey] " Set the section item cal extend(section, {a:itemKey : a:itemValue}, 'force')" " Set the section cal extend(a:dict, {a:sectionKey : section}, 'force')" endfu " Menu {{{1 " " "