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-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= "v20"
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 " call Decho("4: exe silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".s:Escape(tarfile,0))
147 exe "silent r! ".g:tar_cmd." -".g:tar_browseoptions." ".s:Escape(tarfile,1)
149 if v:shell_error != 0
151 echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
152 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
153 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
156 if line("$") == curlast || ( line("$") == (curlast + 1) && getline("$") =~ '\c\%(warning\|error\|inappropriate\|unrecognized\)')
158 echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
159 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
162 set ei=BufReadCmd,FileReadCmd
163 exe "r ".fnameescape(a:tarfile)
166 " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
170 setlocal noma nomod ro
171 noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
174 " call Dret("tar#Browse : w:tarfile<".w:tarfile.">")
177 " ---------------------------------------------------------------------
178 " TarBrowseSelect: {{{2
179 fun! s:TarBrowseSelect()
180 " call Dfunc("TarBrowseSelect() w:tarfile<".w:tarfile."> curfile<".expand("%").">")
183 let fname= getline(".")
184 " call Decho("fname<".fname.">")
189 " call Dret("TarBrowseSelect")
193 " about to make a new window, need to use w:tarfile
194 let tarfile= w:tarfile
195 let curfile= expand("%")
196 if has("win32") && executable("cygpath")
198 let tarfile=substitute(system("cygpath -u ".s:Escape(tarfile,0)),'\n$','','e')
202 if !exists("g:tar_nomax") || g:tar_nomax == 0
205 let s:tblfile_{winnr()}= curfile
206 call tar#Read("tarfile:".tarfile.'::'.fname,1)
210 " call Dret("TarBrowseSelect : s:tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
213 " ---------------------------------------------------------------------
215 fun! tar#Read(fname,mode)
216 " call Dfunc("tar#Read(fname<".a:fname.">,mode=".a:mode.")")
219 let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
220 let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
221 if has("win32") && executable("cygpath")
223 let tarfile=substitute(system("cygpath -u ".s:Escape(tarfile,0)),'\n$','','e')
225 " call Decho("tarfile<".tarfile.">")
226 " call Decho("fname<".fname.">")
228 if fname =~ '\.gz$' && executable("zcat")
231 elseif fname =~ '\.bz2$' && executable("bzcat")
237 if fname =~ '\.gz$\|\.bz2$\|\.Z$\|\.zip$'
242 if tarfile =~# '\.\(gz\|tgz\)$'
243 " call Decho("5: exe silent r! gzip -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd.' -'.g:tar_readoptions.' - '.s:Escape(fname,1))
244 exe "silent r! gzip -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp
245 elseif tarfile =~# '\.lrp$'
246 " call Decho("6: exe silent r! cat ".s:Escape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp)
247 exe "silent r! cat -- ".s:Escape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp
248 elseif tarfile =~# '\.bz2$'
249 " call Decho("7: exe silent r! bzip2 -d -c ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp)
250 exe "silent r! bzip2 -d -c -- ".s:Escape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".s:Escape(fname,1).decmp
252 " call Decho("8: exe silent r! ".g:tar_cmd." -".g:tar_readoptions." -- ".s:Escape(tarfile,1)." ".s:Escape(fname,1))
253 exe "silent r! ".g:tar_cmd." -".g:tar_readoptions." ".s:Escape(tarfile,1)." -- ".s:Escape(fname,1).decmp
257 " because the reverse process of compressing changed files back into the tarball is not currently supported
261 let w:tarfile= a:fname
262 exe "file tarfile::".fnameescape(fname)
269 " call Dret("tar#Read : w:tarfile<".w:tarfile.">")
272 " ---------------------------------------------------------------------
274 fun! tar#Write(fname)
275 " call Dfunc("tar#Write(fname<".a:fname.">) w:tarfile<".w:tarfile."> tblfile_".winnr()."<".s:tblfile_{winnr()}.">")
280 if !executable(g:tar_cmd)
282 echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
283 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
285 " call Dret("tar#Write")
290 echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
291 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
293 " call Dret("tar#Write")
298 let tmpdir= tempname()
299 " call Decho("orig tempname<".tmpdir.">")
301 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
303 " call Decho("tmpdir<".tmpdir.">")
304 call mkdir(tmpdir,"p")
306 " attempt to change to the indicated directory
308 exe "cd ".fnameescape(tmpdir)
309 catch /^Vim\%((\a\+)\)\=:E344/
311 echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
312 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
314 " call Dret("tar#Write")
317 " call Decho("current directory now: ".getcwd())
319 " place temporary files under .../_ZIPVIM_/
320 if isdirectory("_ZIPVIM_")
321 call s:Rmdir("_ZIPVIM_")
323 call mkdir("_ZIPVIM_")
325 " call Decho("current directory now: ".getcwd())
327 let tarfile = substitute(w:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
328 let fname = substitute(w:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
330 " handle compressed archives
331 if tarfile =~# '\.gz'
332 call system("gzip -d -- ".s:Escape(tarfile,0))
333 let tarfile = substitute(tarfile,'\.gz','','e')
334 let compress= "gzip ".s:Escape(tarfile,0)
335 elseif tarfile =~# '\.tgz'
336 call system("gzip -d -- ".s:Escape(tarfile,0))
337 let tarfile = substitute(tarfile,'\.tgz','.tar','e')
338 let compress= "gzip -- ".s:Escape(tarfile,0)
340 elseif tarfile =~# '\.bz2'
341 call system("bzip2 -d -- ".s:Escape(tarfile,0))
342 let tarfile = substitute(tarfile,'\.bz2','','e')
343 let compress= "bzip2 -- ".s:Escape(tarfile,0)
345 " call Decho("tarfile<".tarfile.">")
346 " call Decho("compress<".compress.">")
348 if v:shell_error != 0
350 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
351 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
354 " call Decho("tarfile<".tarfile."> fname<".fname.">")
357 let dirpath = substitute(fname,'/[^/]\+$','','e')
358 if executable("cygpath")
359 let dirpath = substitute(system("cygpath ".s:Escape(dirpath, 0)),'\n','','e')
361 call mkdir(dirpath,"p")
364 let tarfile= curdir.'/'.tarfile
366 " call Decho("tarfile<".tarfile."> fname<".fname.">")
368 exe "w! ".fnameescape(fname)
369 if executable("cygpath")
370 let tarfile = substitute(system("cygpath ".s:Escape(tarfile,0)),'\n','','e')
373 " delete old file from tarfile
374 " call Decho("system(tar --delete -f ".s:Escape(tarfile,0)." -- ".s:Escape(fname,0).")")
375 call system("tar --delete -f ".s:Escape(tarfile,0)." -- ".s:Escape(fname,0))
376 if v:shell_error != 0
378 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
379 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
382 " update tarfile with new file
383 " call Decho("tar -".g:tar_writeoptions." ".s:Escape(tarfile,0)." -- ".s:Escape(fname,0))
384 call system("tar -".g:tar_writeoptions." ".s:Escape(tarfile,0)." -- ".s:Escape(fname,0))
385 if v:shell_error != 0
387 echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
388 " call inputsave()|call input("Press <cr> to continue")|call inputrestore()
389 elseif exists("compress")
390 " call Decho("call system(".compress.")")
391 call system(compress)
393 " call Decho("rename(".tarfile.".gz,".substitute(tarfile,'\.tar$','.tgz','e').")")
394 call rename(tarfile.".gz",substitute(tarfile,'\.tar$','.tgz','e'))
399 " support writing tarfiles across a network
400 if s:tblfile_{winnr()} =~ '^\a\+://'
401 " call Decho("handle writing <".tarfile."> across network to <".s:tblfile_{winnr()}.">")
402 let tblfile= s:tblfile_{winnr()}
407 exe "e! ".fnameescape(tarfile)
408 call netrw#NetWrite(tblfile)
410 let &binary = binkeep
412 unlet s:tblfile_{winnr()}
416 " cleanup and restore current directory
418 call s:Rmdir("_ZIPVIM_")
419 exe "cd ".fnameescape(curdir)
423 " call Dret("tar#Write")
426 " ---------------------------------------------------------------------
429 " call Dfunc("Rmdir(fname<".a:fname.">)")
431 call system("/bin/rm -rf -- ".s:Escape(a:fname,0))
432 elseif has("win32") || has("win95") || has("win64") || has("win16")
434 call system("/bin/rm -rf -- ".s:Escape(a:fname,0))
436 call system("del /S ".s:Escape(a:fname,0))
442 " ---------------------------------------------------------------------
444 fun s:Escape(name,isfilt)
445 " shellescape() was added by patch 7.0.111
446 if exists("*shellescape")
448 let qnameq= shellescape(a:name,1)
450 let qnameq= shellescape(a:name)
453 let qnameq= g:tar_shq . a:name . g:tar_shq
458 " ---------------------------------------------------------------------
459 " Modelines And Restoration: {{{1
462 " vim:ts=8 fdm=marker