xref: /vim-8.2.3635/runtime/autoload/zip.vim (revision cf2d8dee)
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