1 " tar.vim: Handles browsing tarfiles
4 " Version: 23 + modifications by Bram
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-2008 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.
20 " ---------------------------------------------------------------------
24 if &cp || exists("g:loaded_tar") || v:version < 700
27 let g:loaded_tar= "v23b"
28 "call Decho("loading autoload/tar.vim")
29 if v:version < 701 || (v:version == 701 && !has("patch299"))
30 echoerr "(autoload/tar.vim) need vim v7.1 with patchlevel 299"
33 " ---------------------------------------------------------------------
34 " Default Settings: {{{1
35 if !exists("g:tar_browseoptions")
36 let g:tar_browseoptions= "Ptf"
38 if !exists("g:tar_readoptions")
39 let g:tar_readoptions= "OPxf"
41 if !exists("g:tar_cmd")
44 if !exists("g:tar_writeoptions")
45 let g:tar_writeoptions= "uf"
48 if !exists("g:netrw_cygwin")
49 if has("win32") || has("win95") || has("win64") || has("win16")
50 if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
60 " set up shell quoting character
61 if !exists("g:tar_shq")
62 if exists("&shq") && &shq != ""
64 elseif has("win32") || has("win95") || has("win64") || has("win16")
65 if exists("g:netrw_cygwin") && g:netrw_cygwin
73 " call Decho("g:tar_shq<".g:tar_shq.">")
80 " ---------------------------------------------------------------------
82 fun! tar#Browse(tarfile)
83 " call Dfunc("tar#Browse(tarfile<".a:tarfile.">)")
88 if !executable(g:tar_cmd)
90 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
91 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
93 " call Dret("tar#Browse")
96 if !filereadable(a:tarfile)
97 " call Decho('a:tarfile<'.a:tarfile.'> not filereadable')
98 if a:tarfile !~# '^\a\+://'
99 " if its an url, don't complain, let url-handlers such as vim do its thing
101 echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
102 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
105 " call Dret("tar#Browse : file<".a:tarfile."> not readable")
111 let w:tarfile= a:tarfile
114 setlocal buftype=nofile
115 setlocal bufhidden=hide
121 " call Decho("printing header")
122 let lastline= line("$")
123 call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
124 call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
125 call setline(lastline+3,'" Select a file with cursor and press ENTER')
130 let tarfile= a:tarfile
131 if has("win32") && executable("cygpath")
133 let tarfile=substitute(system("cygpath -u ".s:Escape(tarfile,0)),'\n$','','e')
135 let curlast= line("$")
136 if tarfile =~# '\.\(gz\|tgz\)$'
137 " call Decho("1: exe silent r! gzip -d -c -- ".s:Escape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
138 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
139 elseif tarfile =~# '\.lrp'
140 " call Decho("2: exe silent r! cat -- ".s:Escape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - ")
141 exe "silent r! cat -- ".s:Escape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
142 elseif tarfile =~# '\.bz2$'
143 " call Decho("3: exe silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
144 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
146 if tarfile =~ '^\s*-'
147 " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
148 let tarfile = substitute(tarfile, '-', './-', '')
150 " call Decho("4: exe silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".s:Escape(tarfile,1))
151 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".s:Escape(tarfile,1)
153 if v:shell_error != 0
155 echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
156 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
157 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
160 if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~ '\c\%(warning\|error\|inappropriate\|unrecognized\)')
162 echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
163 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
166 set ei=BufReadCmd,FileReadCmd
167 exe "r ".fnameescape(a:tarfile)
170 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
174 setlocal noma nomod ro
175 noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
178 " call Dret("tar#Browse : w:tarfile<".w:tarfile.">")
181 " ---------------------------------------------------------------------
182 " TarBrowseSelect: {{{2
183 fun! s:TarBrowseSelect()
184 " call Dfunc("TarBrowseSelect() w:tarfile<".w:tarfile."> curfile<".expand("%").">")
187 let fname= getline(".")
188 " call Decho("fname<".fname.">")
190 if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
192 echohl WarningMsg | echo '***error*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"; See :help tar-options'
193 " call Dret('tar#BrowseSelect : rejecting tarfile member<'.fname.'> because of embedded "-"')
200 " call Dret("TarBrowseSelect")
204 " about to make a new window, need to use w:tarfile
205 let tarfile= w:tarfile
206 let curfile= expand("%")
207 if has("win32") && executable("cygpath")
209 let tarfile=substitute(system("cygpath -u ".s:Escape(tarfile,0)),'\n$','','e')
213 if !exists("g:tar_nomax") || g:tar_nomax == 0
216 let s:tblfile_{winnr()}= curfile
217 call tar#Read("tarfile:".tarfile.'::'.fname,1)
221 " call Dret("TarBrowseSelect : s:tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
224 " ---------------------------------------------------------------------
226 fun! tar#Read(fname,mode)
227 " call Dfunc("tar#Read(fname<".a:fname.">,mode=".a:mode.")")
230 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
231 let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
232 if has("win32") && executable("cygpath")
234 let tarfile=substitute(system("cygpath -u ".s:Escape(tarfile,0)),'\n$','','e')
236 " call Decho("tarfile<".tarfile.">")
237 " call Decho("fname<".fname.">")
239 if fname =~ '\.gz$' && executable("zcat")
242 elseif fname =~ '\.bz2$' && executable("bzcat")
248 if fname =~ '\.gz$\|\.bz2$\|\.Z$\|\.zip$'
253 if exists("g:tar_secure")
254 let tar_secure= " -- "
258 if tarfile =~# '\.\(gz\|tgz\)$'
259 " call Decho("5: exe silent r! gzip -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.tar_secure.s:Escape(fname,1))
260 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.s:Escape(fname,1).decmp
261 elseif tarfile =~# '\.lrp$'
262 " call Decho("6: exe silent r! cat ".s:Escape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.s:Escape(fname,1).decmp)
263 exe "silent r! cat -- ".s:Escape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.s:Escape(fname,1).decmp
264 elseif tarfile =~# '\.bz2$'
265 " call Decho("7: exe silent r! bzip2 -d -c ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.s:Escape(fname,1).decmp)
266 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.s:Escape(fname,1).decmp
268 if tarfile =~ '^\s*-'
269 " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
270 let tarfile = substitute(tarfile, '-', './-', '')
272 " call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions." "s:Escape(tarfile,1).tar_secure..s:Escape(fname,1).decmp)
273 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions." ".s:Escape(tarfile,1).tar_secure.s:Escape(fname,1).decmp
277 " because the reverse process of compressing changed files back into the tarball is not currently supported
281 let w:tarfile= a:fname
282 exe "file tarfile::".fnameescape(fname)
289 " call Dret("tar#Read : w:tarfile<".w:tarfile.">")
292 " ---------------------------------------------------------------------
294 fun! tar#Write(fname)
295 " call Dfunc("tar#Write(fname<".a:fname.">) w:tarfile<".w:tarfile."> tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
299 if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
301 echohl WarningMsg | echo '***error*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"; See :help tar-options'
302 " call Dret('tar#Write : rejecting tarfile member<'.fname.'> because of embedded "-"')
307 if !executable(g:tar_cmd)
309 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
310 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
312 " call Dret("tar#Write")
317 echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
318 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
320 " call Dret("tar#Write")
325 let tmpdir= tempname()
326 " call Decho("orig tempname<".tmpdir.">")
328 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
330 " call Decho("tmpdir<".tmpdir.">")
331 call mkdir(tmpdir,"p")
333 " attempt to change to the indicated directory
335 exe "cd ".fnameescape(tmpdir)
336 catch /^Vim\%((\a\+)\)\=:E344/
338 echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
339 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
341 " call Dret("tar#Write")
344 " call Decho("current directory now: ".getcwd())
346 " place temporary files under .../_ZIPVIM_/
347 if isdirectory("_ZIPVIM_")
348 call s:Rmdir("_ZIPVIM_")
350 call mkdir("_ZIPVIM_")
352 " call Decho("current directory now: ".getcwd())
354 let tarfile = substitute(w:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
355 let fname = substitute(w:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
357 " handle compressed archives
358 if tarfile =~# '\.gz'
359 call system("gzip -d -- ".s:Escape(tarfile,0))
360 let tarfile = substitute(tarfile,'\.gz','','e')
361 let compress= "gzip -- ".s:Escape(tarfile,0)
362 " call Decho("compress<".compress.">")
363 elseif tarfile =~# '\.tgz'
364 call system("gzip -d -- ".s:Escape(tarfile,0))
365 let tarfile = substitute(tarfile,'\.tgz','.tar','e')
366 let compress= "gzip -- ".s:Escape(tarfile,0)
368 " call Decho("compress<".compress.">")
369 elseif tarfile =~# '\.bz2'
370 call system("bzip2 -d -- ".s:Escape(tarfile,0))
371 let tarfile = substitute(tarfile,'\.bz2','','e')
372 let compress= "bzip2 -- ".s:Escape(tarfile,0)
373 " call Decho("compress<".compress.">")
375 " call Decho("tarfile<".tarfile.">")
377 if v:shell_error != 0
379 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
380 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
383 " call Decho("tarfile<".tarfile."> fname<".fname.">")
386 let dirpath = substitute(fname,'/[^/]\+$','','e')
387 if executable("cygpath")
388 let dirpath = substitute(system("cygpath ".s:Escape(dirpath, 0)),'\n','','e')
390 call mkdir(dirpath,"p")
393 let tarfile= curdir.'/'.tarfile
395 if tarfile =~ '^\s*-'
396 " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
397 let tarfile = substitute(tarfile, '-', './-', '')
399 " call Decho("tarfile<".tarfile."> fname<".fname.">")
401 if exists("g:tar_secure")
402 let tar_secure= " -- "
406 exe "w! ".fnameescape(fname)
407 if executable("cygpath")
408 let tarfile = substitute(system("cygpath ".s:Escape(tarfile,0)),'\n','','e')
411 " delete old file from tarfile
412 " call Decho("system(".g:tar_cmd." --delete -f ".s:Escape(tarfile,0)." -- ".s:Escape(fname,0).")")
413 call system(g:tar_cmd." --delete -f ".s:Escape(tarfile,0).tar_secure.s:Escape(fname,0))
414 if v:shell_error != 0
416 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
417 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
420 " update tarfile with new file
421 " call Decho(g:tar_cmd." -".g:tar_writeoptions." ".s:Escape(tarfile,0).tar_secure.s:Escape(fname,0))
422 call system(g:tar_cmd." -".g:tar_writeoptions." ".s:Escape(tarfile,0).tar_secure.s:Escape(fname,0))
423 if v:shell_error != 0
425 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
426 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
427 elseif exists("compress")
428 " call Decho("call system(".compress.")")
429 call system(compress)
431 " call Decho("rename(".tarfile.".gz,".substitute(tarfile,'\.tar$','.tgz','e').")")
432 call rename(tarfile.".gz",substitute(tarfile,'\.tar$','.tgz','e'))
437 " support writing tarfiles across a network
438 if s:tblfile_{winnr()} =~ '^\a\+://'
439 " call Decho("handle writing <".tarfile."> across network to <".s:tblfile_{winnr()}.">")
440 let tblfile= s:tblfile_{winnr()}
445 exe "e! ".fnameescape(tarfile)
446 call netrw#NetWrite(tblfile)
448 let &binary = binkeep
450 unlet s:tblfile_{winnr()}
454 " cleanup and restore current directory
456 call s:Rmdir("_ZIPVIM_")
457 exe "cd ".fnameescape(curdir)
461 " call Dret("tar#Write")
464 " ---------------------------------------------------------------------
467 " call Dfunc("Rmdir(fname<".a:fname.">)")
469 call system("/bin/rm -rf -- ".s:Escape(a:fname,0))
470 elseif has("win32") || has("win95") || has("win64") || has("win16")
472 call system("/bin/rm -rf -- ".s:Escape(a:fname,0))
474 call system("del /S ".s:Escape(a:fname,0))
480 " ---------------------------------------------------------------------
482 fun s:Escape(name,isfilt)
483 " shellescape() was added by patch 7.0.111
484 if exists("*shellescape")
486 let qnameq= shellescape(a:name,1)
488 let qnameq= shellescape(a:name)
491 let qnameq= g:tar_shq . a:name . g:tar_shq
496 " ---------------------------------------------------------------------
497 " Modelines And Restoration: {{{1
500 " vim:ts=8 fdm=marker