1 " tar.vim: Handles browsing tarfiles
5 " Maintainer: Charles E Campbell, Jr <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
6 " License: Vim License (see vim's :help license)
8 " Contains many ideas from Michael Toren's <tar.vim>
10 " Copyright: Copyright (C) 2005-2009 Charles E. Campbell, Jr. {{{1
11 " Permission is hereby granted to use and distribute this code,
12 " with or without modifications, provided that this copyright
13 " notice is copied with it. Like anything else that's free,
14 " tar.vim and tarPlugin.vim are provided *as is* and comes
15 " with no warranty of any kind, either expressed or implied.
16 " By using this plugin, you agree that in no event will the
17 " copyright holder be liable for any damages resulting from
18 " the use of this software.
19 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
20 " ---------------------------------------------------------------------
22 if &cp || exists("g:loaded_tar")
25 let g:loaded_tar= "v24"
28 echo "***warning*** this version of tar needs vim 7.2"
34 "call Decho("loading autoload/tar.vim")
36 " ---------------------------------------------------------------------
37 " Default Settings: {{{1
38 if !exists("g:tar_browseoptions")
39 let g:tar_browseoptions= "Ptf"
41 if !exists("g:tar_readoptions")
42 let g:tar_readoptions= "OPxf"
44 if !exists("g:tar_cmd")
47 if !exists("g:tar_writeoptions")
48 let g:tar_writeoptions= "uf"
50 if !exists("g:tar_copycmd")
51 if !exists("g:netrw_localcopycmd")
52 if has("win32") || has("win95") || has("win64") || has("win16")
54 let g:netrw_localcopycmd= "cp"
56 let g:netrw_localcopycmd= "copy"
58 elseif has("unix") || has("macunix")
59 let g:netrw_localcopycmd= "cp"
61 let g:netrw_localcopycmd= ""
64 let g:tar_copycmd= g:netrw_localcopycmd
66 if !exists("g:netrw_cygwin")
67 if has("win32") || has("win95") || has("win64") || has("win16")
68 if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
77 if !exists("g:tar_extractcmd")
78 let g:tar_extractcmd= "tar -xf"
81 " set up shell quoting character
82 if !exists("g:tar_shq")
83 if exists("&shq") && &shq != ""
85 elseif has("win32") || has("win95") || has("win64") || has("win16")
86 if exists("g:netrw_cygwin") && g:netrw_cygwin
94 " call Decho("g:tar_shq<".g:tar_shq.">")
101 " ---------------------------------------------------------------------
103 fun! tar#Browse(tarfile)
104 " call Dfunc("tar#Browse(tarfile<".a:tarfile.">)")
109 if !executable(g:tar_cmd)
111 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
113 " call Dret("tar#Browse")
116 if !filereadable(a:tarfile)
117 " call Decho('a:tarfile<'.a:tarfile.'> not filereadable')
118 if a:tarfile !~# '^\a\+://'
119 " if its an url, don't complain, let url-handlers such as vim do its thing
121 echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
124 " call Dret("tar#Browse : file<".a:tarfile."> not readable")
130 let w:tarfile= a:tarfile
133 setlocal buftype=nofile
134 setlocal bufhidden=hide
140 " call Decho("printing header")
141 let lastline= line("$")
142 call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
143 call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
144 call setline(lastline+3,'" Select a file with cursor and press ENTER')
149 let tarfile= a:tarfile
150 if has("win32") && executable("cygpath")
152 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
154 let curlast= line("$")
155 if tarfile =~# '\.\(gz\|tgz\)$'
156 " call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
157 exe "silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
158 elseif tarfile =~# '\.lrp'
159 " call Decho("2: exe silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ")
160 exe "silent r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
161 elseif tarfile =~# '\.bz2$'
162 " call Decho("3: exe silent r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
163 exe "silent r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
164 elseif tarfile =~# '\.lzma$'
165 " call Decho("3: exe silent r! lzma -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
166 exe "silent r! lzma -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
168 if tarfile =~ '^\s*-'
169 " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
170 let tarfile = substitute(tarfile, '-', './-', '')
172 " call Decho("4: exe silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,0))
173 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1)
175 if v:shell_error != 0
177 echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
178 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
181 if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~ '\c\%(warning\|error\|inappropriate\|unrecognized\)')
183 echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
186 set ei=BufReadCmd,FileReadCmd
187 exe "r ".fnameescape(a:tarfile)
190 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
194 setlocal noma nomod ro
195 noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
198 " call Dret("tar#Browse : w:tarfile<".w:tarfile.">")
201 " ---------------------------------------------------------------------
202 " TarBrowseSelect: {{{2
203 fun! s:TarBrowseSelect()
204 " call Dfunc("TarBrowseSelect() w:tarfile<".w:tarfile."> curfile<".expand("%").">")
207 let fname= getline(".")
208 " call Decho("fname<".fname.">")
210 if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
212 echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
213 " call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"')
220 " call Dret("TarBrowseSelect")
224 " about to make a new window, need to use w:tarfile
225 let tarfile= w:tarfile
226 let curfile= expand("%")
227 if has("win32") && executable("cygpath")
229 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
233 if !exists("g:tar_nomax") || g:tar_nomax == 0
236 let s:tblfile_{winnr()}= curfile
237 call tar#Read("tarfile:".tarfile.'::'.fname,1)
241 " call Dret("TarBrowseSelect : s:tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
244 " ---------------------------------------------------------------------
246 fun! tar#Read(fname,mode)
247 " call Dfunc("tar#Read(fname<".a:fname.">,mode=".a:mode.")")
250 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
251 let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
252 if has("win32") && executable("cygpath")
254 let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
256 " call Decho("tarfile<".tarfile.">")
257 " call Decho("fname<".fname.">")
259 if fname =~ '\.bz2$' && executable("bzcat")
262 elseif fname =~ '\.gz$' && executable("zcat")
265 elseif fname =~ '\.lzma$' && executable("lzcat")
271 if fname =~ '\.bz2$\|\.gz$\|\.lzma$\|\.zip$\|\.Z$'
276 if exists("g:tar_secure")
277 let tar_secure= " -- "
281 if tarfile =~# '\.bz2$'
282 " call Decho("7: exe silent r! bzip2 -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
283 exe "silent r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
284 elseif tarfile =~# '\.\(gz\|tgz\)$'
285 " call Decho("5: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.shellescape(fname,1))
286 exe "silent r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
287 elseif tarfile =~# '\.lrp$'
288 " call Decho("6: exe silent r! cat ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
289 exe "silent r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
290 elseif tarfile =~# '\.lzma$'
291 " call Decho("7: exe silent r! lzma -d -c ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp)
292 exe "silent r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
294 if tarfile =~ '^\s*-'
295 " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
296 let tarfile = substitute(tarfile, '-', './-', '')
298 " call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions.tar_secure.shellescape(tarfile,1)." ".shellescape(fname,1).decmp)
299 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
303 " because the reverse process of compressing changed files back into the tarball is not currently supported
307 let w:tarfile= a:fname
308 exe "file tarfile::".fnameescape(fname)
315 " call Dret("tar#Read : w:tarfile<".w:tarfile.">")
318 " ---------------------------------------------------------------------
320 fun! tar#Write(fname)
321 " call Dfunc("tar#Write(fname<".a:fname.">) w:tarfile<".w:tarfile."> tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
325 if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
327 echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"'
328 " call Dret('tar#Write : rejecting tarfile member<'.fname.'> because of embedded "-"')
333 if !executable(g:tar_cmd)
335 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
337 " call Dret("tar#Write")
342 echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
344 " call Dret("tar#Write")
349 let tmpdir= tempname()
350 " call Decho("orig tempname<".tmpdir.">")
352 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
354 " call Decho("tmpdir<".tmpdir.">")
355 call mkdir(tmpdir,"p")
357 " attempt to change to the indicated directory
359 exe "cd ".fnameescape(tmpdir)
360 catch /^Vim\%((\a\+)\)\=:E344/
362 echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
364 " call Dret("tar#Write")
367 " call Decho("current directory now: ".getcwd())
369 " place temporary files under .../_ZIPVIM_/
370 if isdirectory("_ZIPVIM_")
371 call s:Rmdir("_ZIPVIM_")
373 call mkdir("_ZIPVIM_")
375 " call Decho("current directory now: ".getcwd())
377 let tarfile = substitute(w:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
378 let fname = substitute(w:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
380 " handle compressed archives
381 if tarfile =~# '\.bz2'
382 call system("bzip2 -d -- ".shellescape(tarfile,0))
383 let tarfile = substitute(tarfile,'\.bz2','','e')
384 let compress= "bzip2 -- ".shellescape(tarfile,0)
385 " call Decho("compress<".compress.">")
386 elseif tarfile =~# '\.gz'
387 call system("gzip -d -- ".shellescape(tarfile,0))
388 let tarfile = substitute(tarfile,'\.gz','','e')
389 let compress= "gzip -- ".shellescape(tarfile,0)
390 " call Decho("compress<".compress.">")
391 elseif tarfile =~# '\.lzma'
392 call system("lzma -d -- ".shellescape(tarfile,0))
393 let tarfile = substitute(tarfile,'\.lzma','','e')
394 let compress= "lzma -- ".shellescape(tarfile,0)
395 " call Decho("compress<".compress.">")
396 elseif tarfile =~# '\.tgz'
397 call system("gzip -d -- ".shellescape(tarfile,0))
398 let tarfile = substitute(tarfile,'\.tgz','.tar','e')
399 let compress= "gzip -- ".shellescape(tarfile,0)
401 " call Decho("compress<".compress.">")
403 " call Decho("tarfile<".tarfile.">")
405 if v:shell_error != 0
407 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
410 " call Decho("tarfile<".tarfile."> fname<".fname.">")
413 let dirpath = substitute(fname,'/[^/]\+$','','e')
414 if executable("cygpath")
415 let dirpath = substitute(system("cygpath ".shellescape(dirpath, 0)),'\n','','e')
417 call mkdir(dirpath,"p")
420 let tarfile= curdir.'/'.tarfile
422 if tarfile =~ '^\s*-'
423 " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
424 let tarfile = substitute(tarfile, '-', './-', '')
426 " call Decho("tarfile<".tarfile."> fname<".fname.">")
428 if exists("g:tar_secure")
429 let tar_secure= " -- "
433 exe "w! ".fnameescape(fname)
434 if executable("cygpath")
435 let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
438 " delete old file from tarfile
439 " call Decho("system(".g:tar_cmd." --delete -f ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")")
440 call system(g:tar_cmd." --delete -f ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
441 if v:shell_error != 0
443 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
446 " update tarfile with new file
447 " call Decho(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
448 call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
449 if v:shell_error != 0
451 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
452 elseif exists("compress")
453 " call Decho("call system(".compress.")")
454 call system(compress)
456 " call Decho("rename(".tarfile.".gz,".substitute(tarfile,'\.tar$','.tgz','e').")")
457 call rename(tarfile.".gz",substitute(tarfile,'\.tar$','.tgz','e'))
462 " support writing tarfiles across a network
463 if s:tblfile_{winnr()} =~ '^\a\+://'
464 " call Decho("handle writing <".tarfile."> across network to <".s:tblfile_{winnr()}.">")
465 let tblfile= s:tblfile_{winnr()}
467 let binkeep= &l:binary
470 exe "e! ".fnameescape(tarfile)
471 call netrw#NetWrite(tblfile)
473 let &l:binary = binkeep
475 unlet s:tblfile_{winnr()}
479 " cleanup and restore current directory
481 call s:Rmdir("_ZIPVIM_")
482 exe "cd ".fnameescape(curdir)
486 " call Dret("tar#Write")
489 " ---------------------------------------------------------------------
492 " call Dfunc("Rmdir(fname<".a:fname.">)")
494 call system("/bin/rm -rf -- ".shellescape(a:fname,0))
495 elseif has("win32") || has("win95") || has("win64") || has("win16")
497 call system("/bin/rm -rf -- ".shellescape(a:fname,0))
499 call system("del /S ".shellescape(a:fname,0))
505 " ---------------------------------------------------------------------
506 " tar#Vimuntar: installs a tarball in the user's .vim / vimfiles directory {{{2
507 fun! tar#Vimuntar(...)
508 " call Dfunc("tar#Vimuntar() a:0=".a:0." a:1<".(exists("a:1")? a:1 : "-n/a-").">")
509 let tarball = expand("%")
510 " call Decho("tarball<".tarball.">")
511 let tarbase = substitute(tarball,'\..*$','','')
512 " call Decho("tarbase<".tarbase.">")
513 let tarhome = expand("%:p")
514 if has("win32") || has("win95") || has("win64") || has("win16")
515 let tarhome= substitute(tarhome,'\\','/','g')
517 let tarhome= substitute(tarhome,'/[^/]*$','','')
518 " call Decho("tarhome<".tarhome.">")
519 let tartail = expand("%:t")
520 " call Decho("tartail<".tartail.">")
521 let curdir = getcwd()
522 " call Decho("curdir <".curdir.">")
524 if a:0 > 0 && a:1 != ""
527 let vimhome= vimball#VimballHome()
529 " call Decho("vimhome<".vimhome.">")
531 " call Decho("curdir<".curdir."> vimhome<".vimhome.">")
532 if simplify(curdir) != simplify(vimhome)
533 " copy (possibly compressed) tarball to .vim/vimfiles
534 " call Decho(netrw#WinPath(g:tar_copycmd)." ".shellescape(tartail)." ".shellescape(vimhome))
535 call system(netrw#WinPath(g:tar_copycmd)." ".shellescape(tartail)." ".shellescape(vimhome))
536 " call Decho("exe cd ".fnameescape(vimhome))
537 exe "cd ".fnameescape(vimhome)
539 " call Decho("getcwd<".getcwd().">")
541 " if necessary, decompress the tarball; then, extract it
542 if tartail =~ '\.tgz'
543 if executable("gunzip")
544 silent exe "!gunzip ".shellescape(tartail)
545 elseif executable("gzip")
546 silent exe "!gzip -d ".shellescape(tartail)
548 echoerr "unable to decompress<".tartail."> on this sytem"
549 if simplify(curdir) != simplify(tarhome)
550 " remove decompressed tarball, restore directory
551 " call Decho("delete(".tartail.".tar)")
552 call delete(tartail.".tar")
553 " call Decho("exe cd ".fnameescape(curdir))
554 exe "cd ".fnameescape(curdir)
556 " call Dret("tar#Vimuntar")
560 call vimball#Decompress(tartail,0)
562 let extractcmd= netrw#WinPath(g:tar_extractcmd)
563 " call Decho("system(".extractcmd." ".shellescape(tarbase.".tar").")")
564 call system(extractcmd." ".shellescape(tarbase.".tar"))
567 if filereadable("doc/".tarbase.".txt")
568 " call Decho("exe helptags ".getcwd()."/doc")
569 exe "helptags ".getcwd()."/doc"
572 if simplify(tarhome) != simplify(vimhome)
573 " remove decompressed tarball, restore directory
574 call delete(vimhome."/".tarbase.".tar")
575 exe "cd ".fnameescape(curdir)
578 " call Dret("tar#Vimuntar")
581 " =====================================================================
582 " Modelines And Restoration: {{{1
585 " vim:ts=8 fdm=marker