1" zip.vim: Handles browsing zipfiles
2"            AUTOLOAD PORTION
3" Date:		Apr 12, 2010
4" Version:	23
5" Maintainer:	Charles E Campbell, Jr <NdrOchip@ScampbellPfamily.AbizM-NOSPAM>
6" License:	Vim License  (see vim's :help license)
7" Copyright:    Copyright (C) 2005-2008 Charles E. Campbell, Jr. {{{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
17" ---------------------------------------------------------------------
18" Load Once: {{{1
19if &cp || exists("g:loaded_zip")
20 finish
21endif
22let g:loaded_zip= "v23"
23if v:version < 702
24 echohl WarningMsg
25 echo "***warning*** this version of zip needs vim 7.2"
26 echohl Normal
27 finish
28endif
29let s:keepcpo= &cpo
30set cpo&vim
31
32let s:zipfile_escape = ' ?&;\'
33let s:ERROR          = 2
34let s:WARNING        = 1
35let s:NOTE           = 0
36
37" ---------------------------------------------------------------------
38"  Global Values: {{{1
39if !exists("g:zip_shq")
40 if &shq != ""
41  let g:zip_shq= &shq
42 elseif has("unix")
43  let g:zip_shq= "'"
44 else
45  let g:zip_shq= '"'
46 endif
47endif
48if !exists("g:zip_zipcmd")
49 let g:zip_zipcmd= "zip"
50endif
51if !exists("g:zip_unzipcmd")
52 let g:zip_unzipcmd= "unzip"
53endif
54
55" ----------------
56"  Functions: {{{1
57" ----------------
58
59" ---------------------------------------------------------------------
60" zip#Browse: {{{2
61fun! zip#Browse(zipfile)
62"  call Dfunc("zip#Browse(zipfile<".a:zipfile.">)")
63  let repkeep= &report
64  set report=10
65
66  " sanity checks
67  if !exists("*fnameescape")
68   if &verbose > 1
69    echoerr "the zip plugin is not available (your vim doens't support fnameescape())"
70   endif
71   return
72  endif
73  if !executable(g:zip_unzipcmd)
74   redraw!
75   echohl Error | echo "***error*** (zip#Browse) unzip not available on your system"
76"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
77   let &report= repkeep
78"   call Dret("zip#Browse")
79   return
80  endif
81  if !filereadable(a:zipfile)
82   if a:zipfile !~# '^\a\+://'
83    " if its an url, don't complain, let url-handlers such as vim do its thing
84    redraw!
85    echohl Error | echo "***error*** (zip#Browse) File not readable<".a:zipfile.">" | echohl None
86"    call inputsave()|call input("Press <cr> to continue")|call inputrestore()
87   endif
88   let &report= repkeep
89"   call Dret("zip#Browse : file<".a:zipfile."> not readable")
90   return
91  endif
92"  call Decho("passed sanity checks")
93  if &ma != 1
94   set ma
95  endif
96  let b:zipfile= a:zipfile
97
98  setlocal noswapfile
99  setlocal buftype=nofile
100  setlocal bufhidden=hide
101  setlocal nobuflisted
102  setlocal nowrap
103  set ft=tar
104
105  " give header
106  let lastline= line("$")
107  call setline(lastline+1,'" zip.vim version '.g:loaded_zip)
108  call setline(lastline+2,'" Browsing zipfile '.a:zipfile)
109  call setline(lastline+3,'" Select a file with cursor and press ENTER')
110  $put =''
111  0d
112  $
113
114"  call Decho("exe silent r! ".g:zip_unzipcmd." -l -- ".s:Escape(a:zipfile,1))
115  exe "silent r! ".g:zip_unzipcmd." -l -- ".s:Escape(a:zipfile,1)
116  if v:shell_error != 0
117   redraw!
118   echohl WarningMsg | echo "***warning*** (zip#Browse) ".fnameescape(a:zipfile)." is not a zip file" | echohl None
119"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
120   silent %d
121   let eikeep= &ei
122   set ei=BufReadCmd,FileReadCmd
123   exe "r ".fnameescape(a:zipfile)
124   let &ei= eikeep
125   1d
126"   call Dret("zip#Browse")
127   return
128  endif
129"  call Decho("line 6: ".getline(6))
130  let namecol= stridx(getline(6),'Name') + 1
131"  call Decho("namecol=".namecol)
132  4,$g/^\s*----/d
133  4,$g/^\s*\a/d
134  $d
135  if namecol > 0
136   exe 'silent 4,$s/^.*\%'.namecol.'c//'
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"  call Decho("exe r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1))
209  exe "silent r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
210
211  " cleanup
212  0d
213  set nomod
214
215  let &report= repkeep
216"  call Dret("zip#Read")
217endfun
218
219" ---------------------------------------------------------------------
220" zip#Write: {{{2
221fun! zip#Write(fname)
222"  call Dfunc("zip#Write(fname<".a:fname.">) zipfile_".winnr()."<".s:zipfile_{winnr()}.">")
223  let repkeep= &report
224  set report=10
225
226  " sanity checks
227  if !executable(g:zip_zipcmd)
228   redraw!
229   echohl Error | echo "***error*** (zip#Write) sorry, your system doesn't appear to have the zip pgm" | echohl None
230"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
231   let &report= repkeep
232"   call Dret("zip#Write")
233   return
234  endif
235  if !exists("*mkdir")
236   redraw!
237   echohl Error | echo "***error*** (zip#Write) sorry, mkdir() doesn't work on your system" | echohl None
238"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
239   let &report= repkeep
240"   call Dret("zip#Write")
241   return
242  endif
243
244  let curdir= getcwd()
245  let tmpdir= tempname()
246"  call Decho("orig tempname<".tmpdir.">")
247  if tmpdir =~ '\.'
248   let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
249  endif
250"  call Decho("tmpdir<".tmpdir.">")
251  call mkdir(tmpdir,"p")
252
253  " attempt to change to the indicated directory
254  if s:ChgDir(tmpdir,s:ERROR,"(zip#Write) cannot cd to temporary directory")
255   let &report= repkeep
256"   call Dret("zip#Write")
257   return
258  endif
259"  call Decho("current directory now: ".getcwd())
260
261  " place temporary files under .../_ZIPVIM_/
262  if isdirectory("_ZIPVIM_")
263   call s:Rmdir("_ZIPVIM_")
264  endif
265  call mkdir("_ZIPVIM_")
266  cd _ZIPVIM_
267"  call Decho("current directory now: ".getcwd())
268
269  if has("unix")
270   let zipfile = substitute(a:fname,'zipfile:\(.\{-}\)::[^\\].*$','\1','')
271   let fname   = substitute(a:fname,'zipfile:.\{-}::\([^\\].*\)$','\1','')
272  else
273   let zipfile = substitute(a:fname,'^.\{-}zipfile:\(.\{-}\)::[^\\].*$','\1','')
274   let fname   = substitute(a:fname,'^.\{-}zipfile:.\{-}::\([^\\].*\)$','\1','')
275  endif
276"  call Decho("zipfile<".zipfile.">")
277"  call Decho("fname  <".fname.">")
278
279  if fname =~ '/'
280   let dirpath = substitute(fname,'/[^/]\+$','','e')
281   if executable("cygpath")
282    let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e')
283   endif
284"   call Decho("mkdir(dirpath<".dirpath.">,p)")
285   call mkdir(dirpath,"p")
286  endif
287  if zipfile !~ '/'
288   let zipfile= curdir.'/'.zipfile
289  endif
290"  call Decho("zipfile<".zipfile."> fname<".fname.">")
291
292  exe "w! ".fnameescape(fname)
293  if executable("cygpath")
294   let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e')
295  endif
296
297  if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$'
298    let fname = substitute(fname, '[', '[[]', 'g')
299  endif
300
301"  call Decho(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
302  call system(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
303  if v:shell_error != 0
304   redraw!
305   echohl Error | echo "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname | echohl None
306"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
307
308  elseif s:zipfile_{winnr()} =~ '^\a\+://'
309   " support writing zipfiles across a network
310   let netzipfile= s:zipfile_{winnr()}
311"   call Decho("handle writing <".zipfile."> across network as <".netzipfile.">")
312   1split|enew
313   let binkeep= &binary
314   let eikeep = &ei
315   set binary ei=all
316   exe "e! ".fnameescape(zipfile)
317   call netrw#NetWrite(netzipfile)
318   let &ei     = eikeep
319   let &binary = binkeep
320   q!
321   unlet s:zipfile_{winnr()}
322  endif
323  
324  " cleanup and restore current directory
325  cd ..
326  call s:Rmdir("_ZIPVIM_")
327  call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
328  call s:Rmdir(tmpdir)
329  setlocal nomod
330
331  let &report= repkeep
332"  call Dret("zip#Write")
333endfun
334
335" ---------------------------------------------------------------------
336" s:Escape: {{{2
337fun! s:Escape(fname,isfilt)
338"  call Dfunc("QuoteFileDir(fname<".a:fname."> isfilt=".a:isfilt.")")
339  if exists("*shellescape")
340   if a:isfilt
341    let qnameq= shellescape(a:fname,1)
342   else
343    let qnameq= shellescape(a:fname)
344   endif
345  else
346   let qnameq= g:zip_shq.escape(a:fname,g:zip_shq).g:zip_shq
347  endif
348"  call Dret("QuoteFileDir <".qnameq.">")
349  return qnameq
350endfun
351
352" ---------------------------------------------------------------------
353" ChgDir: {{{2
354fun! s:ChgDir(newdir,errlvl,errmsg)
355"  call Dfunc("ChgDir(newdir<".a:newdir."> errlvl=".a:errlvl."  errmsg<".a:errmsg.">)")
356
357  try
358   exe "cd ".fnameescape(a:newdir)
359  catch /^Vim\%((\a\+)\)\=:E344/
360   redraw!
361   if a:errlvl == s:NOTE
362    echo "***note*** ".a:errmsg
363   elseif a:errlvl == s:WARNING
364    echohl WarningMsg | echo "***warning*** ".a:errmsg | echohl NONE
365   elseif a:errlvl == s:ERROR
366    echohl Error | echo "***error*** ".a:errmsg | echohl NONE
367   endif
368"   call inputsave()|call input("Press <cr> to continue")|call inputrestore()
369"   call Dret("ChgDir 1")
370   return 1
371  endtry
372
373"  call Dret("ChgDir 0")
374  return 0
375endfun
376
377" ---------------------------------------------------------------------
378" s:Rmdir: {{{2
379fun! s:Rmdir(fname)
380"  call Dfunc("Rmdir(fname<".a:fname.">)")
381  if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$'
382   call system("rmdir /S/Q ".s:Escape(a:fname,0))
383  else
384   call system("/bin/rm -rf ".s:Escape(a:fname,0))
385  endif
386"  call Dret("Rmdir")
387endfun
388
389" ------------------------------------------------------------------------
390" Modelines And Restoration: {{{1
391let &cpo= s:keepcpo
392unlet s:keepcpo
393" vim:ts=8 fdm=marker
394