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)
|
||||
862 2635 cscope_quickfix.vim
|
||||
51 171 cscope_macros.vim
|
||||
102 13435 DirDiff.vim
|
||||
102 16171 DirDiff.vim
|
||||
1189 8687 matrix.vim
|
||||
1173 15731 tcomment
|
||||
948 2878 Scons Compiler plugin
|
||||
1709 6421 Scons Syntax file
|
||||
1772 7248 DAMOS.zip DAMOS tools (von Stefan)
|
||||
987 14064 DoxygenToolkit.vim
|
||||
1397 14039 xml.vim
|
||||
1397 16076 xml.vim
|
||||
1290 5190 LogiPat.vim
|
||||
1462 5612 dtd2xml
|
||||
1046 4249 Lusty Explorer
|
||||
@ -30,7 +30,7 @@ ScriptID SourceID Filename
|
||||
1173 15731 tComment.vim
|
||||
2701 13194 editsrec
|
||||
3280 14334 Tabbi
|
||||
642 8136 :AutoInstall: getscript.vim
|
||||
1075 15352 :AutoInstall: netrw.vim
|
||||
642 15781 :AutoInstall: getscript.vim
|
||||
1075 15782 :AutoInstall: netrw.vim
|
||||
1502 15362 :AutoInstall: vimball.vim
|
||||
3304 15211 Gundo
|
||||
3304 16172 Gundo
|
||||
|
@ -1,8 +1,8 @@
|
||||
" ---------------------------------------------------------------------
|
||||
" getscript.vim
|
||||
" Author: Charles E. Campbell, Jr.
|
||||
" Date: Jan 08, 2008
|
||||
" Version: 29
|
||||
" Date: May 31, 2011
|
||||
" Version: 33
|
||||
" Installing: :help glvs-install
|
||||
" Usage: :help glvs
|
||||
"
|
||||
@ -12,19 +12,24 @@
|
||||
" Initialization: {{{1
|
||||
" if you're sourcing this file, surely you can't be
|
||||
" expecting vim to be in its vi-compatible mode!
|
||||
if exists("g:loaded_getscript")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_getscript= "v33"
|
||||
if &cp
|
||||
echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)"
|
||||
finish
|
||||
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
|
||||
set cpo&vim
|
||||
"DechoTabOn
|
||||
|
||||
if exists("g:loaded_getscript")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_getscript= "v29"
|
||||
|
||||
" ---------------------------
|
||||
" Global Variables: {{{1
|
||||
" ---------------------------
|
||||
@ -40,25 +45,6 @@ if !exists("g:getscript_cygwin")
|
||||
let g:getscript_cygwin= 0
|
||||
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
|
||||
if !exists("g:GetLatestVimScripts_wget")
|
||||
@ -112,7 +98,9 @@ if g:GetLatestVimScripts_allowautoinstall
|
||||
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
|
||||
endif
|
||||
" call Decho("s:autoinstall<".s:autoinstall.">")
|
||||
@ -126,11 +114,223 @@ com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts()
|
||||
com! -nargs=0 GetScript 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
|
||||
" on the current line, interpreting two numbers and text as
|
||||
" 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(...)
|
||||
" call Dfunc("GetOneScript()")
|
||||
|
||||
@ -188,6 +388,7 @@ fun! s:GetOneScript(...)
|
||||
" call Decho("fname <".fname.">")
|
||||
endif
|
||||
|
||||
" plugin author protection from downloading his/her own scripts atop their latest work
|
||||
if scriptid == 0 || srcid == 0
|
||||
" When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname
|
||||
let @a= rega
|
||||
@ -211,29 +412,30 @@ fun! s:GetOneScript(...)
|
||||
exe "norm z\<CR>"
|
||||
redraw!
|
||||
" 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
|
||||
let scriptaddr = 'http://vim.sf.net/script.php?script_id='.scriptid
|
||||
" grab a copy of the plugin's vim.sourceforge.net webpage
|
||||
let scriptaddr = 'http://vim.sourceforge.net/script.php?script_id='.scriptid
|
||||
let tmpfile = tempname()
|
||||
let v:errmsg = ""
|
||||
|
||||
" make up to three tries at downloading the description
|
||||
let itry= 1
|
||||
while itry <= 3
|
||||
" call Decho("try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr)
|
||||
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!")
|
||||
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!
|
||||
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)
|
||||
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".g:getscript_shq.tmpfile.g:getscript_shq." ".g:getscript_shq.scriptaddr.g:getscript_shq
|
||||
endif
|
||||
if itry == 1
|
||||
exe "silent vsplit ".tmpfile
|
||||
else
|
||||
silent! e %
|
||||
endif
|
||||
" call Decho(".try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr)
|
||||
if has("win32") || has("win16") || has("win95")
|
||||
" 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." ".shellescape(tmpfile).' '.shellescape(scriptaddr)|bw!
|
||||
else
|
||||
" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr))
|
||||
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr)
|
||||
endif
|
||||
if itry == 1
|
||||
exe "silent vsplit ".fnameescape(tmpfile)
|
||||
else
|
||||
silent! e %
|
||||
endif
|
||||
setlocal bh=wipe
|
||||
|
||||
" find the latest source-id in the plugin's webpage
|
||||
silent! 1
|
||||
@ -247,35 +449,35 @@ fun! s:GetOneScript(...)
|
||||
|
||||
" testing: did finding "Click on the package..." fail?
|
||||
if findpkg == 0 || itry >= 4
|
||||
silent q!
|
||||
call delete(tmpfile)
|
||||
" restore options
|
||||
let &t_ti = t_ti
|
||||
let &t_te = t_te
|
||||
let &rs = rs
|
||||
let s:downerrors = s:downerrors + 1
|
||||
" call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">")
|
||||
echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">"
|
||||
" call Dret("GetOneScript : srch for /Click on the package/ failed")
|
||||
let @a= rega
|
||||
return
|
||||
silent q!
|
||||
call delete(tmpfile)
|
||||
" restore options
|
||||
let &t_ti = t_ti
|
||||
let &t_te = t_te
|
||||
let &rs = rs
|
||||
let s:downerrors = s:downerrors + 1
|
||||
" call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">")
|
||||
echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">"
|
||||
" call Dret("GetOneScript : srch for /Click on the package/ failed")
|
||||
let @a= rega
|
||||
return
|
||||
endif
|
||||
" call Decho('found "Click on the package to download"')
|
||||
|
||||
let findsrcid= search('src_id=','W')
|
||||
if findsrcid == 0
|
||||
silent q!
|
||||
call delete(tmpfile)
|
||||
" restore options
|
||||
let &t_ti = t_ti
|
||||
let &t_te = t_te
|
||||
let &rs = rs
|
||||
let s:downerrors = s:downerrors + 1
|
||||
" call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">")
|
||||
echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">"
|
||||
let @a= rega
|
||||
" call Dret("GetOneScript : srch for /src_id/ failed")
|
||||
return
|
||||
silent q!
|
||||
call delete(tmpfile)
|
||||
" restore options
|
||||
let &t_ti = t_ti
|
||||
let &t_te = t_te
|
||||
let &rs = rs
|
||||
let s:downerrors = s:downerrors + 1
|
||||
" call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">")
|
||||
echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">"
|
||||
let @a= rega
|
||||
" call Dret("GetOneScript : srch for /src_id/ failed")
|
||||
return
|
||||
endif
|
||||
" call Decho('found "src_id=" in description page')
|
||||
|
||||
@ -291,8 +493,7 @@ fun! s:GetOneScript(...)
|
||||
let latestsrcid = latestsrcid + 0
|
||||
" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">")
|
||||
|
||||
" has the plugin's most-recent srcid increased, which indicates
|
||||
" that it has been updated
|
||||
" has the plugin's most-recent srcid increased, which indicates that it has been updated
|
||||
if latestsrcid > srcid
|
||||
" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">")
|
||||
|
||||
@ -302,80 +503,124 @@ fun! s:GetOneScript(...)
|
||||
let sname= "NEW_".sname
|
||||
endif
|
||||
|
||||
" -----------------------------------------------------------------------------
|
||||
" 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")
|
||||
" 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")
|
||||
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." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='.latestsrcid)|q
|
||||
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)
|
||||
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
|
||||
" 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." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id=').latestsrcid
|
||||
endif
|
||||
|
||||
" --------------------------------------------------------------------------
|
||||
" AutoInstall: only if doautoinstall has been requested by the plugin itself
|
||||
" --------------------------------------------------------------------------
|
||||
" call Decho("checking if plugin requested autoinstall: doautoinstall=".doautoinstall)
|
||||
if doautoinstall
|
||||
" call Decho("attempting to do autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".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)
|
||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".g:getscript_shq.s:autoinstall.g:getscript_shq
|
||||
let curdir = escape(substitute(getcwd(),'\','/','ge'),"|[]*'\" #")
|
||||
let installdir= curdir."/Installed"
|
||||
if !isdirectory(installdir)
|
||||
call mkdir(installdir)
|
||||
endif
|
||||
" call Decho("exe cd ".s:autoinstall)
|
||||
exe "cd ".escape(s:autoinstall,' ')
|
||||
|
||||
" decompress
|
||||
if sname =~ '\.bz2$'
|
||||
" call Decho("decompress: attempt to bunzip2 ".sname)
|
||||
exe "silent !bunzip2 ".g:getscript_shq.sname.g:getscript_shq
|
||||
let sname= substitute(sname,'\.bz2$','','')
|
||||
" call Decho("decompress: new sname<".sname."> after bunzip2")
|
||||
elseif sname =~ '\.gz$'
|
||||
" call Decho("decompress: attempt to gunzip ".sname)
|
||||
exe "silent !gunzip ".g:getscript_shq.sname.g:getscript_shq
|
||||
let sname= substitute(sname,'\.gz$','','')
|
||||
" call Decho("decompress: new sname<".sname."> after gunzip")
|
||||
endif
|
||||
|
||||
" distribute archive(.zip, .tar, .vba) contents
|
||||
if sname =~ '\.zip$'
|
||||
" call Decho("dearchive: attempt to unzip ".sname)
|
||||
exe "silent !unzip -o ".g:getscript_shq.sname.g:getscript_shq
|
||||
elseif sname =~ '\.tar$'
|
||||
" call Decho("dearchive: attempt to untar ".sname)
|
||||
exe "silent !tar -xvf ".g:getscript_shq.sname.g:getscript_shq
|
||||
elseif sname =~ '\.vba$'
|
||||
" call Decho("dearchive: attempt to handle a vimball: ".sname)
|
||||
silent 1split
|
||||
exe "silent e ".escape(sname,' ')
|
||||
silent so %
|
||||
silent q
|
||||
endif
|
||||
|
||||
if sname =~ '.vim$'
|
||||
" call Decho("dearchive: attempt to simply move ".sname." to plugin")
|
||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." plugin"
|
||||
else
|
||||
" call Decho("dearchive: move <".sname."> to installdir<".installdir.">")
|
||||
exe "silent !".g:GetLatestVimScripts_mv." ".g:getscript_shq.sname.g:getscript_shq." ".installdir
|
||||
endif
|
||||
|
||||
" helptags step
|
||||
let docdir= substitute(&rtp,',.*','','e')."/doc"
|
||||
" call Decho("helptags: docdir<".docdir.">")
|
||||
exe "helptags ".docdir
|
||||
exe "cd ".curdir
|
||||
" call Decho(" ")
|
||||
" call Decho("Autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname))
|
||||
if filereadable(sname)
|
||||
" call Decho("<".sname."> is readable")
|
||||
" call Decho("exe silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall))
|
||||
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall)
|
||||
let curdir = fnameescape(substitute(getcwd(),'\','/','ge'))
|
||||
let installdir= curdir."/Installed"
|
||||
if !isdirectory(installdir)
|
||||
call mkdir(installdir)
|
||||
endif
|
||||
if fname !~ ':AutoInstall:'
|
||||
let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
|
||||
" call Decho("curdir<".curdir."> installdir<".installdir.">")
|
||||
" 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 modline=scriptid." ".latestsrcid." ".fname.cmmnt
|
||||
let tgtdir= "plugin"
|
||||
endif
|
||||
else
|
||||
" call Decho("tgtdir<".tgtdir."> pname<".pname.">")
|
||||
|
||||
" decompress
|
||||
if sname =~ '\.bz2$'
|
||||
" call Decho("decompress: attempt to bunzip2 ".sname)
|
||||
exe "silent !bunzip2 ".shellescape(sname)
|
||||
let sname= substitute(sname,'\.bz2$','','')
|
||||
" call Decho("decompress: new sname<".sname."> after bunzip2")
|
||||
elseif sname =~ '\.gz$'
|
||||
" call Decho("decompress: attempt to gunzip ".sname)
|
||||
exe "silent !gunzip ".shellescape(sname)
|
||||
let sname= substitute(sname,'\.gz$','','')
|
||||
" 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
|
||||
|
||||
" distribute archive(.zip, .tar, .vba) contents
|
||||
if sname =~ '\.zip$'
|
||||
" call Decho("dearchive: attempt to unzip ".sname)
|
||||
exe "silent !unzip -o ".shellescape(sname)
|
||||
elseif sname =~ '\.tar$'
|
||||
" call Decho("dearchive: attempt to untar ".sname)
|
||||
exe "silent !tar -xvf ".shellescape(sname)
|
||||
elseif sname =~ '\.vba$'
|
||||
" call Decho("dearchive: attempt to handle a vimball: ".sname)
|
||||
silent 1split
|
||||
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 q
|
||||
if exists("oldvimballhome")
|
||||
let g:vimball_home= oldvimballhome
|
||||
else
|
||||
unlet g:vimball_home
|
||||
endif
|
||||
else
|
||||
" call Decho("no dearchiving needed")
|
||||
endif
|
||||
|
||||
" ---------------------------------------------
|
||||
" move plugin to plugin/ or AsNeeded/ directory
|
||||
" ---------------------------------------------
|
||||
if sname =~ '.vim$'
|
||||
" call Decho("dearchive: attempt to simply move ".sname." to ".tgtdir)
|
||||
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".tgtdir
|
||||
else
|
||||
" call Decho("dearchive: move <".sname."> to installdir<".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
|
||||
|
||||
" helptags step
|
||||
let docdir= substitute(&rtp,',.*','','e')."/doc"
|
||||
" call Decho("helptags: docdir<".docdir.">")
|
||||
exe "helptags ".fnameescape(docdir)
|
||||
exe "cd ".fnameescape(curdir)
|
||||
endif
|
||||
if fname !~ ':AutoInstall:'
|
||||
let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
|
||||
else
|
||||
let modline=scriptid." ".latestsrcid." ".fname.cmmnt
|
||||
endif
|
||||
else
|
||||
let modline=scriptid." ".latestsrcid." ".fname.cmmnt
|
||||
endif
|
||||
|
||||
" update the data in the <GetLatestVimScripts.dat> file
|
||||
@ -390,197 +635,11 @@ fun! s:GetOneScript(...)
|
||||
let &t_te = t_te
|
||||
let &rs = rs
|
||||
let @a = rega
|
||||
" call Dredir("BUFFER TEST (GetOneScript)","ls!")
|
||||
|
||||
" call Dret("GetOneScript")
|
||||
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
|
||||
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
|
||||
" AUTOLOAD SECTION
|
||||
" Date: Apr 01, 2011
|
||||
" Version: 141
|
||||
" Date: May 31, 2011
|
||||
" Version: 142
|
||||
" Maintainer: Charles E Campbell, Jr <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
|
||||
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
|
||||
" Copyright: Copyright (C) 1999-2010 Charles E. Campbell, Jr. {{{1
|
||||
@ -22,7 +22,7 @@
|
||||
if &cp || exists("g:loaded_netrw")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_netrw = "v141"
|
||||
let g:loaded_netrw = "v142"
|
||||
if v:version < 702
|
||||
echohl WarningMsg
|
||||
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:NetrwTopLvlMenu","Netrw.")
|
||||
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
|
||||
call s:NetrwInit("g:netrw_fname_escape",' ?&;%')
|
||||
@ -1518,6 +1518,14 @@ endfun
|
||||
fun! s:NetrwMethod(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
|
||||
" curmachine used if protocol == ftp and no .netrc
|
||||
if exists("g:netrw_machine")
|
||||
@ -1813,6 +1821,25 @@ endfun
|
||||
" s:NetrwMaps: {{{2
|
||||
fun! s:NetrwMaps(islocal)
|
||||
" 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
|
||||
" call Decho("make local maps")
|
||||
inoremap <buffer> <silent> a <c-o>:call <SID>NetrwHide(1)<cr>
|
||||
@ -1925,15 +1952,22 @@ fun! s:NetrwMaps(islocal)
|
||||
endif
|
||||
let mapsafecurdir = escape(b:netrw_curdir, s:netrw_map_escape)
|
||||
if g:netrw_mousemaps == 1
|
||||
nnoremap <buffer> <silent> <leftmouse> <leftmouse>:call <SID>NetrwLeftmouse(1)<cr>
|
||||
nnoremap <buffer> <silent> <middlemouse> <leftmouse>:call <SID>NetrwPrevWinOpen(1)<cr>
|
||||
nnoremap <buffer> <silent> <s-leftmouse> <leftmouse>:call <SID>NetrwMarkFile(1,<SID>NetrwGetWord())<cr>
|
||||
nmap <buffer> <silent> <2-leftmouse> -
|
||||
nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse
|
||||
nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(1)<cr>
|
||||
nmap <buffer> <middlemouse> <Plug>NetrwMiddlemouse
|
||||
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 '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>'
|
||||
endif
|
||||
exe 'nnoremap <buffer> <silent> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
|
||||
@ -2053,17 +2087,24 @@ fun! s:NetrwMaps(islocal)
|
||||
let mapsafepath = escape(s:path, s:netrw_map_escape)
|
||||
let mapsafeusermach = escape(s:user.s:machine, s:netrw_map_escape)
|
||||
|
||||
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
|
||||
nnoremap <buffer> <silent> <leftmouse> <leftmouse>:call <SID>NetrwLeftmouse(0)<cr>
|
||||
nnoremap <buffer> <silent> <middlemouse> <leftmouse>:call <SID>NetrwPrevWinOpen(0)<cr>
|
||||
nnoremap <buffer> <silent> <s-leftmouse> <leftmouse>:call <SID>NetrwMarkFile(0,<SID>NetrwGetWord())<cr>
|
||||
nmap <buffer> <silent> <2-leftmouse> -
|
||||
nmap <leftmouse> <Plug>NetrwLeftmouse
|
||||
nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(0)<cr>
|
||||
nmap <middlemouse> <Plug>NetrwMiddlemouse
|
||||
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 '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>'
|
||||
endif
|
||||
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>
|
||||
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)
|
||||
|
||||
" call Dret("s:NetrwMaps")
|
||||
endfun
|
||||
|
||||
@ -3647,34 +3673,40 @@ fun! netrw#Explore(indx,dosplit,style,...)
|
||||
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 s:SaveWinVars()
|
||||
let winsize= g:netrw_winsize
|
||||
let winsz= g:netrw_winsize
|
||||
if a:indx > 0
|
||||
let winsize= a:indx
|
||||
let winsz= a:indx
|
||||
endif
|
||||
|
||||
if a:style == 0 " Explore, 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!
|
||||
" 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
|
||||
" 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!
|
||||
" 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
|
||||
" 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!
|
||||
" 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
|
||||
call s:SaveBufVars()
|
||||
@ -4618,13 +4650,13 @@ fun! s:NetrwMarkFileCopy(islocal)
|
||||
|
||||
" sanity checks
|
||||
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")
|
||||
return 0
|
||||
endif
|
||||
" call Decho("sanity chk passed: s:netrwmarkfilelist_".bufnr('%')."<".string(s:netrwmarkfilelist_{bufnr('%')}))
|
||||
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")
|
||||
return 0
|
||||
endif
|
||||
@ -6143,7 +6175,8 @@ fun! s:NetrwSplit(mode)
|
||||
if a:mode == 0
|
||||
" remote and o
|
||||
" 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
|
||||
keepj call s:RestoreWinVars()
|
||||
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
||||
@ -6162,7 +6195,8 @@ fun! s:NetrwSplit(mode)
|
||||
elseif a:mode == 2
|
||||
" remote and 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
|
||||
keepj call s:RestoreWinVars()
|
||||
keepj call s:NetrwBrowse(0,s:NetrwBrowseChgDir(0,s:NetrwGetWord()))
|
||||
@ -6171,7 +6205,8 @@ fun! s:NetrwSplit(mode)
|
||||
elseif a:mode == 3
|
||||
" local and o
|
||||
" 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
|
||||
keepj call s:RestoreWinVars()
|
||||
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
||||
@ -6192,7 +6227,8 @@ fun! s:NetrwSplit(mode)
|
||||
elseif a:mode == 5
|
||||
" local and 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
|
||||
keepj call s:RestoreWinVars()
|
||||
keepj call netrw#LocalBrowseCheck(s:NetrwBrowseChgDir(1,s:NetrwGetWord()))
|
||||
@ -6826,8 +6862,8 @@ fun! s:NetrwRemoteListing()
|
||||
" call Decho("2: exe sil r! ".listcmd)
|
||||
exe "sil! keepalt r! ".listcmd
|
||||
else
|
||||
" call Decho("3: exe sil r! ".listcmd.' '.shellescape(s:path,1))
|
||||
exe "sil! keepalt r! ".listcmd.' '.shellescape(s:path,1)
|
||||
" call Decho("3: exe sil r! ".listcmd.' '.shellescape(fnameescape(s:path),1))
|
||||
exe "sil! keepalt r! ".listcmd.' '.shellescape(fnameescape(s:path),1)
|
||||
" call Decho("listcmd<".listcmd."> path<".s:path.">")
|
||||
endif
|
||||
endif
|
||||
@ -7278,12 +7314,12 @@ fun! s:LocalListing()
|
||||
" get the list of files contained in the current directory
|
||||
let dirname = 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)
|
||||
if filelist != ""
|
||||
let filelist= filelist."\n"
|
||||
endif
|
||||
let filelist= filelist.glob(s:ComposePath(dirname,".*"))
|
||||
let filelist= filelist.glob(s:ComposePath(fnameescape(dirname),".*"))
|
||||
" call Decho("glob(dirname<".dirname."/.*>)=".filelist)
|
||||
|
||||
" Coding choice: either elide ./ if present
|
||||
@ -7797,7 +7833,7 @@ endfun
|
||||
" 0=note = s:NOTE
|
||||
" 1=warning = s:WARNING
|
||||
" 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)
|
||||
" 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
|
||||
fun! s:RemotePathAnalysis(dirname)
|
||||
" call Dfunc("s:RemotePathAnalysis()")
|
||||
" call Dfunc("s:RemotePathAnalysis(a:dirname<".a:dirname.">)")
|
||||
|
||||
let dirpat = '^\(\w\{-}\)://\(\w\+@\)\=\([^/:#]\+\)\%([:#]\(\d\+\)\)\=/\(.*\)$'
|
||||
let s:method = substitute(a:dirname,dirpat,'\1','')
|
||||
|
@ -1,6 +1,6 @@
|
||||
*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*
|
||||
@ -16,6 +16,7 @@ CONTENTS *Gundo-contents*
|
||||
3.6 gundo_disable ............. |gundo_disable|
|
||||
3.7 gundo_map_move_older ...... |gundo_map_move_older|
|
||||
gundo_map_move_newer ...... |gundo_map_move_newer|
|
||||
3.8 gundo_close_on_revert ..... |gundo_close_on_revert|
|
||||
4. License ........................ |GundoLicense|
|
||||
5. Bugs ........................... |GundoBugs|
|
||||
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"
|
||||
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*
|
||||
|
||||
@ -211,6 +219,13 @@ GitHub: http://github.com/sjl/gundo.vim/
|
||||
==============================================================================
|
||||
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
|
||||
* Fix a bug with the movement key mappings.
|
||||
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.
|
||||
<
|
||||
Authors: Charles E. Campbell, Jr. <NdrOchip@ScampbellPfamilyA.Mbiz>
|
||||
(remove NOSPAM from the email address)
|
||||
*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
|
||||
pi_getscript.txt (see |copyright|) except use
|
||||
"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;
|
||||
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
|
||||
2. Unix:
|
||||
@ -76,8 +76,10 @@ Your computer needs to have wget for GetLatestVimScripts to do its work.
|
||||
==============================================================================
|
||||
3. GetLatestVimScripts Usage *glvs-usage* *:GLVS*
|
||||
|
||||
Unless its been defined elsewhere, >
|
||||
Unless it has been defined elsewhere, >
|
||||
|
||||
:GLVS
|
||||
|
||||
will invoke GetLatestVimScripts(). If some other plugin has defined that
|
||||
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
|
||||
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
(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
|
||||
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
|
||||
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*
|
||||
As an example of a <GetLatestVimScripts.dat> file:
|
||||
>
|
||||
ScriptID SourceID Filename
|
||||
--------------------------
|
||||
294 1 Align.vim
|
||||
120 2 decho.vim
|
||||
294 1 :AutoInstall: Align.vim
|
||||
120 2 Decho.vim
|
||||
40 3 DrawIt.tar.gz
|
||||
451 4 EasyAccents.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*
|
||||
|
||||
(this section is for plugin authors)~
|
||||
|
||||
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.dat files:
|
||||
@ -191,15 +216,24 @@ plus any additional lines describing any plugin dependencies it may have.
|
||||
Same format, of course!
|
||||
|
||||
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
|
||||
already present, to the user's GetLatest/GetLatestVimScripts.dat file. Its a
|
||||
relatively painless way to automate the acquisition of any scripts your
|
||||
already present, to the user's GetLatest/GetLatestVimScripts.dat file. It is
|
||||
a relatively painless way to automate the acquisition of any scripts your
|
||||
plugins depend upon.
|
||||
|
||||
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
|
||||
>
|
||||
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
|
||||
g:GetLatestVimScripts_wget command.
|
||||
>
|
||||
g:getLatestVimScripts_allowautoinstall
|
||||
g:GetLatestVimScripts_allowautoinstall
|
||||
< default= 1
|
||||
This variable indicates whether GetLatestVimScripts is allowed
|
||||
to attempt to automatically install scripts. Note that it
|
||||
doesn't understand vimballs (yet). Furthermore, the plugin
|
||||
author has to have explicitly indicated that his/her plugin
|
||||
is automatically installable.
|
||||
|
||||
to attempt to automatically install scripts. Furthermore, the
|
||||
plugin author has to have explicitly indicated that his/her
|
||||
plugin is automatically installable (via the :AutoInstall:
|
||||
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*
|
||||
@ -335,6 +374,14 @@ The AutoInstall process will:
|
||||
==============================================================================
|
||||
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
|
||||
getscriptPlugin.vim was setting it but not restoring it.
|
||||
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.
|
||||
@ -273,7 +273,7 @@ SOURCING *netrw-source* {{{2
|
||||
:Nsource "scp://[user@]machine[[:#]port]/path" uses scp
|
||||
: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
|
||||
edit the directory: >
|
||||
@ -281,14 +281,15 @@ DIRECTORY LISTING *netrw-dirlist* {{{2
|
||||
:e scp://[user]@hostname/path/
|
||||
:e ftp://[user]@hostname/path/
|
||||
<
|
||||
For remote directories (ie. those using scp or ftp), that trailing
|
||||
"/" is necessary (the slash tells netrw to treat the argument as a
|
||||
directory to browse instead of a file to download).
|
||||
For remote directory listings (ie. those using scp or ftp), that
|
||||
trailing "/" is necessary (the slash tells netrw to treat the argument
|
||||
as a directory to browse instead of as a file to download).
|
||||
|
||||
However, the Nread command can also be used to accomplish this:
|
||||
|
||||
:Nread [protocol]://[user]@hostname/path/
|
||||
The Nread command may also be used to accomplish this (again, that
|
||||
trailing slash is necessary): >
|
||||
|
||||
:Nread [protocol]://[user]@hostname/path/
|
||||
<
|
||||
*netrw-login* *netrw-password*
|
||||
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
|
||||
default: "ssh USEPORT HOSTNAME mkdir"
|
||||
|
||||
*g:netrw_mousemaps* =1 (default) enables the mouse buttons
|
||||
while browsing:
|
||||
*g:netrw_mousemaps* =1 (default) enables mouse buttons while
|
||||
browsing to:
|
||||
leftmouse : open file/directory
|
||||
shift-leftmouse : mark file
|
||||
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
|
||||
"o" (see |netrw-o|), "v" (see |netrw-v|),
|
||||
|:Hexplore| or |:Vexplore|.
|
||||
default: ""
|
||||
|:Hexplore| or |:Vexplore|. The g:netrw_winsize
|
||||
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,
|
||||
including multi-byte characters' string
|
||||
@ -2660,7 +2664,7 @@ Associated setting variables: |g:netrw_chgwin|
|
||||
|
||||
*netrw-p11*
|
||||
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>:
|
||||
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_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
|
||||
@ -2762,6 +2804,15 @@ which is loaded automatically at startup (assuming :set nocp).
|
||||
==============================================================================
|
||||
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
|
||||
* restored 2-leftmouse for :Rex-like return
|
||||
* added balloon help for banner
|
||||
|
@ -1574,6 +1574,7 @@ glvs-options pi_getscript.txt /*glvs-options*
|
||||
glvs-plugins pi_getscript.txt /*glvs-plugins*
|
||||
glvs-usage pi_getscript.txt /*glvs-usage*
|
||||
gundo.txt gundo.txt /*gundo.txt*
|
||||
gundo_close_on_revert gundo.txt /*gundo_close_on_revert*
|
||||
gundo_disable gundo.txt /*gundo_disable*
|
||||
gundo_help gundo.txt /*gundo_help*
|
||||
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-p12 pi_netrw.txt /*netrw-p12*
|
||||
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-p3 pi_netrw.txt /*netrw-p3*
|
||||
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-texplore pi_netrw.txt /*netrw-texplore*
|
||||
netrw-todo pi_netrw.txt /*netrw-todo*
|
||||
netrw-trailingslash pi_netrw.txt /*netrw-trailingslash*
|
||||
netrw-transparent pi_netrw.txt /*netrw-transparent*
|
||||
netrw-u pi_netrw.txt /*netrw-u*
|
||||
netrw-updir pi_netrw.txt /*netrw-updir*
|
||||
|
@ -78,6 +78,8 @@ elseif &filetype == 'xhtml'
|
||||
let b:xml_use_xhtml = 1
|
||||
en
|
||||
|
||||
let b:undo_ftplugin = "setlocal cms< isk<"
|
||||
\ . "| unlet b:match_ignorecase b:match_words"
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
" -*- 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
|
||||
" VERSION: 1.1.3
|
||||
" (C) 2001-2010 by William Lee, <wl1012@yahoo.com>
|
||||
" VERSION: 1.1.4
|
||||
" (C) 2001-2011 by William Lee, <wl1012@yahoo.com>
|
||||
" }}}
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@
|
||||
" William Lee <wl1012@yahoo.com>
|
||||
"
|
||||
" LICENSE:
|
||||
" Copyright (c) 2001-2006 William Lee
|
||||
" Copyright (c) 2001-2011 William Lee
|
||||
" All rights reserved.
|
||||
"
|
||||
" Redistribution and use in source and binary forms, with or without
|
||||
@ -151,6 +151,7 @@
|
||||
" Salman Halim, Yosuke Kimura, and others for their suggestions
|
||||
"
|
||||
" 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
|
||||
" 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
|
||||
@ -386,7 +387,7 @@ function! <SID>DirDiff(srcA, srcB)
|
||||
echo "Diffing directories, it may take a while..."
|
||||
let error = <SID>DirDiffExec(cmd, 0)
|
||||
if (error == 0)
|
||||
echo "There is no diff here."
|
||||
redraw | echom "diff found no differences - directories match."
|
||||
return
|
||||
endif
|
||||
silent exe "edit ".DiffBuffer
|
||||
@ -513,6 +514,17 @@ function! <SID>CloseDiffWindows()
|
||||
endif
|
||||
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()
|
||||
" First dehighlight the last marked
|
||||
@ -526,8 +538,15 @@ function! <SID>DirDiffOpen()
|
||||
let dirA = <SID>GetBaseDir("A")
|
||||
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()
|
||||
|
||||
" Ensure we're in the right window
|
||||
exec thisWindow.'wincmd w'
|
||||
|
||||
let line = getline(".")
|
||||
" Parse the line and see whether it's a "Only in" or "Files Differ"
|
||||
call <SID>HighlightLine()
|
||||
@ -543,7 +562,7 @@ function! <SID>DirDiffOpen()
|
||||
endif
|
||||
split
|
||||
wincmd k
|
||||
silent exec "edit ".fnameescape(fileToOpen)
|
||||
silent exec "edit ". <SID>EscapeFileName(fileToOpen)
|
||||
" Fool the window saying that this is diff
|
||||
diffthis
|
||||
wincmd j
|
||||
@ -554,8 +573,15 @@ function! <SID>DirDiffOpen()
|
||||
"Open the diff windows
|
||||
split
|
||||
wincmd k
|
||||
silent exec "edit ".fnameescape(fileB)
|
||||
silent exec "vert diffsplit ".fnameescape(fileA)
|
||||
silent exec "edit ".<SID>EscapeFileName(fileB)
|
||||
|
||||
" 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
|
||||
wincmd j
|
||||
" Resize the window
|
||||
|
@ -19,7 +19,7 @@ if &cp || exists("g:loaded_getscriptPlugin")
|
||||
endif
|
||||
finish
|
||||
endif
|
||||
let g:loaded_getscriptPlugin = "v29"
|
||||
let g:loaded_getscriptPlugin = "v33"
|
||||
let s:keepcpo = &cpo
|
||||
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
|
||||
|
||||
if !exists('g:gundo_debug') && (exists('g:gundo_disable') || exists('loaded_gundo') || &cp)"{{{
|
||||
finish
|
||||
endif
|
||||
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
|
||||
command! -nargs=0 GundoToggle call s:GundoToggle()
|
||||
command! -nargs=0 GundoRenderGraph call s:GundoRenderGraph()
|
||||
autocmd BufNewFile __Gundo__ call s:GundoSettingsGraph()
|
||||
autocmd BufNewFile __Gundo_Preview__ call s:GundoSettingsPreview()
|
||||
command! -nargs=0 GundoToggle call gundo#GundoToggle()
|
||||
command! -nargs=0 GundoRenderGraph call gundo#GundoRenderGraph()
|
||||
"}}}
|
@ -20,7 +20,7 @@
|
||||
if &cp || exists("g:loaded_netrwPlugin")
|
||||
finish
|
||||
endif
|
||||
let g:loaded_netrwPlugin = "v141"
|
||||
let g:loaded_netrwPlugin = "v142"
|
||||
if v:version < 702
|
||||
echohl WarningMsg | echo "***netrw*** you need vim version 7.2 for this version of netrw" | echohl None
|
||||
finish
|
||||
|
@ -88,7 +88,7 @@ if !exists("did_drchip_netrwlist_syntax")
|
||||
hi default link netrwTimeSep netrwDateSep
|
||||
hi default link netrwComma 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)
|
||||
hi default link netrwBak NonText
|
||||
|
Loading…
x
Reference in New Issue
Block a user