1" --------------------------------------------------------------------- 2" getscript.vim 3" Author: Charles E. Campbell, Jr. 4" Date: May 11, 2007 5" Version: 27 6" Installing: :help glvs-install 7" Usage: :help glvs 8" 9" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim 10"redraw!|call inputsave()|call input("Press <cr> to continue")|call inputrestore() 11" --------------------------------------------------------------------- 12" Initialization: {{{1 13" if you're sourcing this file, surely you can't be 14" expecting vim to be in its vi-compatible mode 15if &cp 16 echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)" 17 finish 18endif 19let s:keepcpo = &cpo 20set cpo&vim 21"DechoTabOn 22 23if exists("g:loaded_getscript") 24 finish 25endif 26let g:loaded_getscript= "v27" 27 28" --------------------------------------------------------------------- 29" Global Variables: {{{1 30" allow user to change the command for obtaining scripts (does fetch work?) 31if !exists("g:GetLatestVimScripts_wget") 32 if executable("wget") 33 let g:GetLatestVimScripts_wget= "wget" 34 elseif executable("curl") 35 let g:GetLatestVimScripts_wget= "curl" 36 else 37 let g:GetLatestVimScripts_wget = 'echo "GetLatestVimScripts needs wget or curl"' 38 let g:GetLatestVimScripts_options = "" 39 endif 40endif 41 42" options that wget and curl require: 43if !exists("g:GetLatestVimScripts_options") 44 if g:GetLatestVimScripts_wget == "wget" 45 let g:GetLatestVimScripts_options= "-q -O" 46 elseif g:GetLatestVimScripts_wget == "curl" 47 let g:GetLatestVimScripts_options= "-s -O" 48 else 49 let g:GetLatestVimScripts_options= "" 50 endif 51endif 52 53" by default, allow autoinstall lines to work 54if !exists("g:GetLatestVimScripts_allowautoinstall") 55 let g:GetLatestVimScripts_allowautoinstall= 1 56endif 57 58"" For debugging: 59"let g:GetLatestVimScripts_wget = "echo" 60"let g:GetLatestVimScripts_options = "options" 61 62" --------------------------------------------------------------------- 63" Check If AutoInstall Capable: {{{1 64let s:autoinstall= "" 65if g:GetLatestVimScripts_allowautoinstall 66 67 if (has("win32") || has("gui_win32") || has("gui_win32s") || has("win16") || has("win64") || has("win32unix") || has("win95")) && &shell != "bash" 68 " windows (but not cygwin/bash) 69 let s:dotvim= "vimfiles" 70 if !exists("g:GetLatestVimScripts_mv") 71 let g:GetLatestVimScripts_mv= "ren" 72 endif 73 74 else 75 " unix 76 let s:dotvim= ".vim" 77 if !exists("g:GetLatestVimScripts_mv") 78 let g:GetLatestVimScripts_mv= "mv" 79 endif 80 endif 81 82 if exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim) 83 let s:autoinstall= $HOME."/".s:dotvim 84 endif 85" call Decho("s:autoinstall<".s:autoinstall.">") 86"else "Decho 87" call Decho("g:GetLatestVimScripts_allowautoinstall=".g:GetLatestVimScripts_allowautoinstall.": :AutoInstall: disabled") 88endif 89 90" --------------------------------------------------------------------- 91" Public Interface: {{{1 92com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts() 93com! -nargs=0 GetScript call getscript#GetLatestVimScripts() 94silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts() 95 96" --------------------------------------------------------------------- 97" GetOneScript: (Get Latest Vim Script) this function operates {{{1 98" on the current line, interpreting two numbers and text as 99" ScriptID, SourceID, and Filename. 100" It downloads any scripts that have newer versions from vim.sf.net. 101fun! s:GetOneScript(...) 102" call Dfunc("GetOneScript()") 103 104 " set options to allow progress to be shown on screen 105 let t_ti= &t_ti 106 let t_te= &t_te 107 let rs = &rs 108 set t_ti= t_te= nors 109 110 " put current line on top-of-screen and interpret it into 111 " a script identifer : used to obtain webpage 112 " source identifier : used to identify current version 113 " and an associated comment: used to report on what's being considered 114 if a:0 >= 3 115 let scriptid = a:1 116 let srcid = a:2 117 let fname = a:3 118 let cmmnt = "" 119" call Decho("scriptid<".scriptid.">") 120" call Decho("srcid <".srcid.">") 121" call Decho("fname <".fname.">") 122 else 123 let curline = getline(".") 124 if curline =~ '^\s*#' 125" call Dret("GetOneScript : skipping a pure comment line") 126 return 127 endif 128 let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(.\{-}\)\(\s*#.*\)\=$' 129 try 130 let scriptid = substitute(curline,parsepat,'\1','e') 131 catch /^Vim\%((\a\+)\)\=:E486/ 132 let scriptid= 0 133 endtry 134 try 135 let srcid = substitute(curline,parsepat,'\2','e') 136 catch /^Vim\%((\a\+)\)\=:E486/ 137 let srcid= 0 138 endtry 139 try 140 let fname= substitute(curline,parsepat,'\3','e') 141 catch /^Vim\%((\a\+)\)\=:E486/ 142 let fname= "" 143 endtry 144 try 145 let cmmnt= substitute(curline,parsepat,'\4','e') 146 catch /^Vim\%((\a\+)\)\=:E486/ 147 let cmmnt= "" 148 endtry 149" call Decho("curline <".curline.">") 150" call Decho("parsepat<".parsepat.">") 151" call Decho("scriptid<".scriptid.">") 152" call Decho("srcid <".srcid.">") 153" call Decho("fname <".fname.">") 154 endif 155 156 if scriptid == 0 || srcid == 0 157 " When looking for :AutoInstall: lines, skip scripts that 158 " have 0 0 scriptname 159" call Dret("GetOneScript : skipping a scriptid==srcid==0 line") 160 return 161 endif 162 163 let doautoinstall= 0 164 if fname =~ ":AutoInstall:" 165" call Decho("fname<".fname."> has :AutoInstall:...") 166 let aicmmnt= substitute(fname,'\s\+:AutoInstall:\s\+',' ','') 167" call Decho("aicmmnt<".aicmmnt."> s:autoinstall=".s:autoinstall) 168 if s:autoinstall != "" 169 let doautoinstall = g:GetLatestVimScripts_allowautoinstall 170 endif 171 else 172 let aicmmnt= fname 173 endif 174" call Decho("aicmmnt<".aicmmnt.">: doautoinstall=".doautoinstall) 175 176 exe "norm z\<CR>" 177 redraw! 178" call Decho('considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid) 179 echomsg 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid 180 181 " grab a copy of the plugin's vim.sf.net webpage 182 let scriptaddr = 'http://vim.sf.net/script.php?script_id='.scriptid 183 let tmpfile = tempname() 184 let v:errmsg = "" 185 186 " make up to three tries at downloading the description 187 let itry= 1 188 while itry <= 3 189" call Decho("try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr) 190 if has("win32") || has("win16") || has("win95") 191" call Decho("silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".tmpfile.' "'.scriptaddr.'"') 192 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".tmpfile.' "'.scriptaddr.'"' 193 else 194" call Decho("silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".tmpfile." '".scriptaddr."'") 195 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".tmpfile." '".scriptaddr."'" 196 endif 197 if itry == 1 198 exe "silent vsplit ".tmpfile 199 else 200 silent! e % 201 endif 202 203 " find the latest source-id in the plugin's webpage 204 silent! 1 205 let findpkg= search('Click on the package to download','W') 206 if findpkg > 0 207 break 208 endif 209 let itry= itry + 1 210 endwhile 211" call Decho(" --- end downloading tries while loop --- itry=".itry) 212 213 " testing: did finding "Click on the package..." fail? 214 if findpkg == 0 || itry >= 4 215 silent q! 216 call delete(tmpfile) 217 " restore options 218 let &t_ti = t_ti 219 let &t_te = t_te 220 let &rs = rs 221 let s:downerrors = s:downerrors + 1 222" call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">") 223 echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">" 224" call Dret("GetOneScript : srch for /Click on the package/ failed") 225 return 226 endif 227" call Decho('found "Click on the package to download"') 228 229 let findsrcid= search('src_id=','W') 230 if findsrcid == 0 231 silent q! 232 call delete(tmpfile) 233 " restore options 234 let &t_ti = t_ti 235 let &t_te = t_te 236 let &rs = rs 237 let s:downerrors = s:downerrors + 1 238" call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">") 239 echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">" 240" call Dret("GetOneScript : srch for /src_id/ failed") 241 return 242 endif 243" call Decho('found "src_id=" in description page') 244 245 let srcidpat = '^\s*<td class.*src_id=\(\d\+\)">\([^<]\+\)<.*$' 246 let latestsrcid= substitute(getline("."),srcidpat,'\1','') 247 let sname = substitute(getline("."),srcidpat,'\2','') " script name actually downloaded 248" call Decho("srcidpat<".srcidpat."> latestsrcid<".latestsrcid."> sname<".sname.">") 249 silent q! 250 call delete(tmpfile) 251 252 " convert the strings-of-numbers into numbers 253 let srcid = srcid + 0 254 let latestsrcid = latestsrcid + 0 255" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">") 256 257 " has the plugin's most-recent srcid increased, which indicates 258 " that it has been updated 259 if latestsrcid > srcid 260" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">") 261 262 let s:downloads= s:downloads + 1 263 if sname == bufname("%") 264 " GetLatestVimScript has to be careful about downloading itself 265 let sname= "NEW_".sname 266 endif 267 268 " the plugin has been updated since we last obtained it, so download a new copy 269" call Decho("...downloading new <".sname.">") 270 echomsg "...downloading new <".sname.">" 271 if has("win32") || has("gui_win32") || has("gui_win32s") || has("win16") || has("win64") || has("win32unix") || has("win95") 272" call Decho("windows: silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".sname.' "'.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.'"') 273 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".sname.' "'.'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid.'"' 274 else 275" call Decho("unix: silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".sname." '".'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid."'") 276 exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".sname." '".'http://vim.sf.net/scripts/download_script.php?src_id='.latestsrcid."'" 277 endif 278 279 " AutoInstall: only if doautoinstall is so indicating 280 if doautoinstall 281" call Decho("attempting to do autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname)) 282 if filereadable(sname) 283" call Decho("move <".sname."> to ".s:autoinstall) 284 exe "silent !".g:GetLatestVimScripts_mv." ".sname." ".s:autoinstall 285 let curdir= escape(substitute(getcwd(),'\','/','ge'),"|[]*'\" #") 286" call Decho("exe cd ".s:autoinstall) 287 exe "cd ".s:autoinstall 288 289 " decompress 290 if sname =~ '\.bz2$' 291" call Decho("decompress: attempt to bunzip2 ".sname) 292 exe "silent !bunzip2 ".sname 293 let sname= substitute(sname,'\.bz2$','','') 294" call Decho("decompress: new sname<".sname."> after bunzip2") 295 elseif sname =~ '\.gz$' 296" call Decho("decompress: attempt to gunzip ".sname) 297 exe "silent !gunzip ".sname 298 let sname= substitute(sname,'\.gz$','','') 299" call Decho("decompress: new sname<".sname."> after gunzip") 300 endif 301 302 " distribute archive(.zip, .tar, .vba) contents 303 if sname =~ '\.zip$' 304" call Decho("dearchive: attempt to unzip ".sname) 305 exe "silent !unzip -o ".sname 306 elseif sname =~ '\.tar$' 307" call Decho("dearchive: attempt to untar ".sname) 308 exe "silent !tar -xvf ".sname 309 elseif sname =~ '\.vba$' 310" call Decho("dearchive: attempt to handle a vimball: ".sname) 311 silent 1split 312 exe "silent e ".sname 313 silent so % 314 silent q 315 endif 316 317 if sname =~ '.vim$' 318" call Decho("dearchive: attempt to simply move ".sname." to plugin") 319 exe "silent !".g:GetLatestVimScripts_mv." ".sname." plugin" 320 endif 321 322 " helptags step 323 let docdir= substitute(&rtp,',.*','','e')."/doc" 324" call Decho("helptags: docdir<".docdir.">") 325 exe "helptags ".docdir 326 exe "cd ".curdir 327 endif 328 if fname !~ ':AutoInstall:' 329 let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt 330 else 331 let modline=scriptid." ".latestsrcid." ".fname.cmmnt 332 endif 333 else 334 let modline=scriptid." ".latestsrcid." ".fname.cmmnt 335 endif 336 337 " update the data in the <GetLatestVimScripts.dat> file 338 call setline(line("."),modline) 339" call Decho("update data in ".expand("%")."#".line(".").": modline<".modline.">") 340" else " Decho 341" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."], no need to update") 342 endif 343 344 " restore options 345 let &t_ti= t_ti 346 let &t_te= t_te 347 let &rs = rs 348 349" call Dret("GetOneScript") 350endfun 351 352" --------------------------------------------------------------------- 353" GetLatestVimScripts: this function gets the latest versions of {{{1 354" scripts based on the list in 355" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat 356fun! getscript#GetLatestVimScripts() 357" call Dfunc("GetLatestVimScripts() autoinstall<".s:autoinstall.">") 358 359" insure that wget is executable 360 if executable(g:GetLatestVimScripts_wget) != 1 361 echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system" 362" call Dret("GetLatestVimScripts : wget not executable/availble") 363 return 364 endif 365 366 " Find the .../GetLatest subdirectory under the runtimepath 367 for datadir in split(&rtp,',') + [''] 368 if isdirectory(datadir."/GetLatest") 369" call Decho("found directory<".datadir.">") 370 let datadir= datadir . "/GetLatest" 371 break 372 endif 373 if filereadable(datadir."GetLatestVimScripts.dat") 374" call Decho("found ".datadir."/GetLatestVimScripts.dat") 375 break 376 endif 377 endfor 378 379 " Sanity checks: readability and writability 380 if datadir == "" 381 echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install' 382" call Dret("GetLatestVimScripts : unable to find a GetLatest subdirectory") 383 return 384 endif 385 386 if filewritable(datadir) != 2 387 echoerr "(getLatestVimScripts) Your ".datadir." isn't writable" 388" call Dret("GetLatestVimScripts : non-writable directory<".datadir.">") 389 return 390 endif 391 let datafile= datadir."/GetLatestVimScripts.dat" 392 if !filereadable(datafile) 393 echoerr "Your data file<".datafile."> isn't readable" 394" call Dret("GetLatestVimScripts : non-readable datafile<".datafile.">") 395 return 396 endif 397 if !filewritable(datafile) 398 echoerr "Your data file<".datafile."> isn't writable" 399" call Dret("GetLatestVimScripts : non-writable datafile<".datafile.">") 400 return 401 endif 402" call Decho("datadir <".datadir.">") 403" call Decho("datafile <".datafile.">") 404 405 " don't let any events interfere (like winmanager's, taglist's, etc) 406 let eikeep= &ei 407 set ei=all 408 409 " record current directory, change to datadir, open split window with 410 " datafile 411 let origdir= getcwd() 412 exe "cd ".escape(substitute(datadir,'\','/','ge'),"|[]*'\" #") 413 split 414 exe "e ".escape(substitute(datafile,'\','/','ge'),"|[]*'\" #") 415 res 1000 416 let s:downloads = 0 417 let s:downerrors= 0 418 419 " Check on dependencies mentioned in plugins 420" call Decho(" ") 421" call Decho("searching plugins for GetLatestVimScripts dependencies") 422 let lastline = line("$") 423" call Decho("lastline#".lastline) 424 let plugins = split(globpath(&rtp,"plugin/*.vim")) 425 let foundscript = 0 426 let firstdir= "" 427 428 for plugin in plugins 429 430 " don't process plugins in system directories 431 if firstdir == "" 432 let firstdir= substitute(plugin,'[/\\][^/\\]\+$','','') 433" call Decho("firstdir<".firstdir.">") 434 else 435 let curdir= substitute(plugin,'[/\\][^/\\]\+$','','') 436" call Decho("curdir<".curdir.">") 437 if curdir != firstdir 438 break 439 endif 440 endif 441 442 " read plugin in 443 $ 444" call Decho(" ") 445" call Decho(".dependency checking<".plugin."> line$=".line("$")) 446 exe "silent r ".plugin 447 448 while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0 449 let newscript= substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e') 450 let llp1 = lastline+1 451" call Decho("..newscript<".newscript.">") 452 453 " don't process ""GetLatestVimScripts lines 454 if newscript !~ '^"' 455 " found a "GetLatestVimScripts: # #" line in the script; check if its already in the datafile 456 let curline = line(".") 457 let noai_script = substitute(newscript,'\s*:AutoInstall:\s*','','e') 458 exe llp1 459 let srchline = search('\<'.noai_script.'\>','bW') 460" call Decho("..noai_script<".noai_script."> srch=".srchline."curline#".line(".")." lastline#".lastline) 461 462 if srchline == 0 463 " found a new script to permanently include in the datafile 464 let keep_rega = @a 465 let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','') 466 exe lastline."put a" 467 echomsg "Appending <".@a."> to ".datafile." for ".newscript 468" call Decho("..APPEND (".noai_script.")<".@a."> to GetLatestVimScripts.dat") 469 let @a = keep_rega 470 let lastline = llp1 471 let curline = curline + 1 472 let foundscript = foundscript + 1 473" else " Decho 474" call Decho("..found <".noai_script."> (already in datafile at line#".srchline.")") 475 endif 476 477 let curline = curline + 1 478 exe curline 479 endif 480 endwhile 481 482 let llp1= lastline + 1 483" call Decho(".deleting lines: ".llp1.",$d") 484 exe "silent! ".llp1.",$d" 485 endfor 486" call Decho("--- end dependency checking loop --- foundscript=".foundscript) 487" call Decho(" ") 488 489 if foundscript == 0 490 set nomod 491 endif 492 493 " Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat 494" call Decho("begin: checking out-of-date scripts using datafile<".datafile.">") 495 set lz 496 1 497" /^-----/,$g/^\s*\d/call Decho(getline(".")) 498 1 499 /^-----/,$g/^\s*\d/call s:GetOneScript() 500" call Decho("--- end out-of-date checking --- ") 501 502 " Final report (an echomsg) 503 try 504 silent! ?^-------? 505 catch /^Vim\%((\a\+)\)\=:E114/ 506" call Dret("GetLatestVimScripts : nothing done!") 507 return 508 endtry 509 exe "norm! kz\<CR>" 510 redraw! 511 let s:msg = "" 512 if s:downloads == 1 513 let s:msg = "Downloaded one updated script to <".datadir.">" 514 elseif s:downloads == 2 515 let s:msg= "Downloaded two updated scripts to <".datadir.">" 516 elseif s:downloads > 1 517 let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">" 518 else 519 let s:msg= "Everything was already current" 520 endif 521 if s:downerrors > 0 522 let s:msg= s:msg." (".s:downerrors." downloading errors)" 523 endif 524 echomsg s:msg 525 " save the file 526 if &mod 527 silent! w! 528 endif 529 q 530 531 " restore events and current directory 532 exe "cd ".escape(substitute(origdir,'\','/','ge'),"|[]*'\" #") 533 let &ei= eikeep 534 set nolz 535" call Dret("GetLatestVimScripts : did ".s:downloads." downloads") 536endfun 537" --------------------------------------------------------------------- 538 539" Restore Options: {{{1 540let &cpo= s:keepcpo 541 542" vim: ts=8 sts=2 fdm=marker nowrap 543