GetLatestVimScripts
git-svn-id: https://vimsuite.svn.sourceforge.net/svnroot/vimsuite/trunk@204 eb2d0018-73a3-4aeb-bfe9-1def61c9ec69
This commit is contained in:
parent
ff1b9f62c7
commit
3da9a9e4ac
@ -7,14 +7,14 @@ ScriptID SourceID Filename
|
|||||||
670 8073 visincr.vim (Visual Increment)
|
670 8073 visincr.vim (Visual Increment)
|
||||||
862 2635 cscope_quickfix.vim
|
862 2635 cscope_quickfix.vim
|
||||||
51 171 cscope_macros.vim
|
51 171 cscope_macros.vim
|
||||||
102 13435 DirDiff.vim
|
102 16171 DirDiff.vim
|
||||||
1189 8687 matrix.vim
|
1189 8687 matrix.vim
|
||||||
1173 15731 tcomment
|
1173 15731 tcomment
|
||||||
948 2878 Scons Compiler plugin
|
948 2878 Scons Compiler plugin
|
||||||
1709 6421 Scons Syntax file
|
1709 6421 Scons Syntax file
|
||||||
1772 7248 DAMOS.zip DAMOS tools (von Stefan)
|
1772 7248 DAMOS.zip DAMOS tools (von Stefan)
|
||||||
987 14064 DoxygenToolkit.vim
|
987 14064 DoxygenToolkit.vim
|
||||||
1397 14039 xml.vim
|
1397 16076 xml.vim
|
||||||
1290 5190 LogiPat.vim
|
1290 5190 LogiPat.vim
|
||||||
1462 5612 dtd2xml
|
1462 5612 dtd2xml
|
||||||
1046 4249 Lusty Explorer
|
1046 4249 Lusty Explorer
|
||||||
@ -30,7 +30,7 @@ ScriptID SourceID Filename
|
|||||||
1173 15731 tComment.vim
|
1173 15731 tComment.vim
|
||||||
2701 13194 editsrec
|
2701 13194 editsrec
|
||||||
3280 14334 Tabbi
|
3280 14334 Tabbi
|
||||||
642 8136 :AutoInstall: getscript.vim
|
642 15781 :AutoInstall: getscript.vim
|
||||||
1075 15352 :AutoInstall: netrw.vim
|
1075 15782 :AutoInstall: netrw.vim
|
||||||
1502 15362 :AutoInstall: vimball.vim
|
1502 15362 :AutoInstall: vimball.vim
|
||||||
3304 15211 Gundo
|
3304 16172 Gundo
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
" ---------------------------------------------------------------------
|
" ---------------------------------------------------------------------
|
||||||
" getscript.vim
|
" getscript.vim
|
||||||
" Author: Charles E. Campbell, Jr.
|
" Author: Charles E. Campbell, Jr.
|
||||||
" Date: Jan 08, 2008
|
" Date: May 31, 2011
|
||||||
" Version: 29
|
" Version: 33
|
||||||
" Installing: :help glvs-install
|
" Installing: :help glvs-install
|
||||||
" Usage: :help glvs
|
" Usage: :help glvs
|
||||||
"
|
"
|
||||||
@ -12,19 +12,24 @@
|
|||||||
" Initialization: {{{1
|
" Initialization: {{{1
|
||||||
" if you're sourcing this file, surely you can't be
|
" if you're sourcing this file, surely you can't be
|
||||||
" expecting vim to be in its vi-compatible mode!
|
" expecting vim to be in its vi-compatible mode!
|
||||||
|
if exists("g:loaded_getscript")
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
let g:loaded_getscript= "v33"
|
||||||
if &cp
|
if &cp
|
||||||
echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)"
|
echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)"
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
if v:version < 702
|
||||||
|
echohl WarningMsg
|
||||||
|
echo "***warning*** this version of getscript needs vim 7.2"
|
||||||
|
echohl Normal
|
||||||
|
finish
|
||||||
|
endif
|
||||||
let s:keepcpo = &cpo
|
let s:keepcpo = &cpo
|
||||||
set cpo&vim
|
set cpo&vim
|
||||||
"DechoTabOn
|
"DechoTabOn
|
||||||
|
|
||||||
if exists("g:loaded_getscript")
|
|
||||||
finish
|
|
||||||
endif
|
|
||||||
let g:loaded_getscript= "v29"
|
|
||||||
|
|
||||||
" ---------------------------
|
" ---------------------------
|
||||||
" Global Variables: {{{1
|
" Global Variables: {{{1
|
||||||
" ---------------------------
|
" ---------------------------
|
||||||
@ -40,25 +45,6 @@ if !exists("g:getscript_cygwin")
|
|||||||
let g:getscript_cygwin= 0
|
let g:getscript_cygwin= 0
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
" shell quoting character {{{2
|
|
||||||
if exists("g:netrw_shq") && !exists("g:getscript_shq")
|
|
||||||
let g:getscript_shq= g:netrw_shq
|
|
||||||
elseif !exists("g:getscript_shq")
|
|
||||||
if exists("&shq") && &shq != ""
|
|
||||||
let g:getscript_shq= &shq
|
|
||||||
elseif exists("&sxq") && &sxq != ""
|
|
||||||
let g:getscript_shq= &sxq
|
|
||||||
elseif has("win32") || has("win95") || has("win64") || has("win16")
|
|
||||||
if g:getscript_cygwin
|
|
||||||
let g:getscript_shq= "'"
|
|
||||||
else
|
|
||||||
let g:getscript_shq= '"'
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
let g:getscript_shq= "'"
|
|
||||||
endif
|
|
||||||
" call Decho("g:getscript_shq<".g:getscript_shq.">")
|
|
||||||
endif
|
|
||||||
|
|
||||||
" wget vs curl {{{2
|
" wget vs curl {{{2
|
||||||
if !exists("g:GetLatestVimScripts_wget")
|
if !exists("g:GetLatestVimScripts_wget")
|
||||||
@ -112,7 +98,9 @@ if g:GetLatestVimScripts_allowautoinstall
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim)
|
if exists("g:GetLatestVimScripts_autoinstalldir") && isdirectory(g:GetLatestVimScripts_autoinstalldir)
|
||||||
|
let s:autoinstall= g:GetLatestVimScripts_autoinstalldir"
|
||||||
|
elseif exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim)
|
||||||
let s:autoinstall= $HOME."/".s:dotvim
|
let s:autoinstall= $HOME."/".s:dotvim
|
||||||
endif
|
endif
|
||||||
" call Decho("s:autoinstall<".s:autoinstall.">")
|
" call Decho("s:autoinstall<".s:autoinstall.">")
|
||||||
@ -126,11 +114,223 @@ com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts()
|
|||||||
com! -nargs=0 GetScript call getscript#GetLatestVimScripts()
|
com! -nargs=0 GetScript call getscript#GetLatestVimScripts()
|
||||||
silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts()
|
silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts()
|
||||||
|
|
||||||
|
" ---------------------------------------------------------------------
|
||||||
|
" GetLatestVimScripts: this function gets the latest versions of {{{1
|
||||||
|
" scripts based on the list in
|
||||||
|
" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat
|
||||||
|
fun! getscript#GetLatestVimScripts()
|
||||||
|
" call Dfunc("GetLatestVimScripts() autoinstall<".s:autoinstall.">")
|
||||||
|
|
||||||
|
" insure that wget is executable
|
||||||
|
if executable(g:GetLatestVimScripts_wget) != 1
|
||||||
|
echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system"
|
||||||
|
" call Dret("GetLatestVimScripts : wget not executable/availble")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" insure that fnameescape() is available
|
||||||
|
if !exists("*fnameescape")
|
||||||
|
echoerr "GetLatestVimScripts needs fnameescape() (provided by 7.1.299 or later)"
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Find the .../GetLatest subdirectory under the runtimepath
|
||||||
|
for datadir in split(&rtp,',') + ['']
|
||||||
|
if isdirectory(datadir."/GetLatest")
|
||||||
|
" call Decho("found directory<".datadir.">")
|
||||||
|
let datadir= datadir . "/GetLatest"
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
if filereadable(datadir."GetLatestVimScripts.dat")
|
||||||
|
" call Decho("found ".datadir."/GetLatestVimScripts.dat")
|
||||||
|
break
|
||||||
|
endif
|
||||||
|
endfor
|
||||||
|
|
||||||
|
" Sanity checks: readability and writability
|
||||||
|
if datadir == ""
|
||||||
|
echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install'
|
||||||
|
" call Dret("GetLatestVimScripts : unable to find a GetLatest subdirectory")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if filewritable(datadir) != 2
|
||||||
|
echoerr "(getLatestVimScripts) Your ".datadir." isn't writable"
|
||||||
|
" call Dret("GetLatestVimScripts : non-writable directory<".datadir.">")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let datafile= datadir."/GetLatestVimScripts.dat"
|
||||||
|
if !filereadable(datafile)
|
||||||
|
echoerr "Your data file<".datafile."> isn't readable"
|
||||||
|
" call Dret("GetLatestVimScripts : non-readable datafile<".datafile.">")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
if !filewritable(datafile)
|
||||||
|
echoerr "Your data file<".datafile."> isn't writable"
|
||||||
|
" call Dret("GetLatestVimScripts : non-writable datafile<".datafile.">")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
" --------------------
|
||||||
|
" Passed sanity checks
|
||||||
|
" --------------------
|
||||||
|
|
||||||
|
" call Decho("datadir <".datadir.">")
|
||||||
|
" call Decho("datafile <".datafile.">")
|
||||||
|
|
||||||
|
" don't let any event handlers interfere (like winmanager's, taglist's, etc)
|
||||||
|
let eikeep = &ei
|
||||||
|
let hlskeep = &hls
|
||||||
|
let acdkeep = &acd
|
||||||
|
set ei=all hls&vim noacd
|
||||||
|
|
||||||
|
" Edit the datafile (ie. GetLatestVimScripts.dat):
|
||||||
|
" 1. record current directory (origdir),
|
||||||
|
" 2. change directory to datadir,
|
||||||
|
" 3. split window
|
||||||
|
" 4. edit datafile
|
||||||
|
let origdir= getcwd()
|
||||||
|
" call Decho("exe cd ".fnameescape(substitute(datadir,'\','/','ge')))
|
||||||
|
exe "cd ".fnameescape(substitute(datadir,'\','/','ge'))
|
||||||
|
split
|
||||||
|
" call Decho("exe e ".fnameescape(substitute(datafile,'\','/','ge')))
|
||||||
|
exe "e ".fnameescape(substitute(datafile,'\','/','ge'))
|
||||||
|
res 1000
|
||||||
|
let s:downloads = 0
|
||||||
|
let s:downerrors= 0
|
||||||
|
|
||||||
|
" Check on dependencies mentioned in plugins
|
||||||
|
" call Decho(" ")
|
||||||
|
" call Decho("searching plugins for GetLatestVimScripts dependencies")
|
||||||
|
let lastline = line("$")
|
||||||
|
" call Decho("lastline#".lastline)
|
||||||
|
let firstdir = substitute(&rtp,',.*$','','')
|
||||||
|
let plugins = split(globpath(firstdir,"plugin/*.vim"),'\n')
|
||||||
|
let plugins = plugins + split(globpath(firstdir,"AsNeeded/*.vim"),'\n')
|
||||||
|
let foundscript = 0
|
||||||
|
|
||||||
|
" this loop updates the GetLatestVimScripts.dat file
|
||||||
|
" with dependencies explicitly mentioned in the plugins
|
||||||
|
" via GetLatestVimScripts: ... lines
|
||||||
|
" It reads the plugin script at the end of the GetLatestVimScripts.dat
|
||||||
|
" file, examines it, and then removes it.
|
||||||
|
for plugin in plugins
|
||||||
|
" call Decho(" ")
|
||||||
|
" call Decho("plugin<".plugin.">")
|
||||||
|
|
||||||
|
" read plugin in
|
||||||
|
" evidently a :r creates a new buffer (the "#" buffer) that is subsequently unused -- bwiping it
|
||||||
|
$
|
||||||
|
" call Decho(".dependency checking<".plugin."> line$=".line("$"))
|
||||||
|
" call Decho("..exe silent r ".fnameescape(plugin))
|
||||||
|
exe "silent r ".fnameescape(plugin)
|
||||||
|
exe "silent bwipe ".bufnr("#")
|
||||||
|
|
||||||
|
while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0
|
||||||
|
let depscript = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e')
|
||||||
|
let depscriptid = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\(\d\+\)\s\+.*$','\1','')
|
||||||
|
let llp1 = lastline+1
|
||||||
|
" call Decho("..depscript<".depscript.">")
|
||||||
|
|
||||||
|
" found a "GetLatestVimScripts: # #" line in the script;
|
||||||
|
" check if its already in the datafile by searching backwards from llp1,
|
||||||
|
" the (prior to reading in the plugin script) last line plus one of the GetLatestVimScripts.dat file,
|
||||||
|
" for the script-id with no wrapping allowed.
|
||||||
|
let curline = line(".")
|
||||||
|
let noai_script = substitute(depscript,'\s*:AutoInstall:\s*','','e')
|
||||||
|
exe llp1
|
||||||
|
let srchline = search('^\s*'.depscriptid.'\s\+\d\+\s\+.*$','bW')
|
||||||
|
if srchline == 0
|
||||||
|
" this second search is taken when, for example, a 0 0 scriptname is to be skipped over
|
||||||
|
let srchline= search('\<'.noai_script.'\>','bW')
|
||||||
|
endif
|
||||||
|
" call Decho("..noai_script<".noai_script."> depscriptid#".depscriptid." srchline#".srchline." curline#".line(".")." lastline#".lastline)
|
||||||
|
|
||||||
|
if srchline == 0
|
||||||
|
" found a new script to permanently include in the datafile
|
||||||
|
let keep_rega = @a
|
||||||
|
let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','')
|
||||||
|
echomsg "Appending <".@a."> to ".datafile." for ".depscript
|
||||||
|
" call Decho("..Appending <".@a."> to ".datafile." for ".depscript)
|
||||||
|
exe lastline."put a"
|
||||||
|
let @a = keep_rega
|
||||||
|
let lastline = llp1
|
||||||
|
let curline = curline + 1
|
||||||
|
let foundscript = foundscript + 1
|
||||||
|
" else " Decho
|
||||||
|
" call Decho("..found <".noai_script."> (already in datafile at line#".srchline.")")
|
||||||
|
endif
|
||||||
|
|
||||||
|
let curline = curline + 1
|
||||||
|
exe curline
|
||||||
|
endwhile
|
||||||
|
|
||||||
|
" llp1: last line plus one
|
||||||
|
let llp1= lastline + 1
|
||||||
|
" call Decho(".deleting lines: ".llp1.",$d")
|
||||||
|
exe "silent! ".llp1.",$d"
|
||||||
|
endfor
|
||||||
|
" call Decho("--- end dependency checking loop --- foundscript=".foundscript)
|
||||||
|
" call Decho(" ")
|
||||||
|
" call Dredir("BUFFER TEST (GetLatestVimScripts 1)","ls!")
|
||||||
|
|
||||||
|
if foundscript == 0
|
||||||
|
setlocal nomod
|
||||||
|
endif
|
||||||
|
|
||||||
|
" --------------------------------------------------------------------
|
||||||
|
" Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat
|
||||||
|
" --------------------------------------------------------------------
|
||||||
|
" call Decho("begin: checking out-of-date scripts using datafile<".datafile.">")
|
||||||
|
setlocal lz
|
||||||
|
1
|
||||||
|
" /^-----/,$g/^\s*\d/call Decho(getline("."))
|
||||||
|
1
|
||||||
|
/^-----/,$g/^\s*\d/call s:GetOneScript()
|
||||||
|
" call Decho("--- end out-of-date checking --- ")
|
||||||
|
|
||||||
|
" Final report (an echomsg)
|
||||||
|
try
|
||||||
|
silent! ?^-------?
|
||||||
|
catch /^Vim\%((\a\+)\)\=:E114/
|
||||||
|
" call Dret("GetLatestVimScripts : nothing done!")
|
||||||
|
return
|
||||||
|
endtry
|
||||||
|
exe "norm! kz\<CR>"
|
||||||
|
redraw!
|
||||||
|
let s:msg = ""
|
||||||
|
if s:downloads == 1
|
||||||
|
let s:msg = "Downloaded one updated script to <".datadir.">"
|
||||||
|
elseif s:downloads == 2
|
||||||
|
let s:msg= "Downloaded two updated scripts to <".datadir.">"
|
||||||
|
elseif s:downloads > 1
|
||||||
|
let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">"
|
||||||
|
else
|
||||||
|
let s:msg= "Everything was already current"
|
||||||
|
endif
|
||||||
|
if s:downerrors > 0
|
||||||
|
let s:msg= s:msg." (".s:downerrors." downloading errors)"
|
||||||
|
endif
|
||||||
|
echomsg s:msg
|
||||||
|
" save the file
|
||||||
|
if &mod
|
||||||
|
silent! w!
|
||||||
|
endif
|
||||||
|
q
|
||||||
|
|
||||||
|
" restore events and current directory
|
||||||
|
exe "cd ".fnameescape(substitute(origdir,'\','/','ge'))
|
||||||
|
let &ei = eikeep
|
||||||
|
let &hls = hlskeep
|
||||||
|
let &acd = acdkeep
|
||||||
|
setlocal nolz
|
||||||
|
" call Dredir("BUFFER TEST (GetLatestVimScripts 2)","ls!")
|
||||||
|
" call Dret("GetLatestVimScripts : did ".s:downloads." downloads")
|
||||||
|
endfun
|
||||||
|
|
||||||
" ---------------------------------------------------------------------
|
" ---------------------------------------------------------------------
|
||||||
" GetOneScript: (Get Latest Vim Script) this function operates {{{1
|
" GetOneScript: (Get Latest Vim Script) this function operates {{{1
|
||||||
" on the current line, interpreting two numbers and text as
|
" on the current line, interpreting two numbers and text as
|
||||||
" ScriptID, SourceID, and Filename.
|
" ScriptID, SourceID, and Filename.
|
||||||
" It downloads any scripts that have newer versions from vim.sf.net.
|
" It downloads any scripts that have newer versions from vim.sourceforge.net.
|
||||||
fun! s:GetOneScript(...)
|
fun! s:GetOneScript(...)
|
||||||
" call Dfunc("GetOneScript()")
|
" call Dfunc("GetOneScript()")
|
||||||
|
|
||||||
@ -188,6 +388,7 @@ fun! s:GetOneScript(...)
|
|||||||
" call Decho("fname <".fname.">")
|
" call Decho("fname <".fname.">")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" plugin author protection from downloading his/her own scripts atop their latest work
|
||||||
if scriptid == 0 || srcid == 0
|
if scriptid == 0 || srcid == 0
|
||||||
" When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname
|
" When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname
|
||||||
let @a= rega
|
let @a= rega
|
||||||
@ -211,29 +412,30 @@ fun! s:GetOneScript(...)
|
|||||||
exe "norm z\<CR>"
|
exe "norm z\<CR>"
|
||||||
redraw!
|
redraw!
|
||||||
" call Decho('considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid)
|
" call Decho('considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid)
|
||||||
echomsg 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid
|
echo 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid
|
||||||
|
|
||||||
" grab a copy of the plugin's vim.sf.net webpage
|
" grab a copy of the plugin's vim.sourceforge.net webpage
|
||||||
let scriptaddr = 'http://vim.sf.net/script.php?script_id='.scriptid
|
let scriptaddr = 'http://vim.sourceforge.net/script.php?script_id='.scriptid
|
||||||
let tmpfile = tempname()
|
let tmpfile = tempname()
|
||||||
let v:errmsg = ""
|
let v:errmsg = ""
|
||||||
|
|
||||||
" make up to three tries at downloading the description
|
" make up to three tries at downloading the description
|
||||||
let itry= 1
|
let itry= 1
|
||||||
while itry <= 3
|
while itry <= 3
|
||||||
" call Decho("try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr)
|
" call Decho(".try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr)
|
||||||
if has("win32") || has("win16") || has("win95")
|
if has("win32") || has("win16") || has("win95")
|
||||||
" call Decho("new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq.' '.g:getscript_shq.scriptaddr.g:getscript_shq."|q!")
|
" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile).' '.shellescape(scriptaddr)."|bw!")
|
||||||
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq.' '.g:getscript_shq.scriptaddr.g:getscript_shq|q!
|
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile).' '.shellescape(scriptaddr)|bw!
|
||||||
else
|
else
|
||||||
" call Decho("exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq." ".g:getscript_shq.scriptaddr.g:getscript_shq)
|
" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr))
|
||||||
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq." ".g:getscript_shq.scriptaddr.g:getscript_shq
|
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr)
|
||||||
endif
|
endif
|
||||||
if itry == 1
|
if itry == 1
|
||||||
exe "silent vsplit ".tmpfile
|
exe "silent vsplit ".fnameescape(tmpfile)
|
||||||
else
|
else
|
||||||
silent! e %
|
silent! e %
|
||||||
endif
|
endif
|
||||||
|
setlocal bh=wipe
|
||||||
|
|
||||||
" find the latest source-id in the plugin's webpage
|
" find the latest source-id in the plugin's webpage
|
||||||
silent! 1
|
silent! 1
|
||||||
@ -291,8 +493,7 @@ fun! s:GetOneScript(...)
|
|||||||
let latestsrcid = latestsrcid + 0
|
let latestsrcid = latestsrcid + 0
|
||||||
" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">")
|
" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">")
|
||||||
|
|
||||||
" has the plugin's most-recent srcid increased, which indicates
|
" has the plugin's most-recent srcid increased, which indicates that it has been updated
|
||||||
" that it has been updated
|
|
||||||
if latestsrcid > srcid
|
if latestsrcid > srcid
|
||||||
" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">")
|
" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">")
|
||||||
|
|
||||||
@ -302,72 +503,116 @@ fun! s:GetOneScript(...)
|
|||||||
let sname= "NEW_".sname
|
let sname= "NEW_".sname
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" -----------------------------------------------------------------------------
|
||||||
" the plugin has been updated since we last obtained it, so download a new copy
|
" the plugin has been updated since we last obtained it, so download a new copy
|
||||||
" call Decho("...downloading new <".sname.">")
|
" -----------------------------------------------------------------------------
|
||||||
echomsg "...downloading new <".sname.">"
|
" call Decho(".downloading new <".sname.">")
|
||||||
|
echomsg ".downloading new <".sname.">"
|
||||||
if has("win32") || has("win16") || has("win95")
|
if has("win32") || has("win16") || has("win95")
|
||||||
" call Decho("new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq."|q")
|
" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='.latestsrcid)."|q")
|
||||||
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq|q
|
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='.latestsrcid)|q
|
||||||
else
|
else
|
||||||
" call Decho("silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq)
|
" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='))
|
||||||
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.g:getscript_shq
|
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id=').latestsrcid
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" --------------------------------------------------------------------------
|
||||||
" AutoInstall: only if doautoinstall has been requested by the plugin itself
|
" AutoInstall: only if doautoinstall has been requested by the plugin itself
|
||||||
|
" --------------------------------------------------------------------------
|
||||||
|
" call Decho("checking if plugin requested autoinstall: doautoinstall=".doautoinstall)
|
||||||
if doautoinstall
|
if doautoinstall
|
||||||
" call Decho("attempting to do autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname))
|
" call Decho(" ")
|
||||||
|
" call Decho("Autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname))
|
||||||
if filereadable(sname)
|
if filereadable(sname)
|
||||||
" call Decho("silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.s:autoinstall.g:getscript_shq)
|
" call Decho("<".sname."> is readable")
|
||||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.s:autoinstall.g:getscript_shq
|
" call Decho("exe silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall))
|
||||||
let curdir = escape(substitute(getcwd(),'\','/','ge'),"|[]*'\" #")
|
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall)
|
||||||
|
let curdir = fnameescape(substitute(getcwd(),'\','/','ge'))
|
||||||
let installdir= curdir."/Installed"
|
let installdir= curdir."/Installed"
|
||||||
if !isdirectory(installdir)
|
if !isdirectory(installdir)
|
||||||
call mkdir(installdir)
|
call mkdir(installdir)
|
||||||
endif
|
endif
|
||||||
" call Decho("exe cd ".s:autoinstall)
|
" call Decho("curdir<".curdir."> installdir<".installdir.">")
|
||||||
exe "cd ".escape(s:autoinstall,' ')
|
" call Decho("exe cd ".fnameescape(s:autoinstall))
|
||||||
|
exe "cd ".fnameescape(s:autoinstall)
|
||||||
|
|
||||||
|
" determine target directory for moves
|
||||||
|
let firstdir= substitute(&rtp,',.*$','','')
|
||||||
|
let pname = substitute(sname,'\..*','.vim','')
|
||||||
|
" call Decho("determine tgtdir: is <".firstdir.'/AsNeeded/'.pname." readable?")
|
||||||
|
if filereadable(firstdir.'/AsNeeded/'.pname)
|
||||||
|
let tgtdir= "AsNeeded"
|
||||||
|
else
|
||||||
|
let tgtdir= "plugin"
|
||||||
|
endif
|
||||||
|
" call Decho("tgtdir<".tgtdir."> pname<".pname.">")
|
||||||
|
|
||||||
" decompress
|
" decompress
|
||||||
if sname =~ '\.bz2$'
|
if sname =~ '\.bz2$'
|
||||||
" call Decho("decompress: attempt to bunzip2 ".sname)
|
" call Decho("decompress: attempt to bunzip2 ".sname)
|
||||||
exe "silent !bunzip2 ".g:getscript_shq.sname.g:getscript_shq
|
exe "silent !bunzip2 ".shellescape(sname)
|
||||||
let sname= substitute(sname,'\.bz2$','','')
|
let sname= substitute(sname,'\.bz2$','','')
|
||||||
" call Decho("decompress: new sname<".sname."> after bunzip2")
|
" call Decho("decompress: new sname<".sname."> after bunzip2")
|
||||||
elseif sname =~ '\.gz$'
|
elseif sname =~ '\.gz$'
|
||||||
" call Decho("decompress: attempt to gunzip ".sname)
|
" call Decho("decompress: attempt to gunzip ".sname)
|
||||||
exe "silent !gunzip ".g:getscript_shq.sname.g:getscript_shq
|
exe "silent !gunzip ".shellescape(sname)
|
||||||
let sname= substitute(sname,'\.gz$','','')
|
let sname= substitute(sname,'\.gz$','','')
|
||||||
" call Decho("decompress: new sname<".sname."> after gunzip")
|
" call Decho("decompress: new sname<".sname."> after gunzip")
|
||||||
|
elseif sname =~ '\.xz$'
|
||||||
|
" call Decho("decompress: attempt to unxz ".sname)
|
||||||
|
exe "silent !unxz ".shellescape(sname)
|
||||||
|
let sname= substitute(sname,'\.xz$','','')
|
||||||
|
" call Decho("decompress: new sname<".sname."> after unxz")
|
||||||
|
else
|
||||||
|
" call Decho("no decompression needed")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" distribute archive(.zip, .tar, .vba) contents
|
" distribute archive(.zip, .tar, .vba) contents
|
||||||
if sname =~ '\.zip$'
|
if sname =~ '\.zip$'
|
||||||
" call Decho("dearchive: attempt to unzip ".sname)
|
" call Decho("dearchive: attempt to unzip ".sname)
|
||||||
exe "silent !unzip -o ".g:getscript_shq.sname.g:getscript_shq
|
exe "silent !unzip -o ".shellescape(sname)
|
||||||
elseif sname =~ '\.tar$'
|
elseif sname =~ '\.tar$'
|
||||||
" call Decho("dearchive: attempt to untar ".sname)
|
" call Decho("dearchive: attempt to untar ".sname)
|
||||||
exe "silent !tar -xvf ".g:getscript_shq.sname.g:getscript_shq
|
exe "silent !tar -xvf ".shellescape(sname)
|
||||||
elseif sname =~ '\.vba$'
|
elseif sname =~ '\.vba$'
|
||||||
" call Decho("dearchive: attempt to handle a vimball: ".sname)
|
" call Decho("dearchive: attempt to handle a vimball: ".sname)
|
||||||
silent 1split
|
silent 1split
|
||||||
exe "silent e ".escape(sname,' ')
|
if exists("g:vimball_home")
|
||||||
|
let oldvimballhome= g:vimball_home
|
||||||
|
endif
|
||||||
|
let g:vimball_home= s:autoinstall
|
||||||
|
exe "silent e ".fnameescape(sname)
|
||||||
silent so %
|
silent so %
|
||||||
silent q
|
silent q
|
||||||
|
if exists("oldvimballhome")
|
||||||
|
let g:vimball_home= oldvimballhome
|
||||||
|
else
|
||||||
|
unlet g:vimball_home
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
" call Decho("no dearchiving needed")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" ---------------------------------------------
|
||||||
|
" move plugin to plugin/ or AsNeeded/ directory
|
||||||
|
" ---------------------------------------------
|
||||||
if sname =~ '.vim$'
|
if sname =~ '.vim$'
|
||||||
" call Decho("dearchive: attempt to simply move ".sname." to plugin")
|
" call Decho("dearchive: attempt to simply move ".sname." to ".tgtdir)
|
||||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." plugin"
|
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".tgtdir
|
||||||
else
|
else
|
||||||
" call Decho("dearchive: move <".sname."> to installdir<".installdir.">")
|
" call Decho("dearchive: move <".sname."> to installdir<".installdir.">")
|
||||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".installdir
|
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".installdir
|
||||||
|
endif
|
||||||
|
if tgtdir != "plugin"
|
||||||
|
" call Decho("exe silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir)
|
||||||
|
exe "silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" helptags step
|
" helptags step
|
||||||
let docdir= substitute(&rtp,',.*','','e')."/doc"
|
let docdir= substitute(&rtp,',.*','','e')."/doc"
|
||||||
" call Decho("helptags: docdir<".docdir.">")
|
" call Decho("helptags: docdir<".docdir.">")
|
||||||
exe "helptags ".docdir
|
exe "helptags ".fnameescape(docdir)
|
||||||
exe "cd ".curdir
|
exe "cd ".fnameescape(curdir)
|
||||||
endif
|
endif
|
||||||
if fname !~ ':AutoInstall:'
|
if fname !~ ':AutoInstall:'
|
||||||
let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
|
let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
|
||||||
@ -390,197 +635,11 @@ fun! s:GetOneScript(...)
|
|||||||
let &t_te = t_te
|
let &t_te = t_te
|
||||||
let &rs = rs
|
let &rs = rs
|
||||||
let @a = rega
|
let @a = rega
|
||||||
|
" call Dredir("BUFFER TEST (GetOneScript)","ls!")
|
||||||
|
|
||||||
" call Dret("GetOneScript")
|
" call Dret("GetOneScript")
|
||||||
endfun
|
endfun
|
||||||
|
|
||||||
" ---------------------------------------------------------------------
|
|
||||||
" GetLatestVimScripts: this function gets the latest versions of {{{1
|
|
||||||
" scripts based on the list in
|
|
||||||
" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat
|
|
||||||
fun! getscript#GetLatestVimScripts()
|
|
||||||
" call Dfunc("GetLatestVimScripts() autoinstall<".s:autoinstall.">")
|
|
||||||
|
|
||||||
" insure that wget is executable
|
|
||||||
if executable(g:GetLatestVimScripts_wget) != 1
|
|
||||||
echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system"
|
|
||||||
" call Dret("GetLatestVimScripts : wget not executable/availble")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Find the .../GetLatest subdirectory under the runtimepath
|
|
||||||
for datadir in split(&rtp,',') + ['']
|
|
||||||
if isdirectory(datadir."/GetLatest")
|
|
||||||
" call Decho("found directory<".datadir.">")
|
|
||||||
let datadir= datadir . "/GetLatest"
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
if filereadable(datadir."GetLatestVimScripts.dat")
|
|
||||||
" call Decho("found ".datadir."/GetLatestVimScripts.dat")
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endfor
|
|
||||||
|
|
||||||
" Sanity checks: readability and writability
|
|
||||||
if datadir == ""
|
|
||||||
echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install'
|
|
||||||
" call Dret("GetLatestVimScripts : unable to find a GetLatest subdirectory")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
|
|
||||||
if filewritable(datadir) != 2
|
|
||||||
echoerr "(getLatestVimScripts) Your ".datadir." isn't writable"
|
|
||||||
" call Dret("GetLatestVimScripts : non-writable directory<".datadir.">")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
let datafile= datadir."/GetLatestVimScripts.dat"
|
|
||||||
if !filereadable(datafile)
|
|
||||||
echoerr "Your data file<".datafile."> isn't readable"
|
|
||||||
" call Dret("GetLatestVimScripts : non-readable datafile<".datafile.">")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
if !filewritable(datafile)
|
|
||||||
echoerr "Your data file<".datafile."> isn't writable"
|
|
||||||
" call Dret("GetLatestVimScripts : non-writable datafile<".datafile.">")
|
|
||||||
return
|
|
||||||
endif
|
|
||||||
" call Decho("datadir <".datadir.">")
|
|
||||||
" call Decho("datafile <".datafile.">")
|
|
||||||
|
|
||||||
" don't let any events interfere (like winmanager's, taglist's, etc)
|
|
||||||
let eikeep= &ei
|
|
||||||
set ei=all
|
|
||||||
|
|
||||||
" record current directory, change to datadir, open split window with
|
|
||||||
" datafile
|
|
||||||
let origdir= getcwd()
|
|
||||||
exe "cd ".escape(substitute(datadir,'\','/','ge'),"|[]*'\" #")
|
|
||||||
split
|
|
||||||
exe "e ".escape(substitute(datafile,'\','/','ge'),"|[]*'\" #")
|
|
||||||
res 1000
|
|
||||||
let s:downloads = 0
|
|
||||||
let s:downerrors= 0
|
|
||||||
|
|
||||||
" Check on dependencies mentioned in plugins
|
|
||||||
" call Decho(" ")
|
|
||||||
" call Decho("searching plugins for GetLatestVimScripts dependencies")
|
|
||||||
let lastline = line("$")
|
|
||||||
" call Decho("lastline#".lastline)
|
|
||||||
let plugins = split(globpath(&rtp,"plugin/*.vim"),'\n')
|
|
||||||
let foundscript = 0
|
|
||||||
let firstdir= ""
|
|
||||||
|
|
||||||
for plugin in plugins
|
|
||||||
|
|
||||||
" don't process plugins in system directories
|
|
||||||
if firstdir == ""
|
|
||||||
let firstdir= substitute(plugin,'[/\\][^/\\]\+$','','')
|
|
||||||
" call Decho("setting firstdir<".firstdir.">")
|
|
||||||
else
|
|
||||||
let curdir= substitute(plugin,'[/\\][^/\\]\+$','','')
|
|
||||||
" call Decho("curdir<".curdir.">")
|
|
||||||
if curdir != firstdir
|
|
||||||
" call Decho("skipping subsequent plugins: curdir<".curdir."> != firstdir<".firstdir.">")
|
|
||||||
break
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
|
|
||||||
" read plugin in
|
|
||||||
$
|
|
||||||
" call Decho(" ")
|
|
||||||
" call Decho(".dependency checking<".plugin."> line$=".line("$"))
|
|
||||||
exe "silent r ".escape(plugin,"[]#*$%'\" ?`!&();<>\\")
|
|
||||||
|
|
||||||
while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0
|
|
||||||
let newscript= substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e')
|
|
||||||
let llp1 = lastline+1
|
|
||||||
" call Decho("..newscript<".newscript.">")
|
|
||||||
|
|
||||||
" don't process ""GetLatestVimScripts lines -- those that have been doubly-commented out
|
|
||||||
if newscript !~ '^"'
|
|
||||||
" found a "GetLatestVimScripts: # #" line in the script; check if its already in the datafile
|
|
||||||
let curline = line(".")
|
|
||||||
let noai_script = substitute(newscript,'\s*:AutoInstall:\s*','','e')
|
|
||||||
exe llp1
|
|
||||||
let srchline = search('\<'.noai_script.'\>','bW')
|
|
||||||
" call Decho("..noai_script<".noai_script."> srch=".srchline."curline#".line(".")." lastline#".lastline)
|
|
||||||
|
|
||||||
if srchline == 0
|
|
||||||
" found a new script to permanently include in the datafile
|
|
||||||
let keep_rega = @a
|
|
||||||
let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','')
|
|
||||||
exe lastline."put a"
|
|
||||||
echomsg "Appending <".@a."> to ".datafile." for ".newscript
|
|
||||||
" call Decho("..APPEND (".noai_script.")<".@a."> to GetLatestVimScripts.dat")
|
|
||||||
let @a = keep_rega
|
|
||||||
let lastline = llp1
|
|
||||||
let curline = curline + 1
|
|
||||||
let foundscript = foundscript + 1
|
|
||||||
" else " Decho
|
|
||||||
" call Decho("..found <".noai_script."> (already in datafile at line#".srchline.")")
|
|
||||||
endif
|
|
||||||
|
|
||||||
let curline = curline + 1
|
|
||||||
exe curline
|
|
||||||
endif
|
|
||||||
endwhile
|
|
||||||
|
|
||||||
let llp1= lastline + 1
|
|
||||||
" call Decho(".deleting lines: ".llp1.",$d")
|
|
||||||
exe "silent! ".llp1.",$d"
|
|
||||||
endfor
|
|
||||||
" call Decho("--- end dependency checking loop --- foundscript=".foundscript)
|
|
||||||
" call Decho(" ")
|
|
||||||
|
|
||||||
if foundscript == 0
|
|
||||||
setlocal nomod
|
|
||||||
endif
|
|
||||||
|
|
||||||
" Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat
|
|
||||||
" call Decho("begin: checking out-of-date scripts using datafile<".datafile.">")
|
|
||||||
setlocal lz
|
|
||||||
1
|
|
||||||
" /^-----/,$g/^\s*\d/call Decho(getline("."))
|
|
||||||
1
|
|
||||||
/^-----/,$g/^\s*\d/call s:GetOneScript()
|
|
||||||
" call Decho("--- end out-of-date checking --- ")
|
|
||||||
|
|
||||||
" Final report (an echomsg)
|
|
||||||
try
|
|
||||||
silent! ?^-------?
|
|
||||||
catch /^Vim\%((\a\+)\)\=:E114/
|
|
||||||
" call Dret("GetLatestVimScripts : nothing done!")
|
|
||||||
return
|
|
||||||
endtry
|
|
||||||
exe "norm! kz\<CR>"
|
|
||||||
redraw!
|
|
||||||
let s:msg = ""
|
|
||||||
if s:downloads == 1
|
|
||||||
let s:msg = "Downloaded one updated script to <".datadir.">"
|
|
||||||
elseif s:downloads == 2
|
|
||||||
let s:msg= "Downloaded two updated scripts to <".datadir.">"
|
|
||||||
elseif s:downloads > 1
|
|
||||||
let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">"
|
|
||||||
else
|
|
||||||
let s:msg= "Everything was already current"
|
|
||||||
endif
|
|
||||||
if s:downerrors > 0
|
|
||||||
let s:msg= s:msg." (".s:downerrors." downloading errors)"
|
|
||||||
endif
|
|
||||||
echomsg s:msg
|
|
||||||
" save the file
|
|
||||||
if &mod
|
|
||||||
silent! w!
|
|
||||||
endif
|
|
||||||
q
|
|
||||||
|
|
||||||
" restore events and current directory
|
|
||||||
exe "cd ".escape(substitute(origdir,'\','/','ge'),"|[]*'\" #")
|
|
||||||
let &ei= eikeep
|
|
||||||
setlocal nolz
|
|
||||||
" call Dret("GetLatestVimScripts : did ".s:downloads." downloads")
|
|
||||||
endfun
|
|
||||||
|
|
||||||
" ---------------------------------------------------------------------
|
" ---------------------------------------------------------------------
|
||||||
" Restore Options: {{{1
|
" Restore Options: {{{1
|
||||||
let &cpo= s:keepcpo
|
let &cpo= s:keepcpo
|
||||||
|
574
vimfiles/autoload/gundo.py
Normal file
574
vimfiles/autoload/gundo.py
Normal file
@ -0,0 +1,574 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# File: gundo.py
|
||||||
|
# Description: vim global plugin to visualize your undo tree
|
||||||
|
# Maintainer: Steve Losh <steve@stevelosh.com>
|
||||||
|
# License: GPLv2+ -- look it up.
|
||||||
|
# Notes: Much of this code was thiefed from Mercurial, and the rest was
|
||||||
|
# heavily inspired by scratch.vim and histwin.vim.
|
||||||
|
#
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
import difflib
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import vim
|
||||||
|
|
||||||
|
|
||||||
|
# Mercurial's graphlog code --------------------------------------------------------
|
||||||
|
def asciiedges(seen, rev, parents):
|
||||||
|
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
||||||
|
if rev not in seen:
|
||||||
|
seen.append(rev)
|
||||||
|
nodeidx = seen.index(rev)
|
||||||
|
|
||||||
|
knownparents = []
|
||||||
|
newparents = []
|
||||||
|
for parent in parents:
|
||||||
|
if parent in seen:
|
||||||
|
knownparents.append(parent)
|
||||||
|
else:
|
||||||
|
newparents.append(parent)
|
||||||
|
|
||||||
|
ncols = len(seen)
|
||||||
|
seen[nodeidx:nodeidx + 1] = newparents
|
||||||
|
edges = [(nodeidx, seen.index(p)) for p in knownparents]
|
||||||
|
|
||||||
|
if len(newparents) > 0:
|
||||||
|
edges.append((nodeidx, nodeidx))
|
||||||
|
if len(newparents) > 1:
|
||||||
|
edges.append((nodeidx, nodeidx + 1))
|
||||||
|
|
||||||
|
nmorecols = len(seen) - ncols
|
||||||
|
return nodeidx, edges, ncols, nmorecols
|
||||||
|
|
||||||
|
def get_nodeline_edges_tail(
|
||||||
|
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
|
||||||
|
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
|
||||||
|
# Still going in the same non-vertical direction.
|
||||||
|
if n_columns_diff == -1:
|
||||||
|
start = max(node_index + 1, p_node_index)
|
||||||
|
tail = ["|", " "] * (start - node_index - 1)
|
||||||
|
tail.extend(["/", " "] * (n_columns - start))
|
||||||
|
return tail
|
||||||
|
else:
|
||||||
|
return ["\\", " "] * (n_columns - node_index - 1)
|
||||||
|
else:
|
||||||
|
return ["|", " "] * (n_columns - node_index - 1)
|
||||||
|
|
||||||
|
def draw_edges(edges, nodeline, interline):
|
||||||
|
for (start, end) in edges:
|
||||||
|
if start == end + 1:
|
||||||
|
interline[2 * end + 1] = "/"
|
||||||
|
elif start == end - 1:
|
||||||
|
interline[2 * start + 1] = "\\"
|
||||||
|
elif start == end:
|
||||||
|
interline[2 * start] = "|"
|
||||||
|
else:
|
||||||
|
nodeline[2 * end] = "+"
|
||||||
|
if start > end:
|
||||||
|
(start, end) = (end, start)
|
||||||
|
for i in range(2 * start + 1, 2 * end):
|
||||||
|
if nodeline[i] != "+":
|
||||||
|
nodeline[i] = "-"
|
||||||
|
|
||||||
|
def fix_long_right_edges(edges):
|
||||||
|
for (i, (start, end)) in enumerate(edges):
|
||||||
|
if end > start:
|
||||||
|
edges[i] = (start, end + 1)
|
||||||
|
|
||||||
|
def ascii(buf, state, type, char, text, coldata):
|
||||||
|
"""prints an ASCII graph of the DAG
|
||||||
|
|
||||||
|
takes the following arguments (one call per node in the graph):
|
||||||
|
|
||||||
|
- Somewhere to keep the needed state in (init to asciistate())
|
||||||
|
- Column of the current node in the set of ongoing edges.
|
||||||
|
- Type indicator of node data == ASCIIDATA.
|
||||||
|
- Payload: (char, lines):
|
||||||
|
- Character to use as node's symbol.
|
||||||
|
- List of lines to display as the node's text.
|
||||||
|
- Edges; a list of (col, next_col) indicating the edges between
|
||||||
|
the current node and its parents.
|
||||||
|
- Number of columns (ongoing edges) in the current revision.
|
||||||
|
- The difference between the number of columns (ongoing edges)
|
||||||
|
in the next revision and the number of columns (ongoing edges)
|
||||||
|
in the current revision. That is: -1 means one column removed;
|
||||||
|
0 means no columns added or removed; 1 means one column added.
|
||||||
|
"""
|
||||||
|
|
||||||
|
idx, edges, ncols, coldiff = coldata
|
||||||
|
assert -2 < coldiff < 2
|
||||||
|
if coldiff == -1:
|
||||||
|
# Transform
|
||||||
|
#
|
||||||
|
# | | | | | |
|
||||||
|
# o | | into o---+
|
||||||
|
# |X / |/ /
|
||||||
|
# | | | |
|
||||||
|
fix_long_right_edges(edges)
|
||||||
|
|
||||||
|
# add_padding_line says whether to rewrite
|
||||||
|
#
|
||||||
|
# | | | | | | | |
|
||||||
|
# | o---+ into | o---+
|
||||||
|
# | / / | | | # <--- padding line
|
||||||
|
# o | | | / /
|
||||||
|
# o | |
|
||||||
|
add_padding_line = (len(text) > 2 and coldiff == -1 and
|
||||||
|
[x for (x, y) in edges if x + 1 < y])
|
||||||
|
|
||||||
|
# fix_nodeline_tail says whether to rewrite
|
||||||
|
#
|
||||||
|
# | | o | | | | o | |
|
||||||
|
# | | |/ / | | |/ /
|
||||||
|
# | o | | into | o / / # <--- fixed nodeline tail
|
||||||
|
# | |/ / | |/ /
|
||||||
|
# o | | o | |
|
||||||
|
fix_nodeline_tail = len(text) <= 2 and not add_padding_line
|
||||||
|
|
||||||
|
# nodeline is the line containing the node character (typically o)
|
||||||
|
nodeline = ["|", " "] * idx
|
||||||
|
nodeline.extend([char, " "])
|
||||||
|
|
||||||
|
nodeline.extend(
|
||||||
|
get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
|
||||||
|
state[0], fix_nodeline_tail))
|
||||||
|
|
||||||
|
# shift_interline is the line containing the non-vertical
|
||||||
|
# edges between this entry and the next
|
||||||
|
shift_interline = ["|", " "] * idx
|
||||||
|
if coldiff == -1:
|
||||||
|
n_spaces = 1
|
||||||
|
edge_ch = "/"
|
||||||
|
elif coldiff == 0:
|
||||||
|
n_spaces = 2
|
||||||
|
edge_ch = "|"
|
||||||
|
else:
|
||||||
|
n_spaces = 3
|
||||||
|
edge_ch = "\\"
|
||||||
|
shift_interline.extend(n_spaces * [" "])
|
||||||
|
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
|
||||||
|
|
||||||
|
# draw edges from the current node to its parents
|
||||||
|
draw_edges(edges, nodeline, shift_interline)
|
||||||
|
|
||||||
|
# lines is the list of all graph lines to print
|
||||||
|
lines = [nodeline]
|
||||||
|
if add_padding_line:
|
||||||
|
lines.append(get_padding_line(idx, ncols, edges))
|
||||||
|
lines.append(shift_interline)
|
||||||
|
|
||||||
|
# make sure that there are as many graph lines as there are
|
||||||
|
# log strings
|
||||||
|
while len(text) < len(lines):
|
||||||
|
text.append("")
|
||||||
|
if len(lines) < len(text):
|
||||||
|
extra_interline = ["|", " "] * (ncols + coldiff)
|
||||||
|
while len(lines) < len(text):
|
||||||
|
lines.append(extra_interline)
|
||||||
|
|
||||||
|
# print lines
|
||||||
|
indentation_level = max(ncols, ncols + coldiff)
|
||||||
|
for (line, logstr) in zip(lines, text):
|
||||||
|
ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
|
||||||
|
buf.write(ln.rstrip() + '\n')
|
||||||
|
|
||||||
|
# ... and start over
|
||||||
|
state[0] = coldiff
|
||||||
|
state[1] = idx
|
||||||
|
|
||||||
|
def generate(dag, edgefn, current):
|
||||||
|
seen, state = [], [0, 0]
|
||||||
|
buf = Buffer()
|
||||||
|
for node, parents in list(dag):
|
||||||
|
if node.time:
|
||||||
|
age_label = age(int(node.time))
|
||||||
|
else:
|
||||||
|
age_label = 'Original'
|
||||||
|
line = '[%s] %s' % (node.n, age_label)
|
||||||
|
if node.n == current:
|
||||||
|
char = '@'
|
||||||
|
else:
|
||||||
|
char = 'o'
|
||||||
|
ascii(buf, state, 'C', char, [line], edgefn(seen, node, parents))
|
||||||
|
return buf.b
|
||||||
|
|
||||||
|
|
||||||
|
# Mercurial age function -----------------------------------------------------------
|
||||||
|
agescales = [("year", 3600 * 24 * 365),
|
||||||
|
("month", 3600 * 24 * 30),
|
||||||
|
("week", 3600 * 24 * 7),
|
||||||
|
("day", 3600 * 24),
|
||||||
|
("hour", 3600),
|
||||||
|
("minute", 60),
|
||||||
|
("second", 1)]
|
||||||
|
|
||||||
|
def age(ts):
|
||||||
|
'''turn a timestamp into an age string.'''
|
||||||
|
|
||||||
|
def plural(t, c):
|
||||||
|
if c == 1:
|
||||||
|
return t
|
||||||
|
return t + "s"
|
||||||
|
def fmt(t, c):
|
||||||
|
return "%d %s" % (c, plural(t, c))
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
then = ts
|
||||||
|
if then > now:
|
||||||
|
return 'in the future'
|
||||||
|
|
||||||
|
delta = max(1, int(now - then))
|
||||||
|
if delta > agescales[0][1] * 2:
|
||||||
|
return time.strftime('%Y-%m-%d', time.gmtime(float(ts)))
|
||||||
|
|
||||||
|
for t, s in agescales:
|
||||||
|
n = delta // s
|
||||||
|
if n >= 2 or s == 1:
|
||||||
|
return '%s ago' % fmt(t, n)
|
||||||
|
|
||||||
|
|
||||||
|
# Python Vim utility functions -----------------------------------------------------
|
||||||
|
normal = lambda s: vim.command('normal %s' % s)
|
||||||
|
|
||||||
|
MISSING_BUFFER = "Cannot find Gundo's target buffer (%s)"
|
||||||
|
MISSING_WINDOW = "Cannot find window (%s) for Gundo's target buffer (%s)"
|
||||||
|
|
||||||
|
def _check_sanity():
|
||||||
|
'''Check to make sure we're not crazy.
|
||||||
|
|
||||||
|
Does the following things:
|
||||||
|
|
||||||
|
* Make sure the target buffer still exists.
|
||||||
|
'''
|
||||||
|
b = int(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
if not vim.eval('bufloaded(%d)' % b):
|
||||||
|
vim.command('echo "%s"' % (MISSING_BUFFER % b))
|
||||||
|
return False
|
||||||
|
|
||||||
|
w = int(vim.eval('bufwinnr(%d)' % b))
|
||||||
|
if w == -1:
|
||||||
|
vim.command('echo "%s"' % (MISSING_WINDOW % (w, b)))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _goto_window_for_buffer(b):
|
||||||
|
w = int(vim.eval('bufwinnr(%d)' % int(b)))
|
||||||
|
vim.command('%dwincmd w' % w)
|
||||||
|
|
||||||
|
def _goto_window_for_buffer_name(bn):
|
||||||
|
b = vim.eval('bufnr("%s")' % bn)
|
||||||
|
return _goto_window_for_buffer(b)
|
||||||
|
|
||||||
|
def _undo_to(n):
|
||||||
|
n = int(n)
|
||||||
|
if n == 0:
|
||||||
|
vim.command('silent earlier %s' % (int(vim.eval('&undolevels')) + 1))
|
||||||
|
else:
|
||||||
|
vim.command('silent undo %d' % n)
|
||||||
|
|
||||||
|
|
||||||
|
INLINE_HELP = '''\
|
||||||
|
" Gundo for %s (%d)
|
||||||
|
" j/k - move between undo states
|
||||||
|
" p - preview diff of selected and current states
|
||||||
|
" <cr> - revert to selected state
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
# Python undo tree data structures and functions -----------------------------------
|
||||||
|
class Buffer(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.b = ''
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
self.b += s
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
def __init__(self, n, parent, time, curhead):
|
||||||
|
self.n = int(n)
|
||||||
|
self.parent = parent
|
||||||
|
self.children = []
|
||||||
|
self.curhead = curhead
|
||||||
|
self.time = time
|
||||||
|
|
||||||
|
def _make_nodes(alts, nodes, parent=None):
|
||||||
|
p = parent
|
||||||
|
|
||||||
|
for alt in alts:
|
||||||
|
curhead = 'curhead' in alt
|
||||||
|
node = Node(n=alt['seq'], parent=p, time=alt['time'], curhead=curhead)
|
||||||
|
nodes.append(node)
|
||||||
|
if alt.get('alt'):
|
||||||
|
_make_nodes(alt['alt'], nodes, p)
|
||||||
|
p = node
|
||||||
|
|
||||||
|
def make_nodes():
|
||||||
|
ut = vim.eval('undotree()')
|
||||||
|
entries = ut['entries']
|
||||||
|
|
||||||
|
root = Node(0, None, False, 0)
|
||||||
|
nodes = []
|
||||||
|
_make_nodes(entries, nodes, root)
|
||||||
|
nodes.append(root)
|
||||||
|
nmap = dict((node.n, node) for node in nodes)
|
||||||
|
return nodes, nmap
|
||||||
|
|
||||||
|
def changenr(nodes):
|
||||||
|
_curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes))
|
||||||
|
if _curhead_l:
|
||||||
|
current = _curhead_l[0].parent.n
|
||||||
|
else:
|
||||||
|
current = int(vim.eval('changenr()'))
|
||||||
|
return current
|
||||||
|
|
||||||
|
|
||||||
|
# Gundo rendering ------------------------------------------------------------------
|
||||||
|
|
||||||
|
# Rendering utility functions
|
||||||
|
def _fmt_time(t):
|
||||||
|
return time.strftime('%Y-%m-%d %I:%M:%S %p', time.localtime(float(t)))
|
||||||
|
|
||||||
|
def _output_preview_text(lines):
|
||||||
|
_goto_window_for_buffer_name('__Gundo_Preview__')
|
||||||
|
vim.command('setlocal modifiable')
|
||||||
|
vim.current.buffer[:] = lines
|
||||||
|
vim.command('setlocal nomodifiable')
|
||||||
|
|
||||||
|
def _generate_preview_diff(current, node_before, node_after):
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
if not node_after.n: # we're at the original file
|
||||||
|
before_lines = []
|
||||||
|
|
||||||
|
_undo_to(0)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = 'n/a'
|
||||||
|
before_time = ''
|
||||||
|
after_name = 'Original'
|
||||||
|
after_time = ''
|
||||||
|
elif not node_before.n: # we're at a pseudo-root state
|
||||||
|
_undo_to(0)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = 'Original'
|
||||||
|
before_time = ''
|
||||||
|
after_name = node_after.n
|
||||||
|
after_time = _fmt_time(node_after.time)
|
||||||
|
else:
|
||||||
|
_undo_to(node_before.n)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = node_before.n
|
||||||
|
before_time = _fmt_time(node_before.time)
|
||||||
|
after_name = node_after.n
|
||||||
|
after_time = _fmt_time(node_after.time)
|
||||||
|
|
||||||
|
_undo_to(current)
|
||||||
|
|
||||||
|
return list(difflib.unified_diff(before_lines, after_lines,
|
||||||
|
before_name, after_name,
|
||||||
|
before_time, after_time))
|
||||||
|
|
||||||
|
def _generate_change_preview_diff(current, node_before, node_after):
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
_undo_to(node_before.n)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = node_before.n or 'Original'
|
||||||
|
before_time = node_before.time and _fmt_time(node_before.time) or ''
|
||||||
|
after_name = node_after.n or 'Original'
|
||||||
|
after_time = node_after.time and _fmt_time(node_after.time) or ''
|
||||||
|
|
||||||
|
_undo_to(current)
|
||||||
|
|
||||||
|
return list(difflib.unified_diff(before_lines, after_lines,
|
||||||
|
before_name, after_name,
|
||||||
|
before_time, after_time))
|
||||||
|
|
||||||
|
def GundoRenderGraph():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
node.children = [n for n in nodes if n.parent == node]
|
||||||
|
|
||||||
|
def walk_nodes(nodes):
|
||||||
|
for node in nodes:
|
||||||
|
if node.parent:
|
||||||
|
yield (node, [node.parent])
|
||||||
|
else:
|
||||||
|
yield (node, [])
|
||||||
|
|
||||||
|
dag = sorted(nodes, key=lambda n: int(n.n), reverse=True)
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
result = generate(walk_nodes(dag), asciiedges, current).rstrip().splitlines()
|
||||||
|
result = [' ' + l for l in result]
|
||||||
|
|
||||||
|
target = (vim.eval('g:gundo_target_f'), int(vim.eval('g:gundo_target_n')))
|
||||||
|
|
||||||
|
if int(vim.eval('g:gundo_help')):
|
||||||
|
header = (INLINE_HELP % target).splitlines()
|
||||||
|
else:
|
||||||
|
header = []
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenGraph()')
|
||||||
|
vim.command('setlocal modifiable')
|
||||||
|
vim.current.buffer[:] = (header + result)
|
||||||
|
vim.command('setlocal nomodifiable')
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
for line in result:
|
||||||
|
try:
|
||||||
|
line.split('[')[0].index('@')
|
||||||
|
i += 1
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
i += 1
|
||||||
|
vim.command('%d' % (i+len(header)-1))
|
||||||
|
|
||||||
|
def GundoRenderPreview():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_state = vim.eval('s:GundoGetTargetState()')
|
||||||
|
|
||||||
|
# Check that there's an undo state. There may not be if we're talking about
|
||||||
|
# a buffer with no changes yet.
|
||||||
|
if target_state == None:
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
target_state = int(target_state)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
node_after = nmap[target_state]
|
||||||
|
node_before = node_after.parent
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenPreview()')
|
||||||
|
_output_preview_text(_generate_preview_diff(current, node_before, node_after))
|
||||||
|
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
|
||||||
|
def GundoRenderChangePreview():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_state = vim.eval('s:GundoGetTargetState()')
|
||||||
|
|
||||||
|
# Check that there's an undo state. There may not be if we're talking about
|
||||||
|
# a buffer with no changes yet.
|
||||||
|
if target_state == None:
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
target_state = int(target_state)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
node_after = nmap[target_state]
|
||||||
|
node_before = nmap[current]
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenPreview()')
|
||||||
|
_output_preview_text(_generate_change_preview_diff(current, node_before, node_after))
|
||||||
|
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
|
||||||
|
|
||||||
|
# Gundo undo/redo
|
||||||
|
def GundoRevert():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
||||||
|
back = vim.eval('g:gundo_target_n')
|
||||||
|
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
_undo_to(target_n)
|
||||||
|
|
||||||
|
vim.command('GundoRenderGraph')
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
|
||||||
|
if int(vim.eval('g:gundo_close_on_revert')):
|
||||||
|
vim.command('GundoToggle')
|
||||||
|
|
||||||
|
def GundoPlayTo():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
||||||
|
back = int(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
vim.command('echo "%s"' % back)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
normal('zR')
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
|
||||||
|
start = nmap[changenr(nodes)]
|
||||||
|
end = nmap[target_n]
|
||||||
|
|
||||||
|
def _walk_branch(origin, dest):
|
||||||
|
rev = origin.n < dest.n
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
if origin.n > dest.n:
|
||||||
|
current, final = origin, dest
|
||||||
|
else:
|
||||||
|
current, final = dest, origin
|
||||||
|
|
||||||
|
while current.n >= final.n:
|
||||||
|
if current.n == final.n:
|
||||||
|
break
|
||||||
|
nodes.append(current)
|
||||||
|
current = current.parent
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
nodes.append(current)
|
||||||
|
|
||||||
|
return reversed(nodes) if rev else nodes
|
||||||
|
|
||||||
|
branch = _walk_branch(start, end)
|
||||||
|
|
||||||
|
if not branch:
|
||||||
|
vim.command('unsilent echo "No path to that node from here!"')
|
||||||
|
return
|
||||||
|
|
||||||
|
for node in branch:
|
||||||
|
_undo_to(node.n)
|
||||||
|
vim.command('GundoRenderGraph')
|
||||||
|
normal('zz')
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
vim.command('redraw')
|
||||||
|
vim.command('sleep 60m')
|
||||||
|
|
||||||
|
def initPythonModule():
|
||||||
|
if sys.version_info[:2] < (2, 4):
|
||||||
|
vim.command('let s:has_supported_python = 0')
|
407
vimfiles/autoload/gundo.vim
Normal file
407
vimfiles/autoload/gundo.vim
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
" ============================================================================
|
||||||
|
" File: gundo.vim
|
||||||
|
" Description: vim global plugin to visualize your undo tree
|
||||||
|
" Maintainer: Steve Losh <steve@stevelosh.com>
|
||||||
|
" License: GPLv2+ -- look it up.
|
||||||
|
" Notes: Much of this code was thiefed from Mercurial, and the rest was
|
||||||
|
" heavily inspired by scratch.vim and histwin.vim.
|
||||||
|
"
|
||||||
|
" ============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
"{{{ Init
|
||||||
|
|
||||||
|
if v:version < '703'"{{{
|
||||||
|
function! s:GundoDidNotLoad()
|
||||||
|
echohl WarningMsg|echomsg "Gundo unavailable: requires Vim 7.3+"|echohl None
|
||||||
|
endfunction
|
||||||
|
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
|
||||||
|
finish
|
||||||
|
endif"}}}
|
||||||
|
|
||||||
|
if has('python')"{{{
|
||||||
|
let s:has_supported_python = 1
|
||||||
|
else
|
||||||
|
let s:has_supported_python = 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
if !s:has_supported_python
|
||||||
|
function! s:GundoDidNotLoad()
|
||||||
|
echohl WarningMsg|echomsg "Gundo requires Vim to be compiled with Python 2.4+"|echohl None
|
||||||
|
endfunction
|
||||||
|
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
|
||||||
|
finish
|
||||||
|
endif"}}}
|
||||||
|
|
||||||
|
let s:plugin_path = escape(expand('<sfile>:p:h'), '\')
|
||||||
|
|
||||||
|
if !exists('g:gundo_width')"{{{
|
||||||
|
let g:gundo_width = 45
|
||||||
|
endif"}}}
|
||||||
|
if !exists('g:gundo_preview_height')"{{{
|
||||||
|
let g:gundo_preview_height = 15
|
||||||
|
endif"}}}
|
||||||
|
if !exists('g:gundo_preview_bottom')"{{{
|
||||||
|
let g:gundo_preview_bottom = 0
|
||||||
|
endif"}}}
|
||||||
|
if !exists('g:gundo_right')"{{{
|
||||||
|
let g:gundo_right = 0
|
||||||
|
endif"}}}
|
||||||
|
if !exists('g:gundo_help')"{{{
|
||||||
|
let g:gundo_help = 1
|
||||||
|
endif"}}}
|
||||||
|
if !exists("g:gundo_map_move_older")"{{{
|
||||||
|
let g:gundo_map_move_older = 'j'
|
||||||
|
endif"}}}
|
||||||
|
if !exists("g:gundo_map_move_newer")"{{{
|
||||||
|
let g:gundo_map_move_newer = 'k'
|
||||||
|
endif"}}}
|
||||||
|
if !exists("g:gundo_close_on_revert")"{{{
|
||||||
|
let g:gundo_close_on_revert = 0
|
||||||
|
endif"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo utility functions
|
||||||
|
|
||||||
|
function! s:GundoGetTargetState()"{{{
|
||||||
|
let target_line = matchstr(getline("."), '\v\[[0-9]+\]')
|
||||||
|
return matchstr(target_line, '\v[0-9]+')
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoGoToWindowForBufferName(name)"{{{
|
||||||
|
if bufwinnr(bufnr(a:name)) != -1
|
||||||
|
exe bufwinnr(bufnr(a:name)) . "wincmd w"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoIsVisible()"{{{
|
||||||
|
if bufwinnr(bufnr("__Gundo__")) != -1 || bufwinnr(bufnr("__Gundo_Preview__")) != -1
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoInlineHelpLength()"{{{
|
||||||
|
if g:gundo_help
|
||||||
|
return 6
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo buffer settings
|
||||||
|
|
||||||
|
function! s:GundoMapGraph()"{{{
|
||||||
|
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_older . " :call <sid>GundoMove(1)<CR>"
|
||||||
|
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_newer . " :call <sid>GundoMove(-1)<CR>"
|
||||||
|
nnoremap <script> <silent> <buffer> <CR> :call <sid>GundoRevert()<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> o :call <sid>GundoRevert()<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> <down> :call <sid>GundoMove(1)<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> <up> :call <sid>GundoMove(-1)<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> gg gg:call <sid>GundoMove(1)<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> P :call <sid>GundoPlayTo()<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> p :call <sid>GundoRenderChangePreview()<CR>
|
||||||
|
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
|
||||||
|
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
|
||||||
|
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
|
||||||
|
nnoremap <script> <silent> <buffer> <2-LeftMouse> :call <sid>GundoMouseDoubleClick()<CR>
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoMapPreview()"{{{
|
||||||
|
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
|
||||||
|
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
|
||||||
|
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoSettingsGraph()"{{{
|
||||||
|
setlocal buftype=nofile
|
||||||
|
setlocal bufhidden=hide
|
||||||
|
setlocal noswapfile
|
||||||
|
setlocal nobuflisted
|
||||||
|
setlocal nomodifiable
|
||||||
|
setlocal filetype=gundo
|
||||||
|
setlocal nolist
|
||||||
|
setlocal nonumber
|
||||||
|
setlocal norelativenumber
|
||||||
|
setlocal nowrap
|
||||||
|
call s:GundoSyntaxGraph()
|
||||||
|
call s:GundoMapGraph()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoSettingsPreview()"{{{
|
||||||
|
setlocal buftype=nofile
|
||||||
|
setlocal bufhidden=hide
|
||||||
|
setlocal noswapfile
|
||||||
|
setlocal nobuflisted
|
||||||
|
setlocal nomodifiable
|
||||||
|
setlocal filetype=diff
|
||||||
|
setlocal nonumber
|
||||||
|
setlocal norelativenumber
|
||||||
|
setlocal nowrap
|
||||||
|
setlocal foldlevel=20
|
||||||
|
setlocal foldmethod=diff
|
||||||
|
call s:GundoMapPreview()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoSyntaxGraph()"{{{
|
||||||
|
let b:current_syntax = 'gundo'
|
||||||
|
|
||||||
|
syn match GundoCurrentLocation '@'
|
||||||
|
syn match GundoHelp '\v^".*$'
|
||||||
|
syn match GundoNumberField '\v\[[0-9]+\]'
|
||||||
|
syn match GundoNumber '\v[0-9]+' contained containedin=GundoNumberField
|
||||||
|
|
||||||
|
hi def link GundoCurrentLocation Keyword
|
||||||
|
hi def link GundoHelp Comment
|
||||||
|
hi def link GundoNumberField Comment
|
||||||
|
hi def link GundoNumber Identifier
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo buffer/window management
|
||||||
|
|
||||||
|
function! s:GundoResizeBuffers(backto)"{{{
|
||||||
|
call s:GundoGoToWindowForBufferName('__Gundo__')
|
||||||
|
exe "vertical resize " . g:gundo_width
|
||||||
|
|
||||||
|
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
||||||
|
exe "resize " . g:gundo_preview_height
|
||||||
|
|
||||||
|
exe a:backto . "wincmd w"
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoOpenGraph()"{{{
|
||||||
|
let existing_gundo_buffer = bufnr("__Gundo__")
|
||||||
|
|
||||||
|
if existing_gundo_buffer == -1
|
||||||
|
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
||||||
|
exe "new __Gundo__"
|
||||||
|
if g:gundo_preview_bottom
|
||||||
|
if g:gundo_right
|
||||||
|
wincmd L
|
||||||
|
else
|
||||||
|
wincmd H
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
call s:GundoResizeBuffers(winnr())
|
||||||
|
else
|
||||||
|
let existing_gundo_window = bufwinnr(existing_gundo_buffer)
|
||||||
|
|
||||||
|
if existing_gundo_window != -1
|
||||||
|
if winnr() != existing_gundo_window
|
||||||
|
exe existing_gundo_window . "wincmd w"
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
||||||
|
if g:gundo_preview_bottom
|
||||||
|
if g:gundo_right
|
||||||
|
exe "botright vsplit +buffer" . existing_gundo_buffer
|
||||||
|
else
|
||||||
|
exe "topleft vsplit +buffer" . existing_gundo_buffer
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
exe "split +buffer" . existing_gundo_buffer
|
||||||
|
endif
|
||||||
|
call s:GundoResizeBuffers(winnr())
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoOpenPreview()"{{{
|
||||||
|
let existing_preview_buffer = bufnr("__Gundo_Preview__")
|
||||||
|
|
||||||
|
if existing_preview_buffer == -1
|
||||||
|
if g:gundo_preview_bottom
|
||||||
|
exe "botright new __Gundo_Preview__"
|
||||||
|
else
|
||||||
|
if g:gundo_right
|
||||||
|
exe "botright vnew __Gundo_Preview__"
|
||||||
|
else
|
||||||
|
exe "topleft vnew __Gundo_Preview__"
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
let existing_preview_window = bufwinnr(existing_preview_buffer)
|
||||||
|
|
||||||
|
if existing_preview_window != -1
|
||||||
|
if winnr() != existing_preview_window
|
||||||
|
exe existing_preview_window . "wincmd w"
|
||||||
|
endif
|
||||||
|
else
|
||||||
|
if g:gundo_preview_bottom
|
||||||
|
exe "botright split +buffer" . existing_preview_buffer
|
||||||
|
else
|
||||||
|
if g:gundo_right
|
||||||
|
exe "botright vsplit +buffer" . existing_preview_buffer
|
||||||
|
else
|
||||||
|
exe "topleft vsplit +buffer" . existing_preview_buffer
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoClose()"{{{
|
||||||
|
if s:GundoGoToWindowForBufferName('__Gundo__')
|
||||||
|
quit
|
||||||
|
endif
|
||||||
|
|
||||||
|
if s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
||||||
|
quit
|
||||||
|
endif
|
||||||
|
|
||||||
|
exe bufwinnr(g:gundo_target_n) . "wincmd w"
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoOpen()"{{{
|
||||||
|
if !exists('g:gundo_py_loaded')
|
||||||
|
exe 'pyfile ' . s:plugin_path . '/gundo.py'
|
||||||
|
python initPythonModule()
|
||||||
|
|
||||||
|
if !s:has_supported_python
|
||||||
|
function! s:GundoDidNotLoad()
|
||||||
|
echohl WarningMsg|echomsg "Gundo unavailable: requires Vim 7.3+"|echohl None
|
||||||
|
endfunction
|
||||||
|
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
|
||||||
|
call s:GundoDidNotLoad()
|
||||||
|
return
|
||||||
|
endif"
|
||||||
|
|
||||||
|
let g:gundo_py_loaded = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Save `splitbelow` value and set it to default to avoid problems with
|
||||||
|
" positioning new windows.
|
||||||
|
let saved_splitbelow = &splitbelow
|
||||||
|
let &splitbelow = 0
|
||||||
|
|
||||||
|
call s:GundoOpenPreview()
|
||||||
|
exe bufwinnr(g:gundo_target_n) . "wincmd w"
|
||||||
|
|
||||||
|
call s:GundoRenderGraph()
|
||||||
|
call s:GundoRenderPreview()
|
||||||
|
|
||||||
|
" Restore `splitbelow` value.
|
||||||
|
let &splitbelow = saved_splitbelow
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoToggle()"{{{
|
||||||
|
if s:GundoIsVisible()
|
||||||
|
call s:GundoClose()
|
||||||
|
else
|
||||||
|
let g:gundo_target_n = bufnr('')
|
||||||
|
let g:gundo_target_f = @%
|
||||||
|
call s:GundoOpen()
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo mouse handling
|
||||||
|
|
||||||
|
function! s:GundoMouseDoubleClick()"{{{
|
||||||
|
let start_line = getline('.')
|
||||||
|
|
||||||
|
if stridx(start_line, '[') == -1
|
||||||
|
return
|
||||||
|
else
|
||||||
|
call s:GundoRevert()
|
||||||
|
endif
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo movement
|
||||||
|
|
||||||
|
function! s:GundoMove(direction) range"{{{
|
||||||
|
let start_line = getline('.')
|
||||||
|
if v:count1 == 0
|
||||||
|
let move_count = 1
|
||||||
|
else
|
||||||
|
let move_count = v:count1
|
||||||
|
endif
|
||||||
|
let distance = 2 * move_count
|
||||||
|
|
||||||
|
" If we're in between two nodes we move by one less to get back on track.
|
||||||
|
if stridx(start_line, '[') == -1
|
||||||
|
let distance = distance - 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
let target_n = line('.') + (distance * a:direction)
|
||||||
|
|
||||||
|
" Bound the movement to the graph.
|
||||||
|
if target_n <= s:GundoInlineHelpLength() - 1
|
||||||
|
call cursor(s:GundoInlineHelpLength(), 0)
|
||||||
|
else
|
||||||
|
call cursor(target_n, 0)
|
||||||
|
endif
|
||||||
|
|
||||||
|
let line = getline('.')
|
||||||
|
|
||||||
|
" Move to the node, whether it's an @ or an o
|
||||||
|
let idx1 = stridx(line, '@')
|
||||||
|
let idx2 = stridx(line, 'o')
|
||||||
|
if idx1 != -1
|
||||||
|
call cursor(0, idx1 + 1)
|
||||||
|
else
|
||||||
|
call cursor(0, idx2 + 1)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:GundoRenderPreview()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo rendering
|
||||||
|
|
||||||
|
function! s:GundoRenderGraph()"{{{
|
||||||
|
python GundoRenderGraph()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoRenderPreview()"{{{
|
||||||
|
python GundoRenderPreview()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoRenderChangePreview()"{{{
|
||||||
|
python GundoRenderChangePreview()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Gundo undo/redo
|
||||||
|
|
||||||
|
function! s:GundoRevert()"{{{
|
||||||
|
python GundoRevert()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! s:GundoPlayTo()"{{{
|
||||||
|
python GundoPlayTo()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
"}}}
|
||||||
|
|
||||||
|
"{{{ Misc
|
||||||
|
|
||||||
|
function! gundo#GundoToggle()"{{{
|
||||||
|
call s:GundoToggle()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
function! gundo#GundoRenderGraph()"{{{
|
||||||
|
call s:GundoRenderGraph()
|
||||||
|
endfunction"}}}
|
||||||
|
|
||||||
|
augroup GundoAug
|
||||||
|
autocmd!
|
||||||
|
autocmd BufNewFile __Gundo__ call s:GundoSettingsGraph()
|
||||||
|
autocmd BufNewFile __Gundo_Preview__ call s:GundoSettingsPreview()
|
||||||
|
augroup END
|
||||||
|
|
||||||
|
"}}}
|
@ -1,7 +1,7 @@
|
|||||||
" netrw.vim: Handles file transfer and remote directory listing across
|
" netrw.vim: Handles file transfer and remote directory listing across
|
||||||
" AUTOLOAD SECTION
|
" AUTOLOAD SECTION
|
||||||
" Date: Apr 01, 2011
|
" Date: May 31, 2011
|
||||||
" Version: 141
|
" Version: 142
|
||||||
" Maintainer: Charles E Campbell, Jr <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
|
" Maintainer: Charles E Campbell, Jr <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
|
||||||
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
|
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
|
||||||
" Copyright: Copyright (C) 1999-2010 Charles E. Campbell, Jr. {{{1
|
" Copyright: Copyright (C) 1999-2010 Charles E. Campbell, Jr. {{{1
|
||||||
@ -22,7 +22,7 @@
|
|||||||
if &cp || exists("g:loaded_netrw")
|
if &cp || exists("g:loaded_netrw")
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let g:loaded_netrw = "v141"
|
let g:loaded_netrw = "v142"
|
||||||
if v:version < 702
|
if v:version < 702
|
||||||
echohl WarningMsg
|
echohl WarningMsg
|
||||||
echo "***warning*** this version of netrw needs vim 7.2"
|
echo "***warning*** this version of netrw needs vim 7.2"
|
||||||
@ -291,7 +291,7 @@ call s:NetrwInit("g:netrw_timefmt","%c")
|
|||||||
call s:NetrwInit("g:netrw_xstrlen",0)
|
call s:NetrwInit("g:netrw_xstrlen",0)
|
||||||
call s:NetrwInit("g:NetrwTopLvlMenu","Netrw.")
|
call s:NetrwInit("g:NetrwTopLvlMenu","Netrw.")
|
||||||
call s:NetrwInit("g:netrw_win95ftp",1)
|
call s:NetrwInit("g:netrw_win95ftp",1)
|
||||||
call s:NetrwInit("g:netrw_winsize",25)
|
call s:NetrwInit("g:netrw_winsize",50)
|
||||||
" ---------------------------------------------------------------------
|
" ---------------------------------------------------------------------
|
||||||
" Default values for netrw's script variables: {{{2
|
" Default values for netrw's script variables: {{{2
|
||||||
call s:NetrwInit("g:netrw_fname_escape",' ?&;%')
|
call s:NetrwInit("g:netrw_fname_escape",' ?&;%')
|
||||||
@ -1518,6 +1518,14 @@ endfun
|
|||||||
fun! s:NetrwMethod(choice)
|
fun! s:NetrwMethod(choice)
|
||||||
" call Dfunc("NetrwMethod(a:choice<".a:choice.">)")
|
" call Dfunc("NetrwMethod(a:choice<".a:choice.">)")
|
||||||
|
|
||||||
|
" sanity check: choice should have at least three slashes in it
|
||||||
|
if strlen(substitute(a:choice,'[^/]','','g')) < 3
|
||||||
|
call netrw#ErrorMsg(s:ERROR,"not a netrw-style url; netrw uses protocol://[user@]hostname[:port]/[path])",78)
|
||||||
|
let b:netrw_method = -1
|
||||||
|
" call Dret("NetrwMethod : incorrect url format<".a:choice.">")
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
" record current g:netrw_machine, if any
|
" record current g:netrw_machine, if any
|
||||||
" curmachine used if protocol == ftp and no .netrc
|
" curmachine used if protocol == ftp and no .netrc
|
||||||
if exists("g:netrw_machine")
|
if exists("g:netrw_machine")
|
||||||
@ -1813,6 +1821,25 @@ endfun
|
|||||||
" s:NetrwMaps: {{{2
|
" s:NetrwMaps: {{{2
|
||||||
fun! s:NetrwMaps(islocal)
|
fun! s:NetrwMaps(islocal)
|
||||||
" call Dfunc("s:NetrwMaps(islocal=".a:islocal.") b:netrw_curdir<".b:netrw_curdir.">")
|
" call Dfunc("s:NetrwMaps(islocal=".a:islocal.") b:netrw_curdir<".b:netrw_curdir.">")
|
||||||
|
|
||||||
|
" set up Rexplore and [ 2-leftmouse-click -or- c-leftmouse ]
|
||||||
|
" call Decho("set up Rexplore command")
|
||||||
|
com! Rexplore call s:NetrwRexplore(w:netrw_rexlocal,exists("w:netrw_rexdir")? w:netrw_rexdir : ".")
|
||||||
|
if g:netrw_mousemaps && g:netrw_retmap
|
||||||
|
" call Decho("set up Rexplore 2-leftmouse")
|
||||||
|
if !hasmapto("<Plug>NetrwReturn")
|
||||||
|
if maparg("<2-leftmouse>","n") == "" || maparg("<2-leftmouse>","n") =~ '^-$'
|
||||||
|
" call Decho("making map for 2-leftmouse")
|
||||||
|
nmap <unique> <silent> <2-leftmouse> <Plug>NetrwReturn
|
||||||
|
elseif maparg("<c-leftmouse>","n") == ""
|
||||||
|
" call Decho("making map for c-leftmouse")
|
||||||
|
nmap <unique> <silent> <c-leftmouse> <Plug>NetrwReturn
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
nno <silent> <Plug>NetrwReturn :Rexplore<cr>
|
||||||
|
" call Decho("made <Plug>NetrwReturn map")
|
||||||
|
endif
|
||||||
|
|
||||||
if a:islocal
|
if a:islocal
|
||||||
" call Decho("make local maps")
|
" call Decho("make local maps")
|
||||||
inoremap <buffer> <silent> a <c-o>:call <SID>NetrwHide(1)<cr>
|
inoremap <buffer> <silent> a <c-o>:call <SID>NetrwHide(1)<cr>
|
||||||
@ -1925,15 +1952,22 @@ fun! s:NetrwMaps(islocal)
|
|||||||
endif
|
endif
|
||||||
let mapsafecurdir = escape(b:netrw_curdir, s:netrw_map_escape)
|
let mapsafecurdir = escape(b:netrw_curdir, s:netrw_map_escape)
|
||||||
if g:netrw_mousemaps == 1
|
if g:netrw_mousemaps == 1
|
||||||
nnoremap <buffer> <silent> <leftmouse> <leftmouse>:call <SID>NetrwLeftmouse(1)<cr>
|
nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse
|
||||||
nnoremap <buffer> <silent> <middlemouse> <leftmouse>:call <SID>NetrwPrevWinOpen(1)<cr>
|
nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(1)<cr>
|
||||||
nnoremap <buffer> <silent> <s-leftmouse> <leftmouse>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
|
nmap <buffer> <middlemouse> <Plug>NetrwMiddlemouse
|
||||||
nmap <buffer> <silent> <2-leftmouse> -
|
nno <buffer> <silent> <Plug>NetrwMiddlemouse <leftmouse>:call <SID>NetrwPrevWinOpen(1)<cr>
|
||||||
|
nmap <buffer> <s-leftmouse> <Plug>NetrwSLeftmouse
|
||||||
|
nno <buffer> <silent> <Plug>NetrwSLeftmouse <leftmouse>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
|
||||||
|
nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse
|
||||||
|
nmap <buffer> <silent> <Plug>Netrw2Leftmouse -
|
||||||
|
imap <buffer> <leftmouse> <Plug>ILeftmouse
|
||||||
|
ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(1)<cr>
|
||||||
|
imap <buffer> <middlemouse> <Plug>IMiddlemouse
|
||||||
|
ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(1)<cr>
|
||||||
|
imap <buffer> <s-leftmouse> <Plug>ISLeftmouse
|
||||||
|
ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
|
||||||
exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
||||||
exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
||||||
inoremap <buffer> <silent> <leftmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(1)<cr>
|
|
||||||
inoremap <buffer> <silent> <middlemouse> <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(1)<cr>
|
|
||||||
inoremap <buffer> <silent> <s-leftmouse> <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
|
|
||||||
exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
||||||
endif
|
endif
|
||||||
exe 'nnoremap <buffer> <silent> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
exe 'nnoremap <buffer> <silent> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
||||||
@ -2055,15 +2089,22 @@ fun! s:NetrwMaps(islocal)
|
|||||||
|
|
||||||
nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr>
|
nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr>
|
||||||
if g:netrw_mousemaps == 1
|
if g:netrw_mousemaps == 1
|
||||||
nnoremap <buffer> <silent> <leftmouse> <leftmouse>:call <SID>NetrwLeftmouse(0)<cr>
|
nmap <leftmouse> <Plug>NetrwLeftmouse
|
||||||
nnoremap <buffer> <silent> <middlemouse> <leftmouse>:call <SID>NetrwPrevWinOpen(0)<cr>
|
nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(0)<cr>
|
||||||
nnoremap <buffer> <silent> <s-leftmouse> <leftmouse>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
|
nmap <middlemouse> <Plug>NetrwMiddlemouse
|
||||||
nmap <buffer> <silent> <2-leftmouse> -
|
nno <buffer> <silent> <middlemouse> <Plug>NetrwMiddlemouse <leftmouse>:call <SID>NetrwPrevWinOpen(0)<cr>
|
||||||
|
nmap <buffer> <s-leftmouse> <Plug>NetrwSLeftmouse
|
||||||
|
nno <buffer> <silent> <Plug>NetrwSLeftmouse <leftmouse>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
|
||||||
|
nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse
|
||||||
|
nmap <buffer> <silent> <Plug>Netrw2Leftmouse -
|
||||||
|
imap <buffer> <leftmouse> <Plug>ILeftmouse
|
||||||
|
ino <buffer> <silent> <Plug>ILeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(0)<cr>
|
||||||
|
imap <buffer> <middlemouse> <Plug>IMiddlemouse
|
||||||
|
ino <buffer> <silent> <Plug>IMiddlemouse <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(0)<cr>
|
||||||
|
imap <buffer> <s-leftmouse> <Plug>ISLeftmouse
|
||||||
|
ino <buffer> <silent> <Plug>ISLeftmouse <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
|
||||||
exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
||||||
exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
||||||
inoremap <buffer> <silent> <leftmouse> <c-o><leftmouse><c-o>:call <SID>NetrwLeftmouse(0)<cr>
|
|
||||||
inoremap <buffer> <silent> <middlemouse> <c-o><leftmouse><c-o>:call <SID>NetrwPrevWinOpen(0)<cr>
|
|
||||||
inoremap <buffer> <silent> <s-leftmouse> <c-o><leftmouse><c-o>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
|
|
||||||
exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
exe 'inoremap <buffer> <silent> <rightmouse> <c-o><leftmouse><c-o>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
||||||
endif
|
endif
|
||||||
exe 'nnoremap <buffer> <silent> <del> :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
exe 'nnoremap <buffer> <silent> <del> :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
|
||||||
@ -2081,23 +2122,8 @@ fun! s:NetrwMaps(islocal)
|
|||||||
inoremap <buffer> <F1> <c-o>:he netrw-quickhelp<cr>
|
inoremap <buffer> <F1> <c-o>:he netrw-quickhelp<cr>
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" set up Rexplore and leftmouse-double-click
|
|
||||||
com! Rexplore call s:NetrwRexplore(w:netrw_rexlocal,exists("w:netrw_rexdir")? w:netrw_rexdir : ".")
|
|
||||||
if g:netrw_mousemaps && g:netrw_retmap
|
|
||||||
if !hasmapto("<Plug>NetrwReturn")
|
|
||||||
if maparg("<2-leftmouse>","n") == "" || maparg("<2-leftmouse>","n") =~ '^-$'
|
|
||||||
" call Decho("making map for 2-leftmouse")
|
|
||||||
nmap <unique> <silent> <2-leftmouse> <Plug>NetrwReturn
|
|
||||||
elseif maparg("<c-leftmouse>","n") == ""
|
|
||||||
" call Decho("making map for c-leftmouse")
|
|
||||||
nmap <unique> <silent> <c-leftmouse> <Plug>NetrwReturn
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
exe 'nnoremap <silent> <Plug>NetrwReturn :Rexplore<cr>'
|
|
||||||
" call Decho("made <Plug>NetrwReturn map")
|
|
||||||
endif
|
|
||||||
|
|
||||||
keepj call s:SetRexDir(a:islocal,b:netrw_curdir)
|
keepj call s:SetRexDir(a:islocal,b:netrw_curdir)
|
||||||
|
|
||||||
" call Dret("s:NetrwMaps")
|
" call Dret("s:NetrwMaps")
|
||||||
endfun
|
endfun
|
||||||
|
|
||||||
@ -3647,34 +3673,40 @@ fun! netrw#Explore(indx,dosplit,style,...)
|
|||||||
if a:dosplit || &modified || a:style == 6
|
if a:dosplit || &modified || a:style == 6
|
||||||
" call Decho("case dosplit=".a:dosplit." modified=".&modified." a:style=".a:style.": dosplit or file has been modified")
|
" call Decho("case dosplit=".a:dosplit." modified=".&modified." a:style=".a:style.": dosplit or file has been modified")
|
||||||
call s:SaveWinVars()
|
call s:SaveWinVars()
|
||||||
let winsize= g:netrw_winsize
|
let winsz= g:netrw_winsize
|
||||||
if a:indx > 0
|
if a:indx > 0
|
||||||
let winsize= a:indx
|
let winsz= a:indx
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if a:style == 0 " Explore, Sexplore
|
if a:style == 0 " Explore, Sexplore
|
||||||
" call Decho("style=0: Explore or Sexplore")
|
" call Decho("style=0: Explore or Sexplore")
|
||||||
exe winsize."wincmd s"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe winsz."wincmd s"
|
||||||
|
|
||||||
elseif a:style == 1 "Explore!, Sexplore!
|
elseif a:style == 1 "Explore!, Sexplore!
|
||||||
" call Decho("style=1: Explore! or Sexplore!")
|
" call Decho("style=1: Explore! or Sexplore!")
|
||||||
exe winsize."wincmd v"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe winsz."wincmd v"
|
||||||
|
|
||||||
elseif a:style == 2 " Hexplore
|
elseif a:style == 2 " Hexplore
|
||||||
" call Decho("style=2: Hexplore")
|
" call Decho("style=2: Hexplore")
|
||||||
exe "bel ".winsize."wincmd s"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe "bel ".winsz."wincmd s"
|
||||||
|
|
||||||
elseif a:style == 3 " Hexplore!
|
elseif a:style == 3 " Hexplore!
|
||||||
" call Decho("style=3: Hexplore!")
|
" call Decho("style=3: Hexplore!")
|
||||||
exe "abo ".winsize."wincmd s"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe "abo ".winsz."wincmd s"
|
||||||
|
|
||||||
elseif a:style == 4 " Vexplore
|
elseif a:style == 4 " Vexplore
|
||||||
" call Decho("style=4: Vexplore")
|
" call Decho("style=4: Vexplore")
|
||||||
exe "lefta ".winsize."wincmd v"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe "lefta ".winsz."wincmd v"
|
||||||
|
|
||||||
elseif a:style == 5 " Vexplore!
|
elseif a:style == 5 " Vexplore!
|
||||||
" call Decho("style=5: Vexplore!")
|
" call Decho("style=5: Vexplore!")
|
||||||
exe "rightb ".winsize."wincmd v"
|
let winsz= (winsz*winheight(0))/100
|
||||||
|
exe "rightb ".winsz."wincmd v"
|
||||||
|
|
||||||
elseif a:style == 6 " Texplore
|
elseif a:style == 6 " Texplore
|
||||||
call s:SaveBufVars()
|
call s:SaveBufVars()
|
||||||
@ -4618,13 +4650,13 @@ fun! s:NetrwMarkFileCopy(islocal)
|
|||||||
|
|
||||||
" sanity checks
|
" sanity checks
|
||||||
if !exists("s:netrwmarkfilelist_{bufnr('%')}") || empty(s:netrwmarkfilelist_{bufnr('%')})
|
if !exists("s:netrwmarkfilelist_{bufnr('%')}") || empty(s:netrwmarkfilelist_{bufnr('%')})
|
||||||
keepj call netrw#ErrorMsg(2,"there are no marked files in this window (:help netrw-mf)",66)
|
keepj call netrw#ErrorMsg(s:ERROR,"there are no marked files in this window (:help netrw-mf)",66)
|
||||||
" call Dret("s:NetrwMarkFileCopy 0")
|
" call Dret("s:NetrwMarkFileCopy 0")
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
" call Decho("sanity chk passed: s:netrwmarkfilelist_".bufnr('%')."<".string(s:netrwmarkfilelist_{bufnr('%')}))
|
" call Decho("sanity chk passed: s:netrwmarkfilelist_".bufnr('%')."<".string(s:netrwmarkfilelist_{bufnr('%')}))
|
||||||
if !exists("s:netrwmftgt")
|
if !exists("s:netrwmftgt")
|
||||||
keepj call netrw#ErrorMsg(2,"your marked file target is empty! (:help netrw-mt)",67)
|
keepj call netrw#ErrorMsg(s:ERROR,"your marked file target is empty! (:help netrw-mt)",67)
|
||||||
" call Dret("s:NetrwMarkFileCopy 0")
|
" call Dret("s:NetrwMarkFileCopy 0")
|
||||||
return 0
|
return 0
|
||||||
endif
|
endif
|
||||||
@ -6143,7 +6175,8 @@ fun! s:NetrwSplit(mode)
|
|||||||
if a:mode == 0
|
if a:mode == 0
|
||||||
" remote and o
|
" remote and o
|
||||||
" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s")
|
" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s")
|
||||||
exe (g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s"
|
let winsz= (g:netrw_winsize*winheight(0))/100
|
||||||
|
exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
|
||||||
let s:didsplit= 1
|
let s:didsplit= 1
|
||||||
keepj call s:RestoreWinVars()
|
keepj call s:RestoreWinVars()
|
||||||
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
||||||
@ -6162,7 +6195,8 @@ fun! s:NetrwSplit(mode)
|
|||||||
elseif a:mode == 2
|
elseif a:mode == 2
|
||||||
" remote and v
|
" remote and v
|
||||||
" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v")
|
" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v")
|
||||||
exe (g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v"
|
let winsz= (g:netrw_winsize*winwidth(0))/100
|
||||||
|
exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v"
|
||||||
let s:didsplit= 1
|
let s:didsplit= 1
|
||||||
keepj call s:RestoreWinVars()
|
keepj call s:RestoreWinVars()
|
||||||
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
||||||
@ -6171,7 +6205,8 @@ fun! s:NetrwSplit(mode)
|
|||||||
elseif a:mode == 3
|
elseif a:mode == 3
|
||||||
" local and o
|
" local and o
|
||||||
" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s")
|
" call Decho("exe ".(g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s")
|
||||||
exe (g:netrw_alto? "bel " : "abo ").g:netrw_winsize."wincmd s"
|
let winsz= (g:netrw_winsize*winheight(0))/100
|
||||||
|
exe (g:netrw_alto? "bel " : "abo ").winsz."wincmd s"
|
||||||
let s:didsplit= 1
|
let s:didsplit= 1
|
||||||
keepj call s:RestoreWinVars()
|
keepj call s:RestoreWinVars()
|
||||||
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
||||||
@ -6192,7 +6227,8 @@ fun! s:NetrwSplit(mode)
|
|||||||
elseif a:mode == 5
|
elseif a:mode == 5
|
||||||
" local and v
|
" local and v
|
||||||
" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v")
|
" call Decho("exe ".(g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v")
|
||||||
exe (g:netrw_altv? "rightb " : "lefta ").g:netrw_winsize."wincmd v"
|
let winsz= (g:netrw_winsize*winwidth(0))/100
|
||||||
|
exe (g:netrw_altv? "rightb " : "lefta ").winsz."wincmd v"
|
||||||
let s:didsplit= 1
|
let s:didsplit= 1
|
||||||
keepj call s:RestoreWinVars()
|
keepj call s:RestoreWinVars()
|
||||||
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
||||||
@ -6826,8 +6862,8 @@ fun! s:NetrwRemoteListing()
|
|||||||
" call Decho("2: exe sil r! ".listcmd)
|
" call Decho("2: exe sil r! ".listcmd)
|
||||||
exe "sil! keepalt r! ".listcmd
|
exe "sil! keepalt r! ".listcmd
|
||||||
else
|
else
|
||||||
" call Decho("3: exe sil r! ".listcmd.' '.shellescape(s:path,1))
|
" call Decho("3: exe sil r! ".listcmd.' '.shellescape(fnameescape(s:path),1))
|
||||||
exe "sil! keepalt r! ".listcmd.' '.shellescape(s:path,1)
|
exe "sil! keepalt r! ".listcmd.' '.shellescape(fnameescape(s:path),1)
|
||||||
" call Decho("listcmd<".listcmd."> path<".s:path.">")
|
" call Decho("listcmd<".listcmd."> path<".s:path.">")
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
@ -7278,12 +7314,12 @@ fun! s:LocalListing()
|
|||||||
" get the list of files contained in the current directory
|
" get the list of files contained in the current directory
|
||||||
let dirname = b:netrw_curdir
|
let dirname = b:netrw_curdir
|
||||||
let dirnamelen = s:Strlen(b:netrw_curdir)
|
let dirnamelen = s:Strlen(b:netrw_curdir)
|
||||||
let filelist = glob(s:ComposePath(dirname,"*"))
|
let filelist = glob(s:ComposePath(fnameescape(dirname),"*"))
|
||||||
" call Decho("glob(dirname<".dirname."/*>)=".filelist)
|
" call Decho("glob(dirname<".dirname."/*>)=".filelist)
|
||||||
if filelist != ""
|
if filelist != ""
|
||||||
let filelist= filelist."\n"
|
let filelist= filelist."\n"
|
||||||
endif
|
endif
|
||||||
let filelist= filelist.glob(s:ComposePath(dirname,".*"))
|
let filelist= filelist.glob(s:ComposePath(fnameescape(dirname),".*"))
|
||||||
" call Decho("glob(dirname<".dirname."/.*>)=".filelist)
|
" call Decho("glob(dirname<".dirname."/.*>)=".filelist)
|
||||||
|
|
||||||
" Coding choice: either elide ./ if present
|
" Coding choice: either elide ./ if present
|
||||||
@ -7797,7 +7833,7 @@ endfun
|
|||||||
" 0=note = s:NOTE
|
" 0=note = s:NOTE
|
||||||
" 1=warning = s:WARNING
|
" 1=warning = s:WARNING
|
||||||
" 2=error = s:ERROR
|
" 2=error = s:ERROR
|
||||||
" Dec 03, 2009 : max errnum currently is 77
|
" Apr 18, 2011 : max errnum currently is 78
|
||||||
fun! netrw#ErrorMsg(level,msg,errnum)
|
fun! netrw#ErrorMsg(level,msg,errnum)
|
||||||
" call Dfunc("netrw#ErrorMsg(level=".a:level." msg<".a:msg."> errnum=".a:errnum.") g:netrw_use_errorwindow=".g:netrw_use_errorwindow)
|
" call Dfunc("netrw#ErrorMsg(level=".a:level." msg<".a:msg."> errnum=".a:errnum.") g:netrw_use_errorwindow=".g:netrw_use_errorwindow)
|
||||||
|
|
||||||
@ -8326,7 +8362,7 @@ endfun
|
|||||||
" ---------------------------------------------------------------------
|
" ---------------------------------------------------------------------
|
||||||
" s:RemotePathAnalysis: {{{2
|
" s:RemotePathAnalysis: {{{2
|
||||||
fun! s:RemotePathAnalysis(dirname)
|
fun! s:RemotePathAnalysis(dirname)
|
||||||
" call Dfunc("s:RemotePathAnalysis()")
|
" call Dfunc("s:RemotePathAnalysis(a:dirname<".a:dirname.">)")
|
||||||
|
|
||||||
let dirpat = '^\(\w\{-}\)://\(\w\+@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$'
|
let dirpat = '^\(\w\{-}\)://\(\w\+@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$'
|
||||||
let s:method = substitute(a:dirname,dirpat,'\1','')
|
let s:method = substitute(a:dirname,dirpat,'\1','')
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
*gundo.txt* Graph your undo tree so you can actually USE it.
|
*gundo.txt* Graph your undo tree so you can actually USE it.
|
||||||
|
|
||||||
Making's Vim's undo tree usable by humans.
|
Making Vim's undo tree usable by humans.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
CONTENTS *Gundo-contents*
|
CONTENTS *Gundo-contents*
|
||||||
@ -16,6 +16,7 @@ CONTENTS *Gundo-contents*
|
|||||||
3.6 gundo_disable ............. |gundo_disable|
|
3.6 gundo_disable ............. |gundo_disable|
|
||||||
3.7 gundo_map_move_older ...... |gundo_map_move_older|
|
3.7 gundo_map_move_older ...... |gundo_map_move_older|
|
||||||
gundo_map_move_newer ...... |gundo_map_move_newer|
|
gundo_map_move_newer ...... |gundo_map_move_newer|
|
||||||
|
3.8 gundo_close_on_revert ..... |gundo_close_on_revert|
|
||||||
4. License ........................ |GundoLicense|
|
4. License ........................ |GundoLicense|
|
||||||
5. Bugs ........................... |GundoBugs|
|
5. Bugs ........................... |GundoBugs|
|
||||||
6. Contributing ................... |GundoContributing|
|
6. Contributing ................... |GundoContributing|
|
||||||
@ -188,6 +189,13 @@ useful if you use a Dvorak keyboard and have changed your movement keys.
|
|||||||
Default: gundo_map_move_older = "j"
|
Default: gundo_map_move_older = "j"
|
||||||
gundo_map_move_newer = "k"
|
gundo_map_move_newer = "k"
|
||||||
|
|
||||||
|
------------------------------------------------------------------------------
|
||||||
|
3.8 g:gundo_close_on_revert *gundo_close_on_revert*
|
||||||
|
|
||||||
|
Set this to 1 to automatically close the Gundo windows when reverting.
|
||||||
|
|
||||||
|
Default: 0 (windows do not automatically close)
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
4. License *GundoLicense*
|
4. License *GundoLicense*
|
||||||
|
|
||||||
@ -211,6 +219,13 @@ GitHub: http://github.com/sjl/gundo.vim/
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
7. Changelog *GundoChangelog*
|
7. Changelog *GundoChangelog*
|
||||||
|
|
||||||
|
v2.2.2
|
||||||
|
* More performance improvements.
|
||||||
|
v2.2.1
|
||||||
|
* Refactoring and performance improvements.
|
||||||
|
v2.2.0
|
||||||
|
* Add the g:gundo_close_on_revert setting.
|
||||||
|
* Fix a bug with the splitbelow setting.
|
||||||
v2.1.1
|
v2.1.1
|
||||||
* Fix a bug with the movement key mappings.
|
* Fix a bug with the movement key mappings.
|
||||||
v2.1.0
|
v2.1.0
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
*pi_getscript.txt* For Vim version 7.0. Last change: 2008 Jan 07
|
*pi_getscript.txt* For Vim version 7.0. Last change: 2011 May 31
|
||||||
>
|
>
|
||||||
GETSCRIPT REFERENCE MANUAL by Charles E. Campbell, Jr.
|
GETSCRIPT REFERENCE MANUAL by Charles E. Campbell, Jr.
|
||||||
<
|
<
|
||||||
Authors: Charles E. Campbell, Jr. <NdrOchip@ScampbellPfamilyA.Mbiz>
|
Authors: Charles E. Campbell, Jr. <NdrOchip@ScampbellPfamilyA.Mbiz>
|
||||||
(remove NOSPAM from the email address)
|
(remove NOSPAM from the email address)
|
||||||
*GetLatestVimScripts-copyright*
|
*GetLatestVimScripts-copyright*
|
||||||
Copyright: (c) 2004-2006 by Charles E. Campbell, Jr. *glvs-copyright*
|
Copyright: (c) 2004-2010 by Charles E. Campbell, Jr. *glvs-copyright*
|
||||||
The VIM LICENSE applies to getscript.vim and
|
The VIM LICENSE applies to getscript.vim and
|
||||||
pi_getscript.txt (see |copyright|) except use
|
pi_getscript.txt (see |copyright|) except use
|
||||||
"getscript" instead of "Vim". No warranty, express or implied.
|
"getscript" instead of "Vim". No warranty, express or implied.
|
||||||
@ -51,7 +51,7 @@ The GetLatestVimScripts.dist file serves as an example and a template for your
|
|||||||
own personal list. Feel free to remove all the scripts mentioned within it;
|
own personal list. Feel free to remove all the scripts mentioned within it;
|
||||||
the "important" part of it is the first two lines.
|
the "important" part of it is the first two lines.
|
||||||
|
|
||||||
Your computer needs to have wget for GetLatestVimScripts to do its work.
|
Your computer needs to have wget or curl for GetLatestVimScripts to do its work.
|
||||||
|
|
||||||
1. if compressed: gunzip getscript.vba.gz
|
1. if compressed: gunzip getscript.vba.gz
|
||||||
2. Unix:
|
2. Unix:
|
||||||
@ -76,8 +76,10 @@ Your computer needs to have wget for GetLatestVimScripts to do its work.
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
3. GetLatestVimScripts Usage *glvs-usage* *:GLVS*
|
3. GetLatestVimScripts Usage *glvs-usage* *:GLVS*
|
||||||
|
|
||||||
Unless its been defined elsewhere, >
|
Unless it has been defined elsewhere, >
|
||||||
|
|
||||||
:GLVS
|
:GLVS
|
||||||
|
|
||||||
will invoke GetLatestVimScripts(). If some other plugin has defined that
|
will invoke GetLatestVimScripts(). If some other plugin has defined that
|
||||||
command, then you may type
|
command, then you may type
|
||||||
>
|
>
|
||||||
@ -127,7 +129,8 @@ click on the script's link, you'll see a line resembling
|
|||||||
http://vim.sourceforge.net/scripts/script.php?script_id=40
|
http://vim.sourceforge.net/scripts/script.php?script_id=40
|
||||||
|
|
||||||
The "40" happens to be a ScriptID that GetLatestVimScripts needs to
|
The "40" happens to be a ScriptID that GetLatestVimScripts needs to
|
||||||
download the associated page.
|
download the associated page, and is assigned by vim.sf.net itself
|
||||||
|
during initial uploading of the plugin.
|
||||||
|
|
||||||
The second number on each line gives the script's SourceID. The SourceID
|
The second number on each line gives the script's SourceID. The SourceID
|
||||||
records the count of uploaded scripts as determined by vim.sf.net; hence it
|
records the count of uploaded scripts as determined by vim.sf.net; hence it
|
||||||
@ -136,7 +139,7 @@ insures that GetLatestVimScripts will assume that the script it has is
|
|||||||
out-of-date.
|
out-of-date.
|
||||||
|
|
||||||
The SourceID is extracted by GetLatestVimScripts from the script's page on
|
The SourceID is extracted by GetLatestVimScripts from the script's page on
|
||||||
vim.sf.net; whenever its greater than the one stored in the
|
vim.sf.net; whenever it is greater than the one stored in the
|
||||||
GetLatestVimScripts.dat file, the script will be downloaded
|
GetLatestVimScripts.dat file, the script will be downloaded
|
||||||
(see |GetLatestVimScripts_dat|).
|
(see |GetLatestVimScripts_dat|).
|
||||||
|
|
||||||
@ -151,19 +154,39 @@ This comment line tells getscript.vim to check vimscript #884 and that the
|
|||||||
script is automatically installable. Getscript will also use this line to
|
script is automatically installable. Getscript will also use this line to
|
||||||
help build the GetLatestVimScripts.dat file, by including a line such as: >
|
help build the GetLatestVimScripts.dat file, by including a line such as: >
|
||||||
|
|
||||||
884 1 AutoAlign.vim
|
884 1 :AutoInstall: AutoAlign.vim
|
||||||
<
|
<
|
||||||
in it an AutoAlign.vim line isn't already in GetLatestVimScripts.dat file.
|
assuming that such a line isn't already in GetLatestVimScripts.dat file.
|
||||||
See |glvs-plugins| for more. Thus, GetLatestVimScripts thus provides a
|
See |glvs-plugins| for more. Thus, GetLatestVimScripts thus provides a
|
||||||
comprehensive ability to keep your plugins up-to-date!
|
comprehensive ability to keep your plugins up-to-date!
|
||||||
|
|
||||||
|
In summary:
|
||||||
|
|
||||||
|
* Optionally tell getscript that it is allowed to build/append a
|
||||||
|
GetLatestVimScripts.dat file based upon already installed plugins: >
|
||||||
|
let g:GetLatestVimScripts_allowautoinstall=1
|
||||||
|
<
|
||||||
|
* A line such as >
|
||||||
|
" GetLatestVimScripts: 884 1 :AutoInstall: AutoAlign.vim
|
||||||
|
< in an already-downloaded plugin constitutes the concurrence of the
|
||||||
|
plugin author that getscript may do AutoInstall. Not all plugins
|
||||||
|
may be AutoInstall-able, and the plugin's author is best situated
|
||||||
|
to know whether or not his/her plugin will AutoInstall properly.
|
||||||
|
|
||||||
|
* A line such as >
|
||||||
|
884 1 :AutoInstall: AutoAlign.vim
|
||||||
|
< in your GetLatestVimScripts.dat file constitutes your permission
|
||||||
|
to getscript to do AutoInstall. AutoInstall requires both your
|
||||||
|
and the plugin author's permission. See |GetLatestVimScripts_dat|.
|
||||||
|
|
||||||
|
|
||||||
*GetLatestVimScripts_dat*
|
*GetLatestVimScripts_dat*
|
||||||
As an example of a <GetLatestVimScripts.dat> file:
|
As an example of a <GetLatestVimScripts.dat> file:
|
||||||
>
|
>
|
||||||
ScriptID SourceID Filename
|
ScriptID SourceID Filename
|
||||||
--------------------------
|
--------------------------
|
||||||
294 1 Align.vim
|
294 1 :AutoInstall: Align.vim
|
||||||
120 2 decho.vim
|
120 2 Decho.vim
|
||||||
40 3 DrawIt.tar.gz
|
40 3 DrawIt.tar.gz
|
||||||
451 4 EasyAccents.vim
|
451 4 EasyAccents.vim
|
||||||
195 5 engspchk.vim
|
195 5 engspchk.vim
|
||||||
@ -176,6 +199,8 @@ Note: the first two lines are required, but essentially act as comments.
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
5. GetLatestVimScripts Friendly Plugins *getscript-plugins* *glvs-plugins*
|
5. GetLatestVimScripts Friendly Plugins *getscript-plugins* *glvs-plugins*
|
||||||
|
|
||||||
|
(this section is for plugin authors)~
|
||||||
|
|
||||||
If a plugin author includes the following comment anywhere in their plugin,
|
If a plugin author includes the following comment anywhere in their plugin,
|
||||||
GetLatestVimScripts will find it and use it to automatically build the user's
|
GetLatestVimScripts will find it and use it to automatically build the user's
|
||||||
GetLatestVimScripts.dat files:
|
GetLatestVimScripts.dat files:
|
||||||
@ -191,15 +216,24 @@ plus any additional lines describing any plugin dependencies it may have.
|
|||||||
Same format, of course!
|
Same format, of course!
|
||||||
|
|
||||||
If your command is auto-installable (see |glvs-autoinstall|), and most scripts
|
If your command is auto-installable (see |glvs-autoinstall|), and most scripts
|
||||||
are, then you may include :AutoInstall: at the start of "yourscriptname".
|
are, then you may include :AutoInstall: just before "yourscriptname":
|
||||||
|
>
|
||||||
|
src_id
|
||||||
|
v
|
||||||
|
" GetLatestVimScripts: ### ### :AutoInstall: yourscriptname
|
||||||
|
^
|
||||||
|
scriptid
|
||||||
|
<
|
||||||
|
NOTE: The :AutoInstall: feature requires both the plugin author's and~
|
||||||
|
the user's permission to operate!~
|
||||||
|
|
||||||
GetLatestVimScripts commands for those scripts are then appended, if not
|
GetLatestVimScripts commands for those scripts are then appended, if not
|
||||||
already present, to the user's GetLatest/GetLatestVimScripts.dat file. Its a
|
already present, to the user's GetLatest/GetLatestVimScripts.dat file. It is
|
||||||
relatively painless way to automate the acquisition of any scripts your
|
a relatively painless way to automate the acquisition of any scripts your
|
||||||
plugins depend upon.
|
plugins depend upon.
|
||||||
|
|
||||||
Now, as an author, you probably don't want GetLatestVimScripts to download
|
Now, as an author, you probably don't want GetLatestVimScripts to download
|
||||||
your own scripts for you yourself, thereby overwriting your not-yet-released
|
your own scripts atop your own copy, thereby overwriting your not-yet-released
|
||||||
hard work. GetLatestVimScripts provides a solution for this: put
|
hard work. GetLatestVimScripts provides a solution for this: put
|
||||||
>
|
>
|
||||||
0 0 yourscriptname
|
0 0 yourscriptname
|
||||||
@ -290,14 +324,19 @@ after/syntax/c.vim contained in it to overwrite a user's c.vim.
|
|||||||
This variable holds the options to be used with the
|
This variable holds the options to be used with the
|
||||||
g:GetLatestVimScripts_wget command.
|
g:GetLatestVimScripts_wget command.
|
||||||
>
|
>
|
||||||
g:getLatestVimScripts_allowautoinstall
|
g:GetLatestVimScripts_allowautoinstall
|
||||||
< default= 1
|
< default= 1
|
||||||
This variable indicates whether GetLatestVimScripts is allowed
|
This variable indicates whether GetLatestVimScripts is allowed
|
||||||
to attempt to automatically install scripts. Note that it
|
to attempt to automatically install scripts. Furthermore, the
|
||||||
doesn't understand vimballs (yet). Furthermore, the plugin
|
plugin author has to have explicitly indicated that his/her
|
||||||
author has to have explicitly indicated that his/her plugin
|
plugin is automatically installable (via the :AutoInstall:
|
||||||
is automatically installable.
|
keyword in the GetLatestVimScripts comment line).
|
||||||
|
>
|
||||||
|
g:GetLatestVimScripts_autoinstalldir
|
||||||
|
< default= $HOME/.vim (linux)
|
||||||
|
default= $HOME/vimfiles (windows)
|
||||||
|
Override where :AutoInstall: scripts will be installed.
|
||||||
|
Doesn't override vimball installation.
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
8. GetLatestVimScripts Algorithm *glvs-algorithm* *glvs-alg*
|
8. GetLatestVimScripts Algorithm *glvs-algorithm* *glvs-alg*
|
||||||
@ -335,6 +374,14 @@ The AutoInstall process will:
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
9. GetLatestVimScripts History *getscript-history* *glvs-hist* {{{1
|
9. GetLatestVimScripts History *getscript-history* *glvs-hist* {{{1
|
||||||
|
|
||||||
|
v33 May 31, 2011 : * using fnameescape() instead of escape()
|
||||||
|
* *.xz support
|
||||||
|
v32 Jun 19, 2010 : * (Jan Steffens) added support for xz compression
|
||||||
|
v31 Jun 29, 2008 : * (Bill McCarthy) fixed having hls enabled with getscript
|
||||||
|
* (David Schaefer) the acd option interferes with vimballs
|
||||||
|
Solution: bypass the acd option
|
||||||
|
v30 Jun 13, 2008 : * GLVS now checks for existence of fnameescape() and will
|
||||||
|
issue an error message if it is not supported
|
||||||
v29 Jan 07, 2008 : * Bram M pointed out that cpo is a global option and that
|
v29 Jan 07, 2008 : * Bram M pointed out that cpo is a global option and that
|
||||||
getscriptPlugin.vim was setting it but not restoring it.
|
getscriptPlugin.vim was setting it but not restoring it.
|
||||||
v28 Jan 02, 2008 : * improved shell quoting character handling, cygwin
|
v28 Jan 02, 2008 : * improved shell quoting character handling, cygwin
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
*pi_netrw.txt* For Vim version 7.3. Last change: 2011 Apr 01
|
*pi_netrw.txt* For Vim version 7.3. Last change: 2011 May 31
|
||||||
|
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
NETRW REFERENCE MANUAL by Charles E. Campbell, Jr.
|
NETRW REFERENCE MANUAL by Charles E. Campbell, Jr.
|
||||||
@ -273,7 +273,7 @@ SOURCING *netrw-source* {{{2
|
|||||||
:Nsource "scp://[user@]machine[[:#]port]/path" uses scp
|
:Nsource "scp://[user@]machine[[:#]port]/path" uses scp
|
||||||
:Nsource "sftp://[user@]machine/path" uses sftp
|
:Nsource "sftp://[user@]machine/path" uses sftp
|
||||||
|
|
||||||
DIRECTORY LISTING *netrw-dirlist* {{{2
|
DIRECTORY LISTING *netrw-trailingslash* *netrw-dirlist* {{{2
|
||||||
|
|
||||||
One may browse a directory to get a listing by simply attempting to
|
One may browse a directory to get a listing by simply attempting to
|
||||||
edit the directory: >
|
edit the directory: >
|
||||||
@ -281,14 +281,15 @@ DIRECTORY LISTING *netrw-dirlist* {{{2
|
|||||||
:e scp://[user]@hostname/path/
|
:e scp://[user]@hostname/path/
|
||||||
:e ftp://[user]@hostname/path/
|
:e ftp://[user]@hostname/path/
|
||||||
<
|
<
|
||||||
For remote directories (ie. those using scp or ftp), that trailing
|
For remote directory listings (ie. those using scp or ftp), that
|
||||||
"/" is necessary (the slash tells netrw to treat the argument as a
|
trailing "/" is necessary (the slash tells netrw to treat the argument
|
||||||
directory to browse instead of a file to download).
|
as a directory to browse instead of as a file to download).
|
||||||
|
|
||||||
However, the Nread command can also be used to accomplish this:
|
The Nread command may also be used to accomplish this (again, that
|
||||||
|
trailing slash is necessary): >
|
||||||
|
|
||||||
:Nread [protocol]://[user]@hostname/path/
|
:Nread [protocol]://[user]@hostname/path/
|
||||||
|
<
|
||||||
*netrw-login* *netrw-password*
|
*netrw-login* *netrw-password*
|
||||||
CHANGING USERID AND PASSWORD *netrw-chgup* *netrw-userpass* {{{2
|
CHANGING USERID AND PASSWORD *netrw-chgup* *netrw-userpass* {{{2
|
||||||
|
|
||||||
@ -2158,8 +2159,8 @@ your browsing preferences. (see also: |netrw-settings|)
|
|||||||
*g:netrw_mkdir_cmd* command for making a remote directory
|
*g:netrw_mkdir_cmd* command for making a remote directory
|
||||||
default: "ssh USEPORT HOSTNAME mkdir"
|
default: "ssh USEPORT HOSTNAME mkdir"
|
||||||
|
|
||||||
*g:netrw_mousemaps* =1 (default) enables the mouse buttons
|
*g:netrw_mousemaps* =1 (default) enables mouse buttons while
|
||||||
while browsing:
|
browsing to:
|
||||||
leftmouse : open file/directory
|
leftmouse : open file/directory
|
||||||
shift-leftmouse : mark file
|
shift-leftmouse : mark file
|
||||||
middlemouse : same as P
|
middlemouse : same as P
|
||||||
@ -2274,8 +2275,11 @@ your browsing preferences. (see also: |netrw-settings|)
|
|||||||
|
|
||||||
*g:netrw_winsize* specify initial size of new windows made with
|
*g:netrw_winsize* specify initial size of new windows made with
|
||||||
"o" (see |netrw-o|), "v" (see |netrw-v|),
|
"o" (see |netrw-o|), "v" (see |netrw-v|),
|
||||||
|:Hexplore| or |:Vexplore|.
|
|:Hexplore| or |:Vexplore|. The g:netrw_winsize
|
||||||
default: ""
|
is an integer describing the percentage of the
|
||||||
|
current netrw buffer's window to be used for
|
||||||
|
the new window.
|
||||||
|
default: 50 (for 50%)
|
||||||
|
|
||||||
*g:netrw_xstrlen* Controls how netrw computes string lengths,
|
*g:netrw_xstrlen* Controls how netrw computes string lengths,
|
||||||
including multi-byte characters' string
|
including multi-byte characters' string
|
||||||
@ -2660,7 +2664,7 @@ Associated setting variables: |g:netrw_chgwin|
|
|||||||
|
|
||||||
*netrw-p11*
|
*netrw-p11*
|
||||||
P11. I want to have two windows; a thin one on the left and my editing
|
P11. I want to have two windows; a thin one on the left and my editing
|
||||||
window on the right. How can I do this?
|
window on the right. How may I accomplish this?
|
||||||
|
|
||||||
* Put the following line in your <.vimrc>:
|
* Put the following line in your <.vimrc>:
|
||||||
let g:netrw_altv = 1
|
let g:netrw_altv = 1
|
||||||
@ -2706,7 +2710,45 @@ Associated setting variables: |g:netrw_chgwin|
|
|||||||
"let g:netrw_sftp_cmd = "d:\\dev\\putty\\PSFTP.exe"
|
"let g:netrw_sftp_cmd = "d:\\dev\\putty\\PSFTP.exe"
|
||||||
"let g:netrw_scp_cmd = "d:\\dev\\putty\\PSCP.exe"
|
"let g:netrw_scp_cmd = "d:\\dev\\putty\\PSCP.exe"
|
||||||
<
|
<
|
||||||
|
*netrw-p14*
|
||||||
|
P14. I'd would like to speed up writes using Nwrite and scp/ssh
|
||||||
|
style connections. How? (Thomer M. Gil)
|
||||||
|
|
||||||
|
Try using ssh's ControlMaster and ControlPath (see the ssh_config
|
||||||
|
man page) to share multiple ssh connections over a single network
|
||||||
|
connection. That cuts out the cryptographic handshake on each
|
||||||
|
file write, sometimes speeding it up by an order of magnitude.
|
||||||
|
(see http://thomer.com/howtos/netrw_ssh.html)
|
||||||
|
(included by permission)
|
||||||
|
|
||||||
|
Add the following to your ~/.ssh/config: >
|
||||||
|
|
||||||
|
# you change "*" to the hostname you care about
|
||||||
|
Host *
|
||||||
|
ControlMaster auto
|
||||||
|
ControlPath /tmp/%r@%h:%p
|
||||||
|
|
||||||
|
< Then create an ssh connection to the host and leave it running: >
|
||||||
|
|
||||||
|
ssh -N host.domain.com
|
||||||
|
|
||||||
|
< Now remotely open a file with Vim's Netrw and enjoy the
|
||||||
|
zippiness: >
|
||||||
|
|
||||||
|
vim scp://host.domain.com//home/user/.bashrc
|
||||||
|
<
|
||||||
|
*netrw-p15*
|
||||||
|
P15. How may I use a double-click instead of netrw's usual single click
|
||||||
|
to open a file or directory? (Ben Fritz)
|
||||||
|
|
||||||
|
First, disable netrw's mapping with >
|
||||||
|
let g:netrw_mousemaps= 0
|
||||||
|
< and then create a netrw buffer only mapping in
|
||||||
|
$HOME/.vim/after/ftplugin/netrw.vim: >
|
||||||
|
nmap <buffer> <2-leftmouse> <CR>
|
||||||
|
< Note that setting g:netrw_mousemaps to zero will turn off
|
||||||
|
all netrw's mouse mappings, not just the <leftmouse> one.
|
||||||
|
(see |g:netrw_mousemaps|)
|
||||||
|
|
||||||
==============================================================================
|
==============================================================================
|
||||||
11. Debugging Netrw Itself *netrw-debug* {{{1
|
11. Debugging Netrw Itself *netrw-debug* {{{1
|
||||||
@ -2762,6 +2804,15 @@ which is loaded automatically at startup (assuming :set nocp).
|
|||||||
==============================================================================
|
==============================================================================
|
||||||
12. History *netrw-history* {{{1
|
12. History *netrw-history* {{{1
|
||||||
|
|
||||||
|
v142: Apr 06, 2011 * I modified NetrwRemoteListing() to use
|
||||||
|
shellescape(fnameescape(s:path),1) for
|
||||||
|
the benefit of those using scp://.../
|
||||||
|
with subdirectories having spaces.
|
||||||
|
Problem reported by: Gilles Charron
|
||||||
|
Apr 18, 2011 * s:NetrwMethod() attempts to issue an
|
||||||
|
error message when given a malformed url
|
||||||
|
Apr 29, 2011 * converted most mousemaps to use <Plug>s
|
||||||
|
* |g:netrw_winsize|'s meaning changed
|
||||||
v141: Aug 28, 2010 * added -s:... support for Windows ftp
|
v141: Aug 28, 2010 * added -s:... support for Windows ftp
|
||||||
* restored 2-leftmouse for :Rex-like return
|
* restored 2-leftmouse for :Rex-like return
|
||||||
* added balloon help for banner
|
* added balloon help for banner
|
||||||
|
@ -1574,6 +1574,7 @@ glvs-options pi_getscript.txt /*glvs-options*
|
|||||||
glvs-plugins pi_getscript.txt /*glvs-plugins*
|
glvs-plugins pi_getscript.txt /*glvs-plugins*
|
||||||
glvs-usage pi_getscript.txt /*glvs-usage*
|
glvs-usage pi_getscript.txt /*glvs-usage*
|
||||||
gundo.txt gundo.txt /*gundo.txt*
|
gundo.txt gundo.txt /*gundo.txt*
|
||||||
|
gundo_close_on_revert gundo.txt /*gundo_close_on_revert*
|
||||||
gundo_disable gundo.txt /*gundo_disable*
|
gundo_disable gundo.txt /*gundo_disable*
|
||||||
gundo_help gundo.txt /*gundo_help*
|
gundo_help gundo.txt /*gundo_help*
|
||||||
gundo_map_move_newer gundo.txt /*gundo_map_move_newer*
|
gundo_map_move_newer gundo.txt /*gundo_map_move_newer*
|
||||||
@ -1731,6 +1732,8 @@ netrw-p10 pi_netrw.txt /*netrw-p10*
|
|||||||
netrw-p11 pi_netrw.txt /*netrw-p11*
|
netrw-p11 pi_netrw.txt /*netrw-p11*
|
||||||
netrw-p12 pi_netrw.txt /*netrw-p12*
|
netrw-p12 pi_netrw.txt /*netrw-p12*
|
||||||
netrw-p13 pi_netrw.txt /*netrw-p13*
|
netrw-p13 pi_netrw.txt /*netrw-p13*
|
||||||
|
netrw-p14 pi_netrw.txt /*netrw-p14*
|
||||||
|
netrw-p15 pi_netrw.txt /*netrw-p15*
|
||||||
netrw-p2 pi_netrw.txt /*netrw-p2*
|
netrw-p2 pi_netrw.txt /*netrw-p2*
|
||||||
netrw-p3 pi_netrw.txt /*netrw-p3*
|
netrw-p3 pi_netrw.txt /*netrw-p3*
|
||||||
netrw-p4 pi_netrw.txt /*netrw-p4*
|
netrw-p4 pi_netrw.txt /*netrw-p4*
|
||||||
@ -1779,6 +1782,7 @@ netrw-start pi_netrw.txt /*netrw-start*
|
|||||||
netrw-t pi_netrw.txt /*netrw-t*
|
netrw-t pi_netrw.txt /*netrw-t*
|
||||||
netrw-texplore pi_netrw.txt /*netrw-texplore*
|
netrw-texplore pi_netrw.txt /*netrw-texplore*
|
||||||
netrw-todo pi_netrw.txt /*netrw-todo*
|
netrw-todo pi_netrw.txt /*netrw-todo*
|
||||||
|
netrw-trailingslash pi_netrw.txt /*netrw-trailingslash*
|
||||||
netrw-transparent pi_netrw.txt /*netrw-transparent*
|
netrw-transparent pi_netrw.txt /*netrw-transparent*
|
||||||
netrw-u pi_netrw.txt /*netrw-u*
|
netrw-u pi_netrw.txt /*netrw-u*
|
||||||
netrw-updir pi_netrw.txt /*netrw-updir*
|
netrw-updir pi_netrw.txt /*netrw-updir*
|
||||||
|
@ -78,6 +78,8 @@ elseif &filetype == 'xhtml'
|
|||||||
let b:xml_use_xhtml = 1
|
let b:xml_use_xhtml = 1
|
||||||
en
|
en
|
||||||
|
|
||||||
|
let b:undo_ftplugin = "setlocal cms< isk<"
|
||||||
|
\ . "| unlet b:match_ignorecase b:match_words"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
" -*- vim -*-
|
" -*- vim -*-
|
||||||
" FILE: "/home/wlee/.vim/plugin/DirDiff.vim" {{{
|
" FILE: "/home/wlee/.vim/plugin/DirDiff.vim" {{{
|
||||||
" LAST MODIFICATION: "Mon, 20 Oct 2008 09:04:59 -0500 (wlee)"
|
" LAST MODIFICATION: "Fri, 29 Jul 2011 08:30:07 -0500 (wlee)"
|
||||||
" HEADER MAINTAINED BY: N/A
|
" HEADER MAINTAINED BY: N/A
|
||||||
" VERSION: 1.1.3
|
" VERSION: 1.1.4
|
||||||
" (C) 2001-2010 by William Lee, <wl1012@yahoo.com>
|
" (C) 2001-2011 by William Lee, <wl1012@yahoo.com>
|
||||||
" }}}
|
" }}}
|
||||||
|
|
||||||
|
|
||||||
@ -116,7 +116,7 @@
|
|||||||
" William Lee <wl1012@yahoo.com>
|
" William Lee <wl1012@yahoo.com>
|
||||||
"
|
"
|
||||||
" LICENSE:
|
" LICENSE:
|
||||||
" Copyright (c) 2001-2006 William Lee
|
" Copyright (c) 2001-2011 William Lee
|
||||||
" All rights reserved.
|
" All rights reserved.
|
||||||
"
|
"
|
||||||
" Redistribution and use in source and binary forms, with or without
|
" Redistribution and use in source and binary forms, with or without
|
||||||
@ -151,6 +151,7 @@
|
|||||||
" Salman Halim, Yosuke Kimura, and others for their suggestions
|
" Salman Halim, Yosuke Kimura, and others for their suggestions
|
||||||
"
|
"
|
||||||
" HISTORY:
|
" HISTORY:
|
||||||
|
" 1.1.4 - Fixed split windows problems caused by some .vimrc settings.
|
||||||
" 1.1.3 - Applied the patch to 1.1.2 by Wu WeiWei in order to make diff
|
" 1.1.3 - Applied the patch to 1.1.2 by Wu WeiWei in order to make diff
|
||||||
" that's localized in Chinese work.
|
" that's localized in Chinese work.
|
||||||
" 1.1.2 - Applied the patch to 1.1.0 instead of 1.0.2. Please do not use
|
" 1.1.2 - Applied the patch to 1.1.0 instead of 1.0.2. Please do not use
|
||||||
@ -386,7 +387,7 @@ function! <SID>DirDiff(srcA, srcB)
|
|||||||
echo "Diffing directories, it may take a while..."
|
echo "Diffing directories, it may take a while..."
|
||||||
let error = <SID>DirDiffExec(cmd, 0)
|
let error = <SID>DirDiffExec(cmd, 0)
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
echo "There is no diff here."
|
redraw | echom "diff found no differences - directories match."
|
||||||
return
|
return
|
||||||
endif
|
endif
|
||||||
silent exe "edit ".DiffBuffer
|
silent exe "edit ".DiffBuffer
|
||||||
@ -513,6 +514,17 @@ function! <SID>CloseDiffWindows()
|
|||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
function! <SID>EscapeFileName(path)
|
||||||
|
if (v:version >= 702)
|
||||||
|
return fnameescape(a:path)
|
||||||
|
else
|
||||||
|
" This is not a complete list of escaped character, so it's
|
||||||
|
" not as sophisicated as the fnameescape, but this should
|
||||||
|
" cover most of the cases and should work for Vim version <
|
||||||
|
" 7.2
|
||||||
|
return escape(a:path, " \t\n*?[{`$\\%#'\"|!<")
|
||||||
|
endif
|
||||||
|
endfunction
|
||||||
|
|
||||||
function! <SID>DirDiffOpen()
|
function! <SID>DirDiffOpen()
|
||||||
" First dehighlight the last marked
|
" First dehighlight the last marked
|
||||||
@ -526,8 +538,15 @@ function! <SID>DirDiffOpen()
|
|||||||
let dirA = <SID>GetBaseDir("A")
|
let dirA = <SID>GetBaseDir("A")
|
||||||
let dirB = <SID>GetBaseDir("B")
|
let dirB = <SID>GetBaseDir("B")
|
||||||
|
|
||||||
|
" Save the number of this window, to which we wish to return
|
||||||
|
" This is required in case there are other windows open
|
||||||
|
let thisWindow = winnr()
|
||||||
|
|
||||||
call <SID>CloseDiffWindows()
|
call <SID>CloseDiffWindows()
|
||||||
|
|
||||||
|
" Ensure we're in the right window
|
||||||
|
exec thisWindow.'wincmd w'
|
||||||
|
|
||||||
let line = getline(".")
|
let line = getline(".")
|
||||||
" Parse the line and see whether it's a "Only in" or "Files Differ"
|
" Parse the line and see whether it's a "Only in" or "Files Differ"
|
||||||
call <SID>HighlightLine()
|
call <SID>HighlightLine()
|
||||||
@ -543,7 +562,7 @@ function! <SID>DirDiffOpen()
|
|||||||
endif
|
endif
|
||||||
split
|
split
|
||||||
wincmd k
|
wincmd k
|
||||||
silent exec "edit ".fnameescape(fileToOpen)
|
silent exec "edit ". <SID>EscapeFileName(fileToOpen)
|
||||||
" Fool the window saying that this is diff
|
" Fool the window saying that this is diff
|
||||||
diffthis
|
diffthis
|
||||||
wincmd j
|
wincmd j
|
||||||
@ -554,8 +573,15 @@ function! <SID>DirDiffOpen()
|
|||||||
"Open the diff windows
|
"Open the diff windows
|
||||||
split
|
split
|
||||||
wincmd k
|
wincmd k
|
||||||
silent exec "edit ".fnameescape(fileB)
|
silent exec "edit ".<SID>EscapeFileName(fileB)
|
||||||
silent exec "vert diffsplit ".fnameescape(fileA)
|
|
||||||
|
" To ensure that A is on the left and B on the right, splitright must be off
|
||||||
|
" let saved_splitright = &splitright
|
||||||
|
" set nosplitright
|
||||||
|
" silent exec "vert diffsplit ".<SID>EscapeFileName(fileA)
|
||||||
|
" let &splitright = saved_splitright
|
||||||
|
silent exec "leftabove vert diffsplit ".<SID>EscapeFileName(fileA)
|
||||||
|
|
||||||
" Go back to the diff window
|
" Go back to the diff window
|
||||||
wincmd j
|
wincmd j
|
||||||
" Resize the window
|
" Resize the window
|
||||||
|
@ -19,7 +19,7 @@ if &cp || exists("g:loaded_getscriptPlugin")
|
|||||||
endif
|
endif
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let g:loaded_getscriptPlugin = "v29"
|
let g:loaded_getscriptPlugin = "v33"
|
||||||
let s:keepcpo = &cpo
|
let s:keepcpo = &cpo
|
||||||
set cpo&vim
|
set cpo&vim
|
||||||
|
|
||||||
|
573
vimfiles/plugin/gundo.py
Executable file
573
vimfiles/plugin/gundo.py
Executable file
@ -0,0 +1,573 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# File: gundo.py
|
||||||
|
# Description: vim global plugin to visualize your undo tree
|
||||||
|
# Maintainer: Steve Losh <steve@stevelosh.com>
|
||||||
|
# License: GPLv2+ -- look it up.
|
||||||
|
# Notes: Much of this code was thiefed from Mercurial, and the rest was
|
||||||
|
# heavily inspired by scratch.vim and histwin.vim.
|
||||||
|
#
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
import difflib
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import vim
|
||||||
|
|
||||||
|
# Mercurial's graphlog code
|
||||||
|
def asciiedges(seen, rev, parents):
|
||||||
|
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
||||||
|
if rev not in seen:
|
||||||
|
seen.append(rev)
|
||||||
|
nodeidx = seen.index(rev)
|
||||||
|
|
||||||
|
knownparents = []
|
||||||
|
newparents = []
|
||||||
|
for parent in parents:
|
||||||
|
if parent in seen:
|
||||||
|
knownparents.append(parent)
|
||||||
|
else:
|
||||||
|
newparents.append(parent)
|
||||||
|
|
||||||
|
ncols = len(seen)
|
||||||
|
seen[nodeidx:nodeidx + 1] = newparents
|
||||||
|
edges = [(nodeidx, seen.index(p)) for p in knownparents]
|
||||||
|
|
||||||
|
if len(newparents) > 0:
|
||||||
|
edges.append((nodeidx, nodeidx))
|
||||||
|
if len(newparents) > 1:
|
||||||
|
edges.append((nodeidx, nodeidx + 1))
|
||||||
|
|
||||||
|
nmorecols = len(seen) - ncols
|
||||||
|
return nodeidx, edges, ncols, nmorecols
|
||||||
|
|
||||||
|
def get_nodeline_edges_tail(
|
||||||
|
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
|
||||||
|
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
|
||||||
|
# Still going in the same non-vertical direction.
|
||||||
|
if n_columns_diff == -1:
|
||||||
|
start = max(node_index + 1, p_node_index)
|
||||||
|
tail = ["|", " "] * (start - node_index - 1)
|
||||||
|
tail.extend(["/", " "] * (n_columns - start))
|
||||||
|
return tail
|
||||||
|
else:
|
||||||
|
return ["\\", " "] * (n_columns - node_index - 1)
|
||||||
|
else:
|
||||||
|
return ["|", " "] * (n_columns - node_index - 1)
|
||||||
|
|
||||||
|
def draw_edges(edges, nodeline, interline):
|
||||||
|
for (start, end) in edges:
|
||||||
|
if start == end + 1:
|
||||||
|
interline[2 * end + 1] = "/"
|
||||||
|
elif start == end - 1:
|
||||||
|
interline[2 * start + 1] = "\\"
|
||||||
|
elif start == end:
|
||||||
|
interline[2 * start] = "|"
|
||||||
|
else:
|
||||||
|
nodeline[2 * end] = "+"
|
||||||
|
if start > end:
|
||||||
|
(start, end) = (end, start)
|
||||||
|
for i in range(2 * start + 1, 2 * end):
|
||||||
|
if nodeline[i] != "+":
|
||||||
|
nodeline[i] = "-"
|
||||||
|
|
||||||
|
def fix_long_right_edges(edges):
|
||||||
|
for (i, (start, end)) in enumerate(edges):
|
||||||
|
if end > start:
|
||||||
|
edges[i] = (start, end + 1)
|
||||||
|
|
||||||
|
def ascii(buf, state, type, char, text, coldata):
|
||||||
|
"""prints an ASCII graph of the DAG
|
||||||
|
|
||||||
|
takes the following arguments (one call per node in the graph):
|
||||||
|
|
||||||
|
- Somewhere to keep the needed state in (init to asciistate())
|
||||||
|
- Column of the current node in the set of ongoing edges.
|
||||||
|
- Type indicator of node data == ASCIIDATA.
|
||||||
|
- Payload: (char, lines):
|
||||||
|
- Character to use as node's symbol.
|
||||||
|
- List of lines to display as the node's text.
|
||||||
|
- Edges; a list of (col, next_col) indicating the edges between
|
||||||
|
the current node and its parents.
|
||||||
|
- Number of columns (ongoing edges) in the current revision.
|
||||||
|
- The difference between the number of columns (ongoing edges)
|
||||||
|
in the next revision and the number of columns (ongoing edges)
|
||||||
|
in the current revision. That is: -1 means one column removed;
|
||||||
|
0 means no columns added or removed; 1 means one column added.
|
||||||
|
"""
|
||||||
|
|
||||||
|
idx, edges, ncols, coldiff = coldata
|
||||||
|
assert -2 < coldiff < 2
|
||||||
|
if coldiff == -1:
|
||||||
|
# Transform
|
||||||
|
#
|
||||||
|
# | | | | | |
|
||||||
|
# o | | into o---+
|
||||||
|
# |X / |/ /
|
||||||
|
# | | | |
|
||||||
|
fix_long_right_edges(edges)
|
||||||
|
|
||||||
|
# add_padding_line says whether to rewrite
|
||||||
|
#
|
||||||
|
# | | | | | | | |
|
||||||
|
# | o---+ into | o---+
|
||||||
|
# | / / | | | # <--- padding line
|
||||||
|
# o | | | / /
|
||||||
|
# o | |
|
||||||
|
add_padding_line = (len(text) > 2 and coldiff == -1 and
|
||||||
|
[x for (x, y) in edges if x + 1 < y])
|
||||||
|
|
||||||
|
# fix_nodeline_tail says whether to rewrite
|
||||||
|
#
|
||||||
|
# | | o | | | | o | |
|
||||||
|
# | | |/ / | | |/ /
|
||||||
|
# | o | | into | o / / # <--- fixed nodeline tail
|
||||||
|
# | |/ / | |/ /
|
||||||
|
# o | | o | |
|
||||||
|
fix_nodeline_tail = len(text) <= 2 and not add_padding_line
|
||||||
|
|
||||||
|
# nodeline is the line containing the node character (typically o)
|
||||||
|
nodeline = ["|", " "] * idx
|
||||||
|
nodeline.extend([char, " "])
|
||||||
|
|
||||||
|
nodeline.extend(
|
||||||
|
get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
|
||||||
|
state[0], fix_nodeline_tail))
|
||||||
|
|
||||||
|
# shift_interline is the line containing the non-vertical
|
||||||
|
# edges between this entry and the next
|
||||||
|
shift_interline = ["|", " "] * idx
|
||||||
|
if coldiff == -1:
|
||||||
|
n_spaces = 1
|
||||||
|
edge_ch = "/"
|
||||||
|
elif coldiff == 0:
|
||||||
|
n_spaces = 2
|
||||||
|
edge_ch = "|"
|
||||||
|
else:
|
||||||
|
n_spaces = 3
|
||||||
|
edge_ch = "\\"
|
||||||
|
shift_interline.extend(n_spaces * [" "])
|
||||||
|
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
|
||||||
|
|
||||||
|
# draw edges from the current node to its parents
|
||||||
|
draw_edges(edges, nodeline, shift_interline)
|
||||||
|
|
||||||
|
# lines is the list of all graph lines to print
|
||||||
|
lines = [nodeline]
|
||||||
|
if add_padding_line:
|
||||||
|
lines.append(get_padding_line(idx, ncols, edges))
|
||||||
|
lines.append(shift_interline)
|
||||||
|
|
||||||
|
# make sure that there are as many graph lines as there are
|
||||||
|
# log strings
|
||||||
|
while len(text) < len(lines):
|
||||||
|
text.append("")
|
||||||
|
if len(lines) < len(text):
|
||||||
|
extra_interline = ["|", " "] * (ncols + coldiff)
|
||||||
|
while len(lines) < len(text):
|
||||||
|
lines.append(extra_interline)
|
||||||
|
|
||||||
|
# print lines
|
||||||
|
indentation_level = max(ncols, ncols + coldiff)
|
||||||
|
for (line, logstr) in zip(lines, text):
|
||||||
|
ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
|
||||||
|
buf.write(ln.rstrip() + '\n')
|
||||||
|
|
||||||
|
# ... and start over
|
||||||
|
state[0] = coldiff
|
||||||
|
state[1] = idx
|
||||||
|
|
||||||
|
def generate(dag, edgefn, current):
|
||||||
|
seen, state = [], [0, 0]
|
||||||
|
buf = Buffer()
|
||||||
|
for node, parents in list(dag):
|
||||||
|
if node.time:
|
||||||
|
age_label = age(int(node.time))
|
||||||
|
else:
|
||||||
|
age_label = 'Original'
|
||||||
|
line = '[%s] %s' % (node.n, age_label)
|
||||||
|
if node.n == current:
|
||||||
|
char = '@'
|
||||||
|
else:
|
||||||
|
char = 'o'
|
||||||
|
ascii(buf, state, 'C', char, [line], edgefn(seen, node, parents))
|
||||||
|
return buf.b
|
||||||
|
|
||||||
|
# Mercurial age function
|
||||||
|
|
||||||
|
agescales = [("year", 3600 * 24 * 365),
|
||||||
|
("month", 3600 * 24 * 30),
|
||||||
|
("week", 3600 * 24 * 7),
|
||||||
|
("day", 3600 * 24),
|
||||||
|
("hour", 3600),
|
||||||
|
("minute", 60),
|
||||||
|
("second", 1)]
|
||||||
|
|
||||||
|
def age(ts):
|
||||||
|
'''turn a timestamp into an age string.'''
|
||||||
|
|
||||||
|
def plural(t, c):
|
||||||
|
if c == 1:
|
||||||
|
return t
|
||||||
|
return t + "s"
|
||||||
|
def fmt(t, c):
|
||||||
|
return "%d %s" % (c, plural(t, c))
|
||||||
|
|
||||||
|
now = time.time()
|
||||||
|
then = ts
|
||||||
|
if then > now:
|
||||||
|
return 'in the future'
|
||||||
|
|
||||||
|
delta = max(1, int(now - then))
|
||||||
|
if delta > agescales[0][1] * 2:
|
||||||
|
return time.strftime('%Y-%m-%d', time.gmtime(float(ts)))
|
||||||
|
|
||||||
|
for t, s in agescales:
|
||||||
|
n = delta // s
|
||||||
|
if n >= 2 or s == 1:
|
||||||
|
return '%s ago' % fmt(t, n)
|
||||||
|
|
||||||
|
# Python Vim utility functions
|
||||||
|
|
||||||
|
normal = lambda s: vim.command('normal %s' % s)
|
||||||
|
|
||||||
|
MISSING_BUFFER = "Cannot find Gundo's target buffer (%s)"
|
||||||
|
MISSING_WINDOW = "Cannot find window (%s) for Gundo's target buffer (%s)"
|
||||||
|
|
||||||
|
def _check_sanity():
|
||||||
|
'''Check to make sure we're not crazy.
|
||||||
|
|
||||||
|
Does the following things:
|
||||||
|
|
||||||
|
* Make sure the target buffer still exists.
|
||||||
|
'''
|
||||||
|
b = int(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
if not vim.eval('bufloaded(%d)' % b):
|
||||||
|
vim.command('echo "%s"' % (MISSING_BUFFER % b))
|
||||||
|
return False
|
||||||
|
|
||||||
|
w = int(vim.eval('bufwinnr(%d)' % b))
|
||||||
|
if w == -1:
|
||||||
|
vim.command('echo "%s"' % (MISSING_WINDOW % (w, b)))
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _goto_window_for_buffer(b):
|
||||||
|
w = int(vim.eval('bufwinnr(%d)' % int(b)))
|
||||||
|
vim.command('%dwincmd w' % w)
|
||||||
|
|
||||||
|
def _goto_window_for_buffer_name(bn):
|
||||||
|
b = vim.eval('bufnr("%s")' % bn)
|
||||||
|
return _goto_window_for_buffer(b)
|
||||||
|
|
||||||
|
def _undo_to(n):
|
||||||
|
n = int(n)
|
||||||
|
if n == 0:
|
||||||
|
vim.command('silent earlier %s' % (int(vim.eval('&undolevels')) + 1))
|
||||||
|
else:
|
||||||
|
vim.command('silent undo %d' % n)
|
||||||
|
|
||||||
|
|
||||||
|
INLINE_HELP = '''\
|
||||||
|
" Gundo for %s (%d)
|
||||||
|
" j/k - move between undo states
|
||||||
|
" p - preview diff of selected and current states
|
||||||
|
" <cr> - revert to selected state
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
# Python undo tree data structures and functions
|
||||||
|
|
||||||
|
class Buffer(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.b = ''
|
||||||
|
|
||||||
|
def write(self, s):
|
||||||
|
self.b += s
|
||||||
|
|
||||||
|
class Node(object):
|
||||||
|
def __init__(self, n, parent, time, curhead):
|
||||||
|
self.n = int(n)
|
||||||
|
self.parent = parent
|
||||||
|
self.children = []
|
||||||
|
self.curhead = curhead
|
||||||
|
self.time = time
|
||||||
|
|
||||||
|
def _make_nodes(alts, nodes, parent=None):
|
||||||
|
p = parent
|
||||||
|
|
||||||
|
for alt in alts:
|
||||||
|
curhead = 'curhead' in alt
|
||||||
|
node = Node(n=alt['seq'], parent=p, time=alt['time'], curhead=curhead)
|
||||||
|
nodes.append(node)
|
||||||
|
if alt.get('alt'):
|
||||||
|
_make_nodes(alt['alt'], nodes, p)
|
||||||
|
p = node
|
||||||
|
|
||||||
|
def make_nodes():
|
||||||
|
ut = vim.eval('undotree()')
|
||||||
|
entries = ut['entries']
|
||||||
|
|
||||||
|
root = Node(0, None, False, 0)
|
||||||
|
nodes = []
|
||||||
|
_make_nodes(entries, nodes, root)
|
||||||
|
nodes.append(root)
|
||||||
|
nmap = dict((node.n, node) for node in nodes)
|
||||||
|
return nodes, nmap
|
||||||
|
|
||||||
|
def changenr(nodes):
|
||||||
|
_curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes))
|
||||||
|
if _curhead_l:
|
||||||
|
current = _curhead_l[0].parent.n
|
||||||
|
else:
|
||||||
|
current = int(vim.eval('changenr()'))
|
||||||
|
return current
|
||||||
|
|
||||||
|
# Gundo rendering
|
||||||
|
|
||||||
|
# Rendering utility functions
|
||||||
|
|
||||||
|
def _fmt_time(t):
|
||||||
|
return time.strftime('%Y-%m-%d %I:%M:%S %p', time.localtime(float(t)))
|
||||||
|
|
||||||
|
def _output_preview_text(lines):
|
||||||
|
_goto_window_for_buffer_name('__Gundo_Preview__')
|
||||||
|
vim.command('setlocal modifiable')
|
||||||
|
vim.current.buffer[:] = lines
|
||||||
|
vim.command('setlocal nomodifiable')
|
||||||
|
|
||||||
|
def _generate_preview_diff(current, node_before, node_after):
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
if not node_after.n: # we're at the original file
|
||||||
|
before_lines = []
|
||||||
|
|
||||||
|
_undo_to(0)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = 'n/a'
|
||||||
|
before_time = ''
|
||||||
|
after_name = 'Original'
|
||||||
|
after_time = ''
|
||||||
|
elif not node_before.n: # we're at a pseudo-root state
|
||||||
|
_undo_to(0)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = 'Original'
|
||||||
|
before_time = ''
|
||||||
|
after_name = node_after.n
|
||||||
|
after_time = _fmt_time(node_after.time)
|
||||||
|
else:
|
||||||
|
_undo_to(node_before.n)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = node_before.n
|
||||||
|
before_time = _fmt_time(node_before.time)
|
||||||
|
after_name = node_after.n
|
||||||
|
after_time = _fmt_time(node_after.time)
|
||||||
|
|
||||||
|
_undo_to(current)
|
||||||
|
|
||||||
|
return list(difflib.unified_diff(before_lines, after_lines,
|
||||||
|
before_name, after_name,
|
||||||
|
before_time, after_time))
|
||||||
|
|
||||||
|
def _generate_change_preview_diff(current, node_before, node_after):
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
_undo_to(node_before.n)
|
||||||
|
before_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
_undo_to(node_after.n)
|
||||||
|
after_lines = vim.current.buffer[:]
|
||||||
|
|
||||||
|
before_name = node_before.n or 'Original'
|
||||||
|
before_time = node_before.time and _fmt_time(node_before.time) or ''
|
||||||
|
after_name = node_after.n or 'Original'
|
||||||
|
after_time = node_after.time and _fmt_time(node_after.time) or ''
|
||||||
|
|
||||||
|
_undo_to(current)
|
||||||
|
|
||||||
|
return list(difflib.unified_diff(before_lines, after_lines,
|
||||||
|
before_name, after_name,
|
||||||
|
before_time, after_time))
|
||||||
|
|
||||||
|
def GundoRenderGraph():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
|
||||||
|
for node in nodes:
|
||||||
|
node.children = [n for n in nodes if n.parent == node]
|
||||||
|
|
||||||
|
def walk_nodes(nodes):
|
||||||
|
for node in nodes:
|
||||||
|
if node.parent:
|
||||||
|
yield (node, [node.parent])
|
||||||
|
else:
|
||||||
|
yield (node, [])
|
||||||
|
|
||||||
|
dag = sorted(nodes, key=lambda n: int(n.n), reverse=True)
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
result = generate(walk_nodes(dag), asciiedges, current).rstrip().splitlines()
|
||||||
|
result = [' ' + l for l in result]
|
||||||
|
|
||||||
|
target = (vim.eval('g:gundo_target_f'), int(vim.eval('g:gundo_target_n')))
|
||||||
|
|
||||||
|
if int(vim.eval('g:gundo_help')):
|
||||||
|
header = (INLINE_HELP % target).splitlines()
|
||||||
|
else:
|
||||||
|
header = []
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenGraph()')
|
||||||
|
vim.command('setlocal modifiable')
|
||||||
|
vim.current.buffer[:] = (header + result)
|
||||||
|
vim.command('setlocal nomodifiable')
|
||||||
|
|
||||||
|
i = 1
|
||||||
|
for line in result:
|
||||||
|
try:
|
||||||
|
line.split('[')[0].index('@')
|
||||||
|
i += 1
|
||||||
|
break
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
i += 1
|
||||||
|
vim.command('%d' % (i+len(header)-1))
|
||||||
|
|
||||||
|
def GundoRenderPreview():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_state = vim.eval('s:GundoGetTargetState()')
|
||||||
|
|
||||||
|
# Check that there's an undo state. There may not be if we're talking about
|
||||||
|
# a buffer with no changes yet.
|
||||||
|
if target_state == None:
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
target_state = int(target_state)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
node_after = nmap[target_state]
|
||||||
|
node_before = node_after.parent
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenPreview()')
|
||||||
|
_output_preview_text(_generate_preview_diff(current, node_before, node_after))
|
||||||
|
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
|
||||||
|
def GundoRenderChangePreview():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_state = vim.eval('s:GundoGetTargetState()')
|
||||||
|
|
||||||
|
# Check that there's an undo state. There may not be if we're talking about
|
||||||
|
# a buffer with no changes yet.
|
||||||
|
if target_state == None:
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
target_state = int(target_state)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
current = changenr(nodes)
|
||||||
|
|
||||||
|
node_after = nmap[target_state]
|
||||||
|
node_before = nmap[current]
|
||||||
|
|
||||||
|
vim.command('call s:GundoOpenPreview()')
|
||||||
|
_output_preview_text(_generate_change_preview_diff(current, node_before, node_after))
|
||||||
|
|
||||||
|
_goto_window_for_buffer_name('__Gundo__')
|
||||||
|
|
||||||
|
# Gundo undo/redo
|
||||||
|
|
||||||
|
def GundoRevert():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
||||||
|
back = vim.eval('g:gundo_target_n')
|
||||||
|
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
_undo_to(target_n)
|
||||||
|
|
||||||
|
vim.command('GundoRenderGraph')
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
|
||||||
|
if int(vim.eval('g:gundo_close_on_revert')):
|
||||||
|
vim.command('GundoToggle')
|
||||||
|
|
||||||
|
def GundoPlayTo():
|
||||||
|
if not _check_sanity():
|
||||||
|
return
|
||||||
|
|
||||||
|
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
||||||
|
back = int(vim.eval('g:gundo_target_n'))
|
||||||
|
|
||||||
|
vim.command('echo "%s"' % back)
|
||||||
|
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
normal('zR')
|
||||||
|
|
||||||
|
nodes, nmap = make_nodes()
|
||||||
|
|
||||||
|
start = nmap[changenr(nodes)]
|
||||||
|
end = nmap[target_n]
|
||||||
|
|
||||||
|
def _walk_branch(origin, dest):
|
||||||
|
rev = origin.n < dest.n
|
||||||
|
|
||||||
|
nodes = []
|
||||||
|
if origin.n > dest.n:
|
||||||
|
current, final = origin, dest
|
||||||
|
else:
|
||||||
|
current, final = dest, origin
|
||||||
|
|
||||||
|
while current.n >= final.n:
|
||||||
|
if current.n == final.n:
|
||||||
|
break
|
||||||
|
nodes.append(current)
|
||||||
|
current = current.parent
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
nodes.append(current)
|
||||||
|
|
||||||
|
return reversed(nodes) if rev else nodes
|
||||||
|
|
||||||
|
branch = _walk_branch(start, end)
|
||||||
|
|
||||||
|
if not branch:
|
||||||
|
vim.command('unsilent echo "No path to that node from here!"')
|
||||||
|
return
|
||||||
|
|
||||||
|
for node in branch:
|
||||||
|
_undo_to(node.n)
|
||||||
|
vim.command('GundoRenderGraph')
|
||||||
|
normal('zz')
|
||||||
|
_goto_window_for_buffer(back)
|
||||||
|
vim.command('redraw')
|
||||||
|
vim.command('sleep 60m')
|
||||||
|
|
||||||
|
def initPythonModule():
|
||||||
|
if sys.version_info[:2] < (2, 4):
|
||||||
|
vim.command('let s:has_supported_python = 0')
|
@ -10,946 +10,13 @@
|
|||||||
|
|
||||||
|
|
||||||
"{{{ Init
|
"{{{ Init
|
||||||
|
|
||||||
if !exists('g:gundo_debug') && (exists('g:gundo_disable') || exists('loaded_gundo') || &cp)"{{{
|
if !exists('g:gundo_debug') && (exists('g:gundo_disable') || exists('loaded_gundo') || &cp)"{{{
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let loaded_gundo = 1"}}}
|
let loaded_gundo = 1"}}}
|
||||||
|
|
||||||
if v:version < '703'"{{{
|
|
||||||
function! s:GundoDidNotLoad()
|
|
||||||
echohl WarningMsg|echomsg "Gundo unavailable: requires Vim 7.3+"|echohl None
|
|
||||||
endfunction
|
|
||||||
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
|
|
||||||
finish
|
|
||||||
endif"}}}
|
|
||||||
|
|
||||||
if has('python')"{{{
|
|
||||||
let s:has_supported_python = 1
|
|
||||||
|
|
||||||
python << ENDPYTHON
|
|
||||||
import sys
|
|
||||||
import vim
|
|
||||||
if sys.version_info[:2] < (2, 4):
|
|
||||||
vim.command('let s:has_supported_python = 0')
|
|
||||||
ENDPYTHON
|
|
||||||
else
|
|
||||||
let s:has_supported_python = 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
if !s:has_supported_python
|
|
||||||
function! s:GundoDidNotLoad()
|
|
||||||
echohl WarningMsg|echomsg "Gundo requires Vim to be compiled with Python 2.4+"|echohl None
|
|
||||||
endfunction
|
|
||||||
command! -nargs=0 GundoToggle call s:GundoDidNotLoad()
|
|
||||||
finish
|
|
||||||
endif"}}}
|
|
||||||
|
|
||||||
if !exists('g:gundo_width')"{{{
|
|
||||||
let g:gundo_width = 45
|
|
||||||
endif"}}}
|
|
||||||
if !exists('g:gundo_preview_height')"{{{
|
|
||||||
let g:gundo_preview_height = 15
|
|
||||||
endif"}}}
|
|
||||||
if !exists('g:gundo_preview_bottom')"{{{
|
|
||||||
let g:gundo_preview_bottom = 0
|
|
||||||
endif"}}}
|
|
||||||
if !exists('g:gundo_right')"{{{
|
|
||||||
let g:gundo_right = 0
|
|
||||||
endif"}}}
|
|
||||||
if !exists('g:gundo_help')"{{{
|
|
||||||
let g:gundo_help = 1
|
|
||||||
endif"}}}
|
|
||||||
if !exists("g:gundo_map_move_older")"{{{
|
|
||||||
let g:gundo_map_move_older = 'j'
|
|
||||||
endif"}}}
|
|
||||||
if !exists("g:gundo_map_move_newer")"{{{
|
|
||||||
let g:gundo_map_move_newer = 'k'
|
|
||||||
endif"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Mercurial's graphlog code
|
|
||||||
python << ENDPYTHON
|
|
||||||
def asciiedges(seen, rev, parents):
|
|
||||||
"""adds edge info to changelog DAG walk suitable for ascii()"""
|
|
||||||
if rev not in seen:
|
|
||||||
seen.append(rev)
|
|
||||||
nodeidx = seen.index(rev)
|
|
||||||
|
|
||||||
knownparents = []
|
|
||||||
newparents = []
|
|
||||||
for parent in parents:
|
|
||||||
if parent in seen:
|
|
||||||
knownparents.append(parent)
|
|
||||||
else:
|
|
||||||
newparents.append(parent)
|
|
||||||
|
|
||||||
ncols = len(seen)
|
|
||||||
seen[nodeidx:nodeidx + 1] = newparents
|
|
||||||
edges = [(nodeidx, seen.index(p)) for p in knownparents]
|
|
||||||
|
|
||||||
if len(newparents) > 0:
|
|
||||||
edges.append((nodeidx, nodeidx))
|
|
||||||
if len(newparents) > 1:
|
|
||||||
edges.append((nodeidx, nodeidx + 1))
|
|
||||||
|
|
||||||
nmorecols = len(seen) - ncols
|
|
||||||
return nodeidx, edges, ncols, nmorecols
|
|
||||||
|
|
||||||
def get_nodeline_edges_tail(
|
|
||||||
node_index, p_node_index, n_columns, n_columns_diff, p_diff, fix_tail):
|
|
||||||
if fix_tail and n_columns_diff == p_diff and n_columns_diff != 0:
|
|
||||||
# Still going in the same non-vertical direction.
|
|
||||||
if n_columns_diff == -1:
|
|
||||||
start = max(node_index + 1, p_node_index)
|
|
||||||
tail = ["|", " "] * (start - node_index - 1)
|
|
||||||
tail.extend(["/", " "] * (n_columns - start))
|
|
||||||
return tail
|
|
||||||
else:
|
|
||||||
return ["\\", " "] * (n_columns - node_index - 1)
|
|
||||||
else:
|
|
||||||
return ["|", " "] * (n_columns - node_index - 1)
|
|
||||||
|
|
||||||
def draw_edges(edges, nodeline, interline):
|
|
||||||
for (start, end) in edges:
|
|
||||||
if start == end + 1:
|
|
||||||
interline[2 * end + 1] = "/"
|
|
||||||
elif start == end - 1:
|
|
||||||
interline[2 * start + 1] = "\\"
|
|
||||||
elif start == end:
|
|
||||||
interline[2 * start] = "|"
|
|
||||||
else:
|
|
||||||
nodeline[2 * end] = "+"
|
|
||||||
if start > end:
|
|
||||||
(start, end) = (end, start)
|
|
||||||
for i in range(2 * start + 1, 2 * end):
|
|
||||||
if nodeline[i] != "+":
|
|
||||||
nodeline[i] = "-"
|
|
||||||
|
|
||||||
def fix_long_right_edges(edges):
|
|
||||||
for (i, (start, end)) in enumerate(edges):
|
|
||||||
if end > start:
|
|
||||||
edges[i] = (start, end + 1)
|
|
||||||
|
|
||||||
def ascii(buf, state, type, char, text, coldata):
|
|
||||||
"""prints an ASCII graph of the DAG
|
|
||||||
|
|
||||||
takes the following arguments (one call per node in the graph):
|
|
||||||
|
|
||||||
- Somewhere to keep the needed state in (init to asciistate())
|
|
||||||
- Column of the current node in the set of ongoing edges.
|
|
||||||
- Type indicator of node data == ASCIIDATA.
|
|
||||||
- Payload: (char, lines):
|
|
||||||
- Character to use as node's symbol.
|
|
||||||
- List of lines to display as the node's text.
|
|
||||||
- Edges; a list of (col, next_col) indicating the edges between
|
|
||||||
the current node and its parents.
|
|
||||||
- Number of columns (ongoing edges) in the current revision.
|
|
||||||
- The difference between the number of columns (ongoing edges)
|
|
||||||
in the next revision and the number of columns (ongoing edges)
|
|
||||||
in the current revision. That is: -1 means one column removed;
|
|
||||||
0 means no columns added or removed; 1 means one column added.
|
|
||||||
"""
|
|
||||||
|
|
||||||
idx, edges, ncols, coldiff = coldata
|
|
||||||
assert -2 < coldiff < 2
|
|
||||||
if coldiff == -1:
|
|
||||||
# Transform
|
|
||||||
#
|
|
||||||
# | | | | | |
|
|
||||||
# o | | into o---+
|
|
||||||
# |X / |/ /
|
|
||||||
# | | | |
|
|
||||||
fix_long_right_edges(edges)
|
|
||||||
|
|
||||||
# add_padding_line says whether to rewrite
|
|
||||||
#
|
|
||||||
# | | | | | | | |
|
|
||||||
# | o---+ into | o---+
|
|
||||||
# | / / | | | # <--- padding line
|
|
||||||
# o | | | / /
|
|
||||||
# o | |
|
|
||||||
add_padding_line = (len(text) > 2 and coldiff == -1 and
|
|
||||||
[x for (x, y) in edges if x + 1 < y])
|
|
||||||
|
|
||||||
# fix_nodeline_tail says whether to rewrite
|
|
||||||
#
|
|
||||||
# | | o | | | | o | |
|
|
||||||
# | | |/ / | | |/ /
|
|
||||||
# | o | | into | o / / # <--- fixed nodeline tail
|
|
||||||
# | |/ / | |/ /
|
|
||||||
# o | | o | |
|
|
||||||
fix_nodeline_tail = len(text) <= 2 and not add_padding_line
|
|
||||||
|
|
||||||
# nodeline is the line containing the node character (typically o)
|
|
||||||
nodeline = ["|", " "] * idx
|
|
||||||
nodeline.extend([char, " "])
|
|
||||||
|
|
||||||
nodeline.extend(
|
|
||||||
get_nodeline_edges_tail(idx, state[1], ncols, coldiff,
|
|
||||||
state[0], fix_nodeline_tail))
|
|
||||||
|
|
||||||
# shift_interline is the line containing the non-vertical
|
|
||||||
# edges between this entry and the next
|
|
||||||
shift_interline = ["|", " "] * idx
|
|
||||||
if coldiff == -1:
|
|
||||||
n_spaces = 1
|
|
||||||
edge_ch = "/"
|
|
||||||
elif coldiff == 0:
|
|
||||||
n_spaces = 2
|
|
||||||
edge_ch = "|"
|
|
||||||
else:
|
|
||||||
n_spaces = 3
|
|
||||||
edge_ch = "\\"
|
|
||||||
shift_interline.extend(n_spaces * [" "])
|
|
||||||
shift_interline.extend([edge_ch, " "] * (ncols - idx - 1))
|
|
||||||
|
|
||||||
# draw edges from the current node to its parents
|
|
||||||
draw_edges(edges, nodeline, shift_interline)
|
|
||||||
|
|
||||||
# lines is the list of all graph lines to print
|
|
||||||
lines = [nodeline]
|
|
||||||
if add_padding_line:
|
|
||||||
lines.append(get_padding_line(idx, ncols, edges))
|
|
||||||
lines.append(shift_interline)
|
|
||||||
|
|
||||||
# make sure that there are as many graph lines as there are
|
|
||||||
# log strings
|
|
||||||
while len(text) < len(lines):
|
|
||||||
text.append("")
|
|
||||||
if len(lines) < len(text):
|
|
||||||
extra_interline = ["|", " "] * (ncols + coldiff)
|
|
||||||
while len(lines) < len(text):
|
|
||||||
lines.append(extra_interline)
|
|
||||||
|
|
||||||
# print lines
|
|
||||||
indentation_level = max(ncols, ncols + coldiff)
|
|
||||||
for (line, logstr) in zip(lines, text):
|
|
||||||
ln = "%-*s %s" % (2 * indentation_level, "".join(line), logstr)
|
|
||||||
buf.write(ln.rstrip() + '\n')
|
|
||||||
|
|
||||||
# ... and start over
|
|
||||||
state[0] = coldiff
|
|
||||||
state[1] = idx
|
|
||||||
|
|
||||||
def generate(dag, edgefn, current):
|
|
||||||
seen, state = [], [0, 0]
|
|
||||||
buf = Buffer()
|
|
||||||
for node, parents in list(dag):
|
|
||||||
if node.time:
|
|
||||||
age_label = age(int(node.time))
|
|
||||||
else:
|
|
||||||
age_label = 'Original'
|
|
||||||
line = '[%s] %s' % (node.n, age_label)
|
|
||||||
if node.n == current:
|
|
||||||
char = '@'
|
|
||||||
else:
|
|
||||||
char = 'o'
|
|
||||||
ascii(buf, state, 'C', char, [line], edgefn(seen, node, parents))
|
|
||||||
return buf.b
|
|
||||||
ENDPYTHON
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Mercurial age function
|
|
||||||
python << ENDPYTHON
|
|
||||||
import time
|
|
||||||
|
|
||||||
agescales = [("year", 3600 * 24 * 365),
|
|
||||||
("month", 3600 * 24 * 30),
|
|
||||||
("week", 3600 * 24 * 7),
|
|
||||||
("day", 3600 * 24),
|
|
||||||
("hour", 3600),
|
|
||||||
("minute", 60),
|
|
||||||
("second", 1)]
|
|
||||||
|
|
||||||
def age(ts):
|
|
||||||
'''turn a timestamp into an age string.'''
|
|
||||||
|
|
||||||
def plural(t, c):
|
|
||||||
if c == 1:
|
|
||||||
return t
|
|
||||||
return t + "s"
|
|
||||||
def fmt(t, c):
|
|
||||||
return "%d %s" % (c, plural(t, c))
|
|
||||||
|
|
||||||
now = time.time()
|
|
||||||
then = ts
|
|
||||||
if then > now:
|
|
||||||
return 'in the future'
|
|
||||||
|
|
||||||
delta = max(1, int(now - then))
|
|
||||||
if delta > agescales[0][1] * 2:
|
|
||||||
return time.strftime('%Y-%m-%d', time.gmtime(float(ts)))
|
|
||||||
|
|
||||||
for t, s in agescales:
|
|
||||||
n = delta // s
|
|
||||||
if n >= 2 or s == 1:
|
|
||||||
return '%s ago' % fmt(t, n)
|
|
||||||
ENDPYTHON
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Python Vim utility functions
|
|
||||||
python << ENDPYTHON
|
|
||||||
import vim
|
|
||||||
|
|
||||||
normal = lambda s: vim.command('normal %s' % s)
|
|
||||||
|
|
||||||
MISSING_BUFFER = "Cannot find Gundo's target buffer (%s)"
|
|
||||||
MISSING_WINDOW = "Cannot find window (%s) for Gundo's target buffer (%s)"
|
|
||||||
|
|
||||||
def _check_sanity():
|
|
||||||
'''Check to make sure we're not crazy.
|
|
||||||
|
|
||||||
Does the following things:
|
|
||||||
|
|
||||||
* Make sure the target buffer still exists.
|
|
||||||
'''
|
|
||||||
b = int(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
if not vim.eval('bufloaded(%d)' % b):
|
|
||||||
vim.command('echo "%s"' % (MISSING_BUFFER % b))
|
|
||||||
return False
|
|
||||||
|
|
||||||
w = int(vim.eval('bufwinnr(%d)' % b))
|
|
||||||
if w == -1:
|
|
||||||
vim.command('echo "%s"' % (MISSING_WINDOW % (w, b)))
|
|
||||||
return False
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _goto_window_for_buffer(b):
|
|
||||||
w = int(vim.eval('bufwinnr(%d)' % int(b)))
|
|
||||||
vim.command('%dwincmd w' % w)
|
|
||||||
|
|
||||||
def _goto_window_for_buffer_name(bn):
|
|
||||||
b = vim.eval('bufnr("%s")' % bn)
|
|
||||||
return _goto_window_for_buffer(b)
|
|
||||||
|
|
||||||
def _undo_to(n):
|
|
||||||
n = int(n)
|
|
||||||
if n == 0:
|
|
||||||
vim.command('silent earlier %s' % (int(vim.eval('&undolevels')) + 1))
|
|
||||||
else:
|
|
||||||
vim.command('silent undo %d' % n)
|
|
||||||
|
|
||||||
|
|
||||||
INLINE_HELP = '''\
|
|
||||||
" Gundo for %s (%d)
|
|
||||||
" j/k - move between undo states
|
|
||||||
" p - preview diff of selected and current states
|
|
||||||
" <cr> - revert to selected state
|
|
||||||
|
|
||||||
'''
|
|
||||||
ENDPYTHON
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Python undo tree data structures and functions
|
|
||||||
python << ENDPYTHON
|
|
||||||
import itertools
|
|
||||||
|
|
||||||
class Buffer(object):
|
|
||||||
def __init__(self):
|
|
||||||
self.b = ''
|
|
||||||
|
|
||||||
def write(self, s):
|
|
||||||
self.b += s
|
|
||||||
|
|
||||||
class Node(object):
|
|
||||||
def __init__(self, n, parent, time, curhead):
|
|
||||||
self.n = int(n)
|
|
||||||
self.parent = parent
|
|
||||||
self.children = []
|
|
||||||
self.curhead = curhead
|
|
||||||
self.time = time
|
|
||||||
|
|
||||||
def _make_nodes(alts, nodes, parent=None):
|
|
||||||
p = parent
|
|
||||||
|
|
||||||
for alt in alts:
|
|
||||||
curhead = 'curhead' in alt
|
|
||||||
node = Node(n=alt['seq'], parent=p, time=alt['time'], curhead=curhead)
|
|
||||||
nodes.append(node)
|
|
||||||
if alt.get('alt'):
|
|
||||||
_make_nodes(alt['alt'], nodes, p)
|
|
||||||
p = node
|
|
||||||
|
|
||||||
def make_nodes():
|
|
||||||
ut = vim.eval('undotree()')
|
|
||||||
entries = ut['entries']
|
|
||||||
|
|
||||||
root = Node(0, None, False, 0)
|
|
||||||
nodes = []
|
|
||||||
_make_nodes(entries, nodes, root)
|
|
||||||
nodes.append(root)
|
|
||||||
nmap = dict((node.n, node) for node in nodes)
|
|
||||||
return nodes, nmap
|
|
||||||
|
|
||||||
def changenr(nodes):
|
|
||||||
_curhead_l = list(itertools.dropwhile(lambda n: not n.curhead, nodes))
|
|
||||||
if _curhead_l:
|
|
||||||
current = _curhead_l[0].parent.n
|
|
||||||
else:
|
|
||||||
current = int(vim.eval('changenr()'))
|
|
||||||
return current
|
|
||||||
ENDPYTHON
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo utility functions
|
|
||||||
|
|
||||||
function! s:GundoGetTargetState()"{{{
|
|
||||||
let target_line = matchstr(getline("."), '\v\[[0-9]+\]')
|
|
||||||
return matchstr(target_line, '\v[0-9]+')
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoGoToWindowForBufferName(name)"{{{
|
|
||||||
if bufwinnr(bufnr(a:name)) != -1
|
|
||||||
exe bufwinnr(bufnr(a:name)) . "wincmd w"
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoIsVisible()"{{{
|
|
||||||
if bufwinnr(bufnr("__Gundo__")) != -1 || bufwinnr(bufnr("__Gundo_Preview__")) != -1
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoInlineHelpLength()"{{{
|
|
||||||
if g:gundo_help
|
|
||||||
return 6
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo buffer settings
|
|
||||||
|
|
||||||
function! s:GundoMapGraph()"{{{
|
|
||||||
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_older . " :call <sid>GundoMove(1)<CR>"
|
|
||||||
exec 'nnoremap <script> <silent> <buffer> ' . g:gundo_map_move_newer . " :call <sid>GundoMove(-1)<CR>"
|
|
||||||
nnoremap <script> <silent> <buffer> <CR> :call <sid>GundoRevert()<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> o :call <sid>GundoRevert()<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> <down> :call <sid>GundoMove(1)<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> <up> :call <sid>GundoMove(-1)<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> gg gg:call <sid>GundoMove(1)<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> P :call <sid>GundoPlayTo()<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> p :call <sid>GundoRenderChangePreview()<CR>
|
|
||||||
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
|
|
||||||
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
|
|
||||||
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
|
|
||||||
nnoremap <script> <silent> <buffer> <2-LeftMouse> :call <sid>GundoMouseDoubleClick()<CR>
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoMapPreview()"{{{
|
|
||||||
nnoremap <script> <silent> <buffer> q :call <sid>GundoClose()<CR>
|
|
||||||
cabbrev <script> <silent> <buffer> q call <sid>GundoClose()
|
|
||||||
cabbrev <script> <silent> <buffer> quit call <sid>GundoClose()
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoSettingsGraph()"{{{
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal bufhidden=hide
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal nomodifiable
|
|
||||||
setlocal filetype=gundo
|
|
||||||
setlocal nolist
|
|
||||||
setlocal nonumber
|
|
||||||
setlocal norelativenumber
|
|
||||||
setlocal nowrap
|
|
||||||
call s:GundoSyntaxGraph()
|
|
||||||
call s:GundoMapGraph()
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoSettingsPreview()"{{{
|
|
||||||
setlocal buftype=nofile
|
|
||||||
setlocal bufhidden=hide
|
|
||||||
setlocal noswapfile
|
|
||||||
setlocal nobuflisted
|
|
||||||
setlocal nomodifiable
|
|
||||||
setlocal filetype=diff
|
|
||||||
setlocal nonumber
|
|
||||||
setlocal norelativenumber
|
|
||||||
setlocal nowrap
|
|
||||||
setlocal foldlevel=20
|
|
||||||
setlocal foldmethod=diff
|
|
||||||
call s:GundoMapPreview()
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoSyntaxGraph()"{{{
|
|
||||||
let b:current_syntax = 'gundo'
|
|
||||||
|
|
||||||
syn match GundoCurrentLocation '@'
|
|
||||||
syn match GundoHelp '\v^".*$'
|
|
||||||
syn match GundoNumberField '\v\[[0-9]+\]'
|
|
||||||
syn match GundoNumber '\v[0-9]+' contained containedin=GundoNumberField
|
|
||||||
|
|
||||||
hi def link GundoCurrentLocation Keyword
|
|
||||||
hi def link GundoHelp Comment
|
|
||||||
hi def link GundoNumberField Comment
|
|
||||||
hi def link GundoNumber Identifier
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo buffer/window management
|
|
||||||
|
|
||||||
function! s:GundoResizeBuffers(backto)"{{{
|
|
||||||
call s:GundoGoToWindowForBufferName('__Gundo__')
|
|
||||||
exe "vertical resize " . g:gundo_width
|
|
||||||
|
|
||||||
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
|
||||||
exe "resize " . g:gundo_preview_height
|
|
||||||
|
|
||||||
exe a:backto . "wincmd w"
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoOpenGraph()"{{{
|
|
||||||
let existing_gundo_buffer = bufnr("__Gundo__")
|
|
||||||
|
|
||||||
if existing_gundo_buffer == -1
|
|
||||||
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
|
||||||
exe "new __Gundo__"
|
|
||||||
if g:gundo_preview_bottom
|
|
||||||
if g:gundo_right
|
|
||||||
wincmd L
|
|
||||||
else
|
|
||||||
wincmd H
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
call s:GundoResizeBuffers(winnr())
|
|
||||||
else
|
|
||||||
let existing_gundo_window = bufwinnr(existing_gundo_buffer)
|
|
||||||
|
|
||||||
if existing_gundo_window != -1
|
|
||||||
if winnr() != existing_gundo_window
|
|
||||||
exe existing_gundo_window . "wincmd w"
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
call s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
|
||||||
if g:gundo_preview_bottom
|
|
||||||
if g:gundo_right
|
|
||||||
exe "botright vsplit +buffer" . existing_gundo_buffer
|
|
||||||
else
|
|
||||||
exe "topleft vsplit +buffer" . existing_gundo_buffer
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
exe "split +buffer" . existing_gundo_buffer
|
|
||||||
endif
|
|
||||||
call s:GundoResizeBuffers(winnr())
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoOpenPreview()"{{{
|
|
||||||
let existing_preview_buffer = bufnr("__Gundo_Preview__")
|
|
||||||
|
|
||||||
if existing_preview_buffer == -1
|
|
||||||
if g:gundo_preview_bottom
|
|
||||||
exe "botright new __Gundo_Preview__"
|
|
||||||
else
|
|
||||||
if g:gundo_right
|
|
||||||
exe "botright vnew __Gundo_Preview__"
|
|
||||||
else
|
|
||||||
exe "topleft vnew __Gundo_Preview__"
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
let existing_preview_window = bufwinnr(existing_preview_buffer)
|
|
||||||
|
|
||||||
if existing_preview_window != -1
|
|
||||||
if winnr() != existing_preview_window
|
|
||||||
exe existing_preview_window . "wincmd w"
|
|
||||||
endif
|
|
||||||
else
|
|
||||||
if g:gundo_preview_bottom
|
|
||||||
exe "botright split +buffer" . existing_preview_buffer
|
|
||||||
else
|
|
||||||
if g:gundo_right
|
|
||||||
exe "botright vsplit +buffer" . existing_preview_buffer
|
|
||||||
else
|
|
||||||
exe "topleft vsplit +buffer" . existing_preview_buffer
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoClose()"{{{
|
|
||||||
if s:GundoGoToWindowForBufferName('__Gundo__')
|
|
||||||
quit
|
|
||||||
endif
|
|
||||||
|
|
||||||
if s:GundoGoToWindowForBufferName('__Gundo_Preview__')
|
|
||||||
quit
|
|
||||||
endif
|
|
||||||
|
|
||||||
exe bufwinnr(g:gundo_target_n) . "wincmd w"
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoOpen()"{{{
|
|
||||||
call s:GundoOpenPreview()
|
|
||||||
exe bufwinnr(g:gundo_target_n) . "wincmd w"
|
|
||||||
|
|
||||||
call s:GundoRenderGraph()
|
|
||||||
call s:GundoRenderPreview()
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoToggle()"{{{
|
|
||||||
if s:GundoIsVisible()
|
|
||||||
call s:GundoClose()
|
|
||||||
else
|
|
||||||
let g:gundo_target_n = bufnr('')
|
|
||||||
let g:gundo_target_f = @%
|
|
||||||
call s:GundoOpen()
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo mouse handling
|
|
||||||
|
|
||||||
function! s:GundoMouseDoubleClick()"{{{
|
|
||||||
let start_line = getline('.')
|
|
||||||
|
|
||||||
if stridx(start_line, '[') == -1
|
|
||||||
return
|
|
||||||
else
|
|
||||||
call s:GundoRevert()
|
|
||||||
endif
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo movement
|
|
||||||
|
|
||||||
function! s:GundoMove(direction) range"{{{
|
|
||||||
let start_line = getline('.')
|
|
||||||
if v:count1 == 0
|
|
||||||
let move_count = 1
|
|
||||||
else
|
|
||||||
let move_count = v:count1
|
|
||||||
endif
|
|
||||||
let distance = 2 * move_count
|
|
||||||
|
|
||||||
" If we're in between two nodes we move by one less to get back on track.
|
|
||||||
if stridx(start_line, '[') == -1
|
|
||||||
let distance = distance - 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
let target_n = line('.') + (distance * a:direction)
|
|
||||||
|
|
||||||
" Bound the movement to the graph.
|
|
||||||
if target_n <= s:GundoInlineHelpLength() - 1
|
|
||||||
call cursor(s:GundoInlineHelpLength(), 0)
|
|
||||||
else
|
|
||||||
call cursor(target_n, 0)
|
|
||||||
endif
|
|
||||||
|
|
||||||
let line = getline('.')
|
|
||||||
|
|
||||||
" Move to the node, whether it's an @ or an o
|
|
||||||
let idx1 = stridx(line, '@')
|
|
||||||
let idx2 = stridx(line, 'o')
|
|
||||||
if idx1 != -1
|
|
||||||
call cursor(0, idx1 + 1)
|
|
||||||
else
|
|
||||||
call cursor(0, idx2 + 1)
|
|
||||||
endif
|
|
||||||
|
|
||||||
call s:GundoRenderPreview()
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo rendering
|
|
||||||
|
|
||||||
"{{{ Rendering utility functions
|
|
||||||
python << ENDPYTHON
|
|
||||||
import difflib
|
|
||||||
|
|
||||||
def _fmt_time(t):
|
|
||||||
return time.strftime('%Y-%m-%d %I:%M:%S %p', time.localtime(float(t)))
|
|
||||||
|
|
||||||
def _output_preview_text(lines):
|
|
||||||
_goto_window_for_buffer_name('__Gundo_Preview__')
|
|
||||||
vim.command('setlocal modifiable')
|
|
||||||
vim.current.buffer[:] = lines
|
|
||||||
vim.command('setlocal nomodifiable')
|
|
||||||
|
|
||||||
def _generate_preview_diff(current, node_before, node_after):
|
|
||||||
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
if not node_after.n: # we're at the original file
|
|
||||||
before_lines = []
|
|
||||||
|
|
||||||
_undo_to(0)
|
|
||||||
after_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
before_name = 'n/a'
|
|
||||||
before_time = ''
|
|
||||||
after_name = 'Original'
|
|
||||||
after_time = ''
|
|
||||||
elif not node_before.n: # we're at a pseudo-root state
|
|
||||||
_undo_to(0)
|
|
||||||
before_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
_undo_to(node_after.n)
|
|
||||||
after_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
before_name = 'Original'
|
|
||||||
before_time = ''
|
|
||||||
after_name = node_after.n
|
|
||||||
after_time = _fmt_time(node_after.time)
|
|
||||||
else:
|
|
||||||
_undo_to(node_before.n)
|
|
||||||
before_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
_undo_to(node_after.n)
|
|
||||||
after_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
before_name = node_before.n
|
|
||||||
before_time = _fmt_time(node_before.time)
|
|
||||||
after_name = node_after.n
|
|
||||||
after_time = _fmt_time(node_after.time)
|
|
||||||
|
|
||||||
_undo_to(current)
|
|
||||||
|
|
||||||
return list(difflib.unified_diff(before_lines, after_lines,
|
|
||||||
before_name, after_name,
|
|
||||||
before_time, after_time))
|
|
||||||
|
|
||||||
def _generate_change_preview_diff(current, node_before, node_after):
|
|
||||||
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
_undo_to(node_before.n)
|
|
||||||
before_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
_undo_to(node_after.n)
|
|
||||||
after_lines = vim.current.buffer[:]
|
|
||||||
|
|
||||||
before_name = node_before.n or 'Original'
|
|
||||||
before_time = node_before.time and _fmt_time(node_before.time) or ''
|
|
||||||
after_name = node_after.n or 'Original'
|
|
||||||
after_time = node_after.time and _fmt_time(node_after.time) or ''
|
|
||||||
|
|
||||||
_undo_to(current)
|
|
||||||
|
|
||||||
return list(difflib.unified_diff(before_lines, after_lines,
|
|
||||||
before_name, after_name,
|
|
||||||
before_time, after_time))
|
|
||||||
ENDPYTHON
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
function! s:GundoRenderGraph()"{{{
|
|
||||||
python << ENDPYTHON
|
|
||||||
def GundoRenderGraph():
|
|
||||||
if not _check_sanity():
|
|
||||||
return
|
|
||||||
|
|
||||||
nodes, nmap = make_nodes()
|
|
||||||
|
|
||||||
for node in nodes:
|
|
||||||
node.children = [n for n in nodes if n.parent == node]
|
|
||||||
|
|
||||||
def walk_nodes(nodes):
|
|
||||||
for node in nodes:
|
|
||||||
if node.parent:
|
|
||||||
yield (node, [node.parent])
|
|
||||||
else:
|
|
||||||
yield (node, [])
|
|
||||||
|
|
||||||
dag = sorted(nodes, key=lambda n: int(n.n), reverse=True)
|
|
||||||
current = changenr(nodes)
|
|
||||||
|
|
||||||
result = generate(walk_nodes(dag), asciiedges, current).rstrip().splitlines()
|
|
||||||
result = [' ' + l for l in result]
|
|
||||||
|
|
||||||
target = (vim.eval('g:gundo_target_f'), int(vim.eval('g:gundo_target_n')))
|
|
||||||
|
|
||||||
if int(vim.eval('g:gundo_help')):
|
|
||||||
header = (INLINE_HELP % target).splitlines()
|
|
||||||
else:
|
|
||||||
header = []
|
|
||||||
|
|
||||||
vim.command('call s:GundoOpenGraph()')
|
|
||||||
vim.command('setlocal modifiable')
|
|
||||||
vim.current.buffer[:] = (header + result)
|
|
||||||
vim.command('setlocal nomodifiable')
|
|
||||||
|
|
||||||
i = 1
|
|
||||||
for line in result:
|
|
||||||
try:
|
|
||||||
line.split('[')[0].index('@')
|
|
||||||
i += 1
|
|
||||||
break
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
i += 1
|
|
||||||
vim.command('%d' % (i+len(header)-1))
|
|
||||||
|
|
||||||
GundoRenderGraph()
|
|
||||||
ENDPYTHON
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoRenderPreview()"{{{
|
|
||||||
python << ENDPYTHON
|
|
||||||
def GundoRenderPreview():
|
|
||||||
if not _check_sanity():
|
|
||||||
return
|
|
||||||
|
|
||||||
target_state = vim.eval('s:GundoGetTargetState()')
|
|
||||||
|
|
||||||
# Check that there's an undo state. There may not be if we're talking about
|
|
||||||
# a buffer with no changes yet.
|
|
||||||
if target_state == None:
|
|
||||||
_goto_window_for_buffer_name('__Gundo__')
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
target_state = int(target_state)
|
|
||||||
|
|
||||||
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
nodes, nmap = make_nodes()
|
|
||||||
current = changenr(nodes)
|
|
||||||
|
|
||||||
node_after = nmap[target_state]
|
|
||||||
node_before = node_after.parent
|
|
||||||
|
|
||||||
vim.command('call s:GundoOpenPreview()')
|
|
||||||
_output_preview_text(_generate_preview_diff(current, node_before, node_after))
|
|
||||||
|
|
||||||
_goto_window_for_buffer_name('__Gundo__')
|
|
||||||
|
|
||||||
GundoRenderPreview()
|
|
||||||
ENDPYTHON
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoRenderChangePreview()"{{{
|
|
||||||
python << ENDPYTHON
|
|
||||||
def GundoRenderChangePreview():
|
|
||||||
if not _check_sanity():
|
|
||||||
return
|
|
||||||
|
|
||||||
target_state = vim.eval('s:GundoGetTargetState()')
|
|
||||||
|
|
||||||
# Check that there's an undo state. There may not be if we're talking about
|
|
||||||
# a buffer with no changes yet.
|
|
||||||
if target_state == None:
|
|
||||||
_goto_window_for_buffer_name('__Gundo__')
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
target_state = int(target_state)
|
|
||||||
|
|
||||||
_goto_window_for_buffer(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
nodes, nmap = make_nodes()
|
|
||||||
current = changenr(nodes)
|
|
||||||
|
|
||||||
node_after = nmap[target_state]
|
|
||||||
node_before = nmap[current]
|
|
||||||
|
|
||||||
vim.command('call s:GundoOpenPreview()')
|
|
||||||
_output_preview_text(_generate_change_preview_diff(current, node_before, node_after))
|
|
||||||
|
|
||||||
_goto_window_for_buffer_name('__Gundo__')
|
|
||||||
|
|
||||||
GundoRenderChangePreview()
|
|
||||||
ENDPYTHON
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
|
||||||
|
|
||||||
"{{{ Gundo undo/redo
|
|
||||||
|
|
||||||
function! s:GundoRevert()"{{{
|
|
||||||
python << ENDPYTHON
|
|
||||||
def GundoRevert():
|
|
||||||
if not _check_sanity():
|
|
||||||
return
|
|
||||||
|
|
||||||
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
|
||||||
back = vim.eval('g:gundo_target_n')
|
|
||||||
|
|
||||||
_goto_window_for_buffer(back)
|
|
||||||
_undo_to(target_n)
|
|
||||||
|
|
||||||
vim.command('GundoRenderGraph')
|
|
||||||
_goto_window_for_buffer(back)
|
|
||||||
|
|
||||||
GundoRevert()
|
|
||||||
ENDPYTHON
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
function! s:GundoPlayTo()"{{{
|
|
||||||
python << ENDPYTHON
|
|
||||||
def GundoPlayTo():
|
|
||||||
if not _check_sanity():
|
|
||||||
return
|
|
||||||
|
|
||||||
target_n = int(vim.eval('s:GundoGetTargetState()'))
|
|
||||||
back = int(vim.eval('g:gundo_target_n'))
|
|
||||||
|
|
||||||
vim.command('echo "%s"' % back)
|
|
||||||
|
|
||||||
_goto_window_for_buffer(back)
|
|
||||||
normal('zR')
|
|
||||||
|
|
||||||
nodes, nmap = make_nodes()
|
|
||||||
|
|
||||||
start = nmap[changenr(nodes)]
|
|
||||||
end = nmap[target_n]
|
|
||||||
|
|
||||||
def _walk_branch(origin, dest):
|
|
||||||
rev = origin.n < dest.n
|
|
||||||
|
|
||||||
nodes = []
|
|
||||||
if origin.n > dest.n:
|
|
||||||
current, final = origin, dest
|
|
||||||
else:
|
|
||||||
current, final = dest, origin
|
|
||||||
|
|
||||||
while current.n >= final.n:
|
|
||||||
if current.n == final.n:
|
|
||||||
break
|
|
||||||
nodes.append(current)
|
|
||||||
current = current.parent
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
nodes.append(current)
|
|
||||||
|
|
||||||
return reversed(nodes) if rev else nodes
|
|
||||||
|
|
||||||
branch = _walk_branch(start, end)
|
|
||||||
|
|
||||||
if not branch:
|
|
||||||
vim.command('unsilent echo "No path to that node from here!"')
|
|
||||||
return
|
|
||||||
|
|
||||||
for node in branch:
|
|
||||||
_undo_to(node.n)
|
|
||||||
vim.command('GundoRenderGraph')
|
|
||||||
normal('zz')
|
|
||||||
_goto_window_for_buffer(back)
|
|
||||||
vim.command('redraw')
|
|
||||||
vim.command('sleep 60m')
|
|
||||||
|
|
||||||
GundoPlayTo()
|
|
||||||
ENDPYTHON
|
|
||||||
endfunction"}}}
|
|
||||||
|
|
||||||
"}}}
|
"}}}
|
||||||
|
|
||||||
"{{{ Misc
|
"{{{ Misc
|
||||||
command! -nargs=0 GundoToggle call s:GundoToggle()
|
command! -nargs=0 GundoToggle call gundo#GundoToggle()
|
||||||
command! -nargs=0 GundoRenderGraph call s:GundoRenderGraph()
|
command! -nargs=0 GundoRenderGraph call gundo#GundoRenderGraph()
|
||||||
autocmd BufNewFile __Gundo__ call s:GundoSettingsGraph()
|
|
||||||
autocmd BufNewFile __Gundo_Preview__ call s:GundoSettingsPreview()
|
|
||||||
"}}}
|
"}}}
|
@ -20,7 +20,7 @@
|
|||||||
if &cp || exists("g:loaded_netrwPlugin")
|
if &cp || exists("g:loaded_netrwPlugin")
|
||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
let g:loaded_netrwPlugin = "v141"
|
let g:loaded_netrwPlugin = "v142"
|
||||||
if v:version < 702
|
if v:version < 702
|
||||||
echohl WarningMsg | echo "***netrw*** you need vim version 7.2 for this version of netrw" | echohl None
|
echohl WarningMsg | echo "***netrw*** you need vim version 7.2 for this version of netrw" | echohl None
|
||||||
finish
|
finish
|
||||||
|
@ -88,7 +88,7 @@ if !exists("did_drchip_netrwlist_syntax")
|
|||||||
hi default link netrwTimeSep netrwDateSep
|
hi default link netrwTimeSep netrwDateSep
|
||||||
hi default link netrwComma netrwComment
|
hi default link netrwComma netrwComment
|
||||||
hi default link netrwHide netrwComment
|
hi default link netrwHide netrwComment
|
||||||
hi default link netrwMarkFile DiffChange
|
hi default link netrwMarkFile TabLineSel
|
||||||
|
|
||||||
" special syntax highlighting (see :he g:netrw_special_syntax)
|
" special syntax highlighting (see :he g:netrw_special_syntax)
|
||||||
hi default link netrwBak NonText
|
hi default link netrwBak NonText
|
||||||
|
Loading…
x
Reference in New Issue
Block a user