1" zip.vim: Handles browsing zipfiles 2" AUTOLOAD PORTION 3" Date: Jul 02, 2013 4" Version: 27 5" Maintainer: Charles E Campbell <[email protected]> 6" License: Vim License (see vim's :help license) 7" Copyright: Copyright (C) 2005-2013 Charles E. Campbell {{{1 8" Permission is hereby granted to use and distribute this code, 9" with or without modifications, provided that this copyright 10" notice is copied with it. Like anything else that's free, 11" zip.vim and zipPlugin.vim are provided *as is* and comes with 12" no warranty of any kind, either expressed or implied. By using 13" this plugin, you agree that in no event will the copyright 14" holder be liable for any damages resulting from the use 15" of this software. 16"redraw!|call DechoSep()|call inputsave()|call input("Press <cr> to continue")|call inputrestore() 17 18" --------------------------------------------------------------------- 19" Load Once: {{{1 20if &cp || exists("g:loaded_zip") 21 finish 22endif 23let g:loaded_zip= "v27" 24if v:version < 702 25 echohl WarningMsg 26 echo "***warning*** this version of zip needs vim 7.2" 27 echohl Normal 28 finish 29endif 30let s:keepcpo= &cpo 31set cpo&vim 32"DechoTabOn 33 34let s:zipfile_escape = ' ?&;\' 35let s:ERROR = 2 36let s:WARNING = 1 37let s:NOTE = 0 38 39" --------------------------------------------------------------------- 40" Global Values: {{{1 41if !exists("g:zip_shq") 42 if &shq != "" 43 let g:zip_shq= &shq 44 elseif has("unix") 45 let g:zip_shq= "'" 46 else 47 let g:zip_shq= '"' 48 endif 49endif 50if !exists("g:zip_zipcmd") 51 let g:zip_zipcmd= "zip" 52endif 53if !exists("g:zip_unzipcmd") 54 let g:zip_unzipcmd= "unzip" 55endif 56 57" ---------------- 58" Functions: {{{1 59" ---------------- 60 61" --------------------------------------------------------------------- 62" zip#Browse: {{{2 63fun! zip#Browse(zipfile) 64" call Dfunc("zip#Browse(zipfile<".a:zipfile.">)") 65 " sanity check: insure that the zipfile has "PK" as its first two letters 66 " (zipped files have a leading PK as a "magic cookie") 67 if !filereadable(a:zipfile) || readfile(a:zipfile, "", 1)[0] !~ '^PK' 68 exe "noautocmd e ".fnameescape(a:zipfile) 69" call Dret("zip#Browse : not a zipfile<".a:zipfile.">") 70 return 71" else " Decho 72" call Decho("zip#Browse: a:zipfile<".a:zipfile."> passed PK test - its a zip file") 73 endif 74 75 let repkeep= &report 76 set report=10 77 78 " sanity checks 79 if !exists("*fnameescape") 80 if &verbose > 1 81 echoerr "the zip plugin is not available (your vim doens't support fnameescape())" 82 endif 83 return 84 endif 85 if !executable(g:zip_unzipcmd) 86 redraw! 87 echohl Error | echo "***error*** (zip#Browse) unzip not available on your system" 88" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 89 let &report= repkeep 90" call Dret("zip#Browse") 91 return 92 endif 93 if !filereadable(a:zipfile) 94 if a:zipfile !~# '^\a\+://' 95 " if its an url, don't complain, let url-handlers such as vim do its thing 96 redraw! 97 echohl Error | echo "***error*** (zip#Browse) File not readable<".a:zipfile.">" | echohl None 98" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 99 endif 100 let &report= repkeep 101" call Dret("zip#Browse : file<".a:zipfile."> not readable") 102 return 103 endif 104" call Decho("passed sanity checks") 105 if &ma != 1 106 set ma 107 endif 108 let b:zipfile= a:zipfile 109 110 setlocal noswapfile 111 setlocal buftype=nofile 112 setlocal bufhidden=hide 113 setlocal nobuflisted 114 setlocal nowrap 115 set ft=tar 116 117 " give header 118 call append(0, ['" zip.vim version '.g:loaded_zip, 119 \ '" Browsing zipfile '.a:zipfile, 120 \ '" Select a file with cursor and press ENTER']) 121 keepj $ 122 123" call Decho("exe silent r! ".g:zip_unzipcmd." -l -- ".s:Escape(a:zipfile,1)) 124 exe "keepj sil! r! ".g:zip_unzipcmd." -Z -1 -- ".s:Escape(a:zipfile,1) 125 if v:shell_error != 0 126 redraw! 127 echohl WarningMsg | echo "***warning*** (zip#Browse) ".fnameescape(a:zipfile)." is not a zip file" | echohl None 128" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 129 keepj sil! %d 130 let eikeep= &ei 131 set ei=BufReadCmd,FileReadCmd 132 exe "keepj r ".fnameescape(a:zipfile) 133 let &ei= eikeep 134 keepj 1d 135" call Dret("zip#Browse") 136 return 137 endif 138 139 setlocal noma nomod ro 140 noremap <silent> <buffer> <cr> :call <SID>ZipBrowseSelect()<cr> 141 142 let &report= repkeep 143" call Dret("zip#Browse") 144endfun 145 146" --------------------------------------------------------------------- 147" ZipBrowseSelect: {{{2 148fun! s:ZipBrowseSelect() 149" call Dfunc("ZipBrowseSelect() zipfile<".b:zipfile."> curfile<".expand("%").">") 150 let repkeep= &report 151 set report=10 152 let fname= getline(".") 153 154 " sanity check 155 if fname =~ '^"' 156 let &report= repkeep 157" call Dret("ZipBrowseSelect") 158 return 159 endif 160 if fname =~ '/$' 161 redraw! 162 echohl Error | echo "***error*** (zip#Browse) Please specify a file, not a directory" | echohl None 163" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 164 let &report= repkeep 165" call Dret("ZipBrowseSelect") 166 return 167 endif 168 169" call Decho("fname<".fname.">") 170 171 " get zipfile to the new-window 172 let zipfile = b:zipfile 173 let curfile= expand("%") 174" call Decho("zipfile<".zipfile.">") 175" call Decho("curfile<".curfile.">") 176 177 new 178 if !exists("g:zip_nomax") || g:zip_nomax == 0 179 wincmd _ 180 endif 181 let s:zipfile_{winnr()}= curfile 182" call Decho("exe e ".fnameescape("zipfile:".zipfile.'::'.fname)) 183 exe "e ".fnameescape("zipfile:".zipfile.'::'.fname) 184 filetype detect 185 186 let &report= repkeep 187" call Dret("ZipBrowseSelect : s:zipfile_".winnr()."<".s:zipfile_{winnr()}.">") 188endfun 189 190" --------------------------------------------------------------------- 191" zip#Read: {{{2 192fun! zip#Read(fname,mode) 193" call Dfunc("zip#Read(fname<".a:fname.">,mode=".a:mode.")") 194 let repkeep= &report 195 set report=10 196 197 if has("unix") 198 let zipfile = substitute(a:fname,'zipfile:\(.\{-}\)::[^\\].*$','\1','') 199 let fname = substitute(a:fname,'zipfile:.\{-}::\([^\\].*\)$','\1','') 200 else 201 let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','') 202 let fname = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','') 203 let fname = substitute(fname, '[', '[[]', 'g') 204 endif 205" call Decho("zipfile<".zipfile.">") 206" call Decho("fname <".fname.">") 207 208 " the following code does much the same thing as 209 " exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1) 210 " but allows zipfile:... entries in quickfix lists 211 let temp = tempname() 212" call Decho("using temp file<".temp.">") 213 let fn = expand('%:p') 214 exe "sil! !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1).' > '.temp 215" call Decho("exe sil! !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fnameescape(fname),1).' > '.temp) 216 sil exe 'keepalt file '.temp 217 sil keepj e! 218 sil exe 'keepalt file '.fnameescape(fn) 219 call delete(temp) 220 221 filetype detect 222 223 " cleanup 224 " keepj 0d " used to be needed for the ...r! ... method 225 set nomod 226 227 let &report= repkeep 228" call Dret("zip#Read") 229endfun 230 231" --------------------------------------------------------------------- 232" zip#Write: {{{2 233fun! zip#Write(fname) 234" call Dfunc("zip#Write(fname<".a:fname.">) zipfile_".winnr()."<".s:zipfile_{winnr()}.">") 235 let repkeep= &report 236 set report=10 237 238 " sanity checks 239 if !executable(g:zip_zipcmd) 240 redraw! 241 echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the zip pgm" | echohl None 242" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 243 let &report= repkeep 244" call Dret("zip#Write") 245 return 246 endif 247 if !exists("*mkdir") 248 redraw! 249 echohl Error | echo "***error*** (zip#Write) sorry, mkdir() doesn't work on your system" | echohl None 250" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 251 let &report= repkeep 252" call Dret("zip#Write") 253 return 254 endif 255 256 let curdir= getcwd() 257 let tmpdir= tempname() 258" call Decho("orig tempname<".tmpdir.">") 259 if tmpdir =~ '\.' 260 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e') 261 endif 262" call Decho("tmpdir<".tmpdir.">") 263 call mkdir(tmpdir,"p") 264 265 " attempt to change to the indicated directory 266 if s:ChgDir(tmpdir,s:ERROR,"(zip#Write) cannot cd to temporary directory") 267 let &report= repkeep 268" call Dret("zip#Write") 269 return 270 endif 271" call Decho("current directory now: ".getcwd()) 272 273 " place temporary files under .../_ZIPVIM_/ 274 if isdirectory("_ZIPVIM_") 275 call s:Rmdir("_ZIPVIM_") 276 endif 277 call mkdir("_ZIPVIM_") 278 cd _ZIPVIM_ 279" call Decho("current directory now: ".getcwd()) 280 281 if has("unix") 282 let zipfile = substitute(a:fname,'zipfile:\(.\{-}\)::[^\\].*$','\1','') 283 let fname = substitute(a:fname,'zipfile:.\{-}::\([^\\].*\)$','\1','') 284 else 285 let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','') 286 let fname = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','') 287 endif 288" call Decho("zipfile<".zipfile.">") 289" call Decho("fname <".fname.">") 290 291 if fname =~ '/' 292 let dirpath = substitute(fname,'/[^/]\+$','','e') 293 if has("win32unix") && executable("cygpath") 294 let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e') 295 endif 296" call Decho("mkdir(dirpath<".dirpath.">,p)") 297 call mkdir(dirpath,"p") 298 endif 299 if zipfile !~ '/' 300 let zipfile= curdir.'/'.zipfile 301 endif 302" call Decho("zipfile<".zipfile."> fname<".fname.">") 303 304 exe "w! ".fnameescape(fname) 305 if has("win32unix") && executable("cygpath") 306 let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e') 307 endif 308 309 if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$' 310 let fname = substitute(fname, '[', '[[]', 'g') 311 endif 312 313" call Decho(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0)) 314 call system(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0)) 315 if v:shell_error != 0 316 redraw! 317 echohl Error | echo "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname | echohl None 318" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 319 320 elseif s:zipfile_{winnr()} =~ '^\a\+://' 321 " support writing zipfiles across a network 322 let netzipfile= s:zipfile_{winnr()} 323" call Decho("handle writing <".zipfile."> across network as <".netzipfile.">") 324 1split|enew 325 let binkeep= &binary 326 let eikeep = &ei 327 set binary ei=all 328 exe "e! ".fnameescape(zipfile) 329 call netrw#NetWrite(netzipfile) 330 let &ei = eikeep 331 let &binary = binkeep 332 q! 333 unlet s:zipfile_{winnr()} 334 endif 335 336 " cleanup and restore current directory 337 cd .. 338 call s:Rmdir("_ZIPVIM_") 339 call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!") 340 call s:Rmdir(tmpdir) 341 setlocal nomod 342 343 let &report= repkeep 344" call Dret("zip#Write") 345endfun 346 347" --------------------------------------------------------------------- 348" s:Escape: {{{2 349fun! s:Escape(fname,isfilt) 350" call Dfunc("QuoteFileDir(fname<".a:fname."> isfilt=".a:isfilt.")") 351 if exists("*shellescape") 352 if a:isfilt 353 let qnameq= shellescape(a:fname,1) 354 else 355 let qnameq= shellescape(a:fname) 356 endif 357 else 358 let qnameq= g:zip_shq.escape(a:fname,g:zip_shq).g:zip_shq 359 endif 360" call Dret("QuoteFileDir <".qnameq.">") 361 return qnameq 362endfun 363 364" --------------------------------------------------------------------- 365" ChgDir: {{{2 366fun! s:ChgDir(newdir,errlvl,errmsg) 367" call Dfunc("ChgDir(newdir<".a:newdir."> errlvl=".a:errlvl." errmsg<".a:errmsg.">)") 368 369 try 370 exe "cd ".fnameescape(a:newdir) 371 catch /^Vim\%((\a\+)\)\=:E344/ 372 redraw! 373 if a:errlvl == s:NOTE 374 echo "***note*** ".a:errmsg 375 elseif a:errlvl == s:WARNING 376 echohl WarningMsg | echo "***warning*** ".a:errmsg | echohl NONE 377 elseif a:errlvl == s:ERROR 378 echohl Error | echo "***error*** ".a:errmsg | echohl NONE 379 endif 380" call inputsave()|call input("Press <cr> to continue")|call inputrestore() 381" call Dret("ChgDir 1") 382 return 1 383 endtry 384 385" call Dret("ChgDir 0") 386 return 0 387endfun 388 389" --------------------------------------------------------------------- 390" s:Rmdir: {{{2 391fun! s:Rmdir(fname) 392" call Dfunc("Rmdir(fname<".a:fname.">)") 393 if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$' 394 call system("rmdir /S/Q ".s:Escape(a:fname,0)) 395 else 396 call system("/bin/rm -rf ".s:Escape(a:fname,0)) 397 endif 398" call Dret("Rmdir") 399endfun 400 401" ------------------------------------------------------------------------ 402" Modelines And Restoration: {{{1 403let &cpo= s:keepcpo 404unlet s:keepcpo 405" vim:ts=8 fdm=marker 406