blob: 4a53fc5f28656aa7bae886240e06a57702bde7e2 [file] [log] [blame]
Bram Moolenaar60a795a2005-09-16 21:55:43 +00001" zip.vim: Handles browsing zipfiles
Damien2cad9412024-07-24 20:07:00 +02002" AUTOLOAD PORTION
Christian Brabandtbc29ea62024-08-21 08:18:44 +02003" Date: 2024 Aug 21
Christian Brabandta336d8f2024-08-05 21:26:46 +02004" Version: 34
Christian Brabandtf9ca1392024-02-19 20:37:11 +01005" Maintainer: This runtime file is looking for a new maintainer.
6" Former Maintainer: Charles E Campbell
Christian Brabandt1c673422024-06-15 14:49:24 +02007" Last Change:
Damien2cad9412024-07-24 20:07:00 +02008" 2024 Jun 16 by Vim Project: handle whitespace on Windows properly (#14998)
9" 2024 Jul 23 by Vim Project: fix 'x' command
10" 2024 Jul 24 by Vim Project: use delete() function
Damienf0e9b722024-08-05 20:21:18 +020011" 2024 Jul 30 by Vim Project: fix opening remote zipfile
zeertzjqc5bdd662024-08-04 18:35:50 +020012" 2024 Aug 04 by Vim Project: escape '[' in name of file to be extracted
Damienf0e9b722024-08-05 20:21:18 +020013" 2024 Aug 05 by Vim Project: workaround for the FreeBSD's unzip
Christian Brabandta63f66e2024-08-05 20:47:34 +020014" 2024 Aug 05 by Vim Project: clean-up and make it work with shellslash on Windows
Christian Brabandt7790ea02024-08-20 22:41:52 +020015" 2024 Aug 18 by Vim Project: correctly handle special globbing chars
Christian Brabandtbc29ea62024-08-21 08:18:44 +020016" 2024 Aug 21 by Vim Project: simplify condition to detect MS-Windows
Bram Moolenaar9964e462007-05-05 17:54:07 +000017" License: Vim License (see vim's :help license)
Christian Brabandt1c673422024-06-15 14:49:24 +020018" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
19" Permission is hereby granted to use and distribute this code,
20" with or without modifications, provided that this copyright
21" notice is copied with it. Like anything else that's free,
22" zip.vim and zipPlugin.vim are provided *as is* and comes with
23" no warranty of any kind, either expressed or implied. By using
24" this plugin, you agree that in no event will the copyright
25" holder be liable for any damages resulting from the use
26" of this software.
Bram Moolenaar60a795a2005-09-16 21:55:43 +000027
28" ---------------------------------------------------------------------
Bram Moolenaar9964e462007-05-05 17:54:07 +000029" Load Once: {{{1
Bram Moolenaar00a927d2010-05-14 23:24:24 +020030if &cp || exists("g:loaded_zip")
Bram Moolenaar60a795a2005-09-16 21:55:43 +000031 finish
32endif
Christian Brabandta336d8f2024-08-05 21:26:46 +020033let g:loaded_zip= "v34"
Bram Moolenaar00a927d2010-05-14 23:24:24 +020034let s:keepcpo= &cpo
35set cpo&vim
Bram Moolenaar60a795a2005-09-16 21:55:43 +000036
Bram Moolenaardb552d602006-03-23 22:59:57 +000037let s:zipfile_escape = ' ?&;\'
Bram Moolenaar9964e462007-05-05 17:54:07 +000038let s:ERROR = 2
39let s:WARNING = 1
40let s:NOTE = 0
41
42" ---------------------------------------------------------------------
43" Global Values: {{{1
44if !exists("g:zip_shq")
Bram Moolenaar446cb832008-06-24 21:56:24 +000045 if &shq != ""
46 let g:zip_shq= &shq
47 elseif has("unix")
Bram Moolenaar9964e462007-05-05 17:54:07 +000048 let g:zip_shq= "'"
49 else
50 let g:zip_shq= '"'
51 endif
52endif
Bram Moolenaarccc18222007-05-10 18:25:20 +000053if !exists("g:zip_zipcmd")
54 let g:zip_zipcmd= "zip"
55endif
56if !exists("g:zip_unzipcmd")
57 let g:zip_unzipcmd= "unzip"
58endif
Bram Moolenaard0796902016-09-16 20:02:31 +020059if !exists("g:zip_extractcmd")
60 let g:zip_extractcmd= g:zip_unzipcmd
61endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +000062
Christian Brabandt8d529262024-08-06 18:35:00 +020063" ---------------------------------------------------------------------
64" required early
65" s:Mess: {{{2
66fun! s:Mess(group, msg)
67 redraw!
68 exe "echohl " . a:group
69 echomsg a:msg
70 echohl Normal
71endfun
72
Christian Brabandte2d9b0d2024-08-07 08:13:32 +020073if v:version < 901
74 " required for defer
75 call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 9.1 or later")
Christian Brabandt8d529262024-08-06 18:35:00 +020076 finish
77endif
Christian Brabandt7790ea02024-08-20 22:41:52 +020078" sanity checks
79if !executable(g:zip_unzipcmd)
80 call s:Mess('Error', "***error*** (zip#Browse) unzip not available on your system")
81 finish
82endif
D. Ben Knoblecd8a3ea2023-11-04 05:11:17 -040083if !dist#vim#IsSafeExecutable('zip', g:zip_unzipcmd)
Christian Brabandt8d529262024-08-06 18:35:00 +020084 call s:Mess('Error', "Warning: NOT executing " .. g:zip_unzipcmd .. " from current directory!")
Christian Brabandt816fbcc2023-08-31 23:52:30 +020085 finish
86endif
Anton Sharonov67c951d2023-09-05 21:03:27 +020087
Bram Moolenaar60a795a2005-09-16 21:55:43 +000088" ----------------
89" Functions: {{{1
90" ----------------
91
92" ---------------------------------------------------------------------
93" zip#Browse: {{{2
94fun! zip#Browse(zipfile)
Damienc4be0662024-07-30 19:14:35 +020095 " sanity check: ensure that the zipfile has "PK" as its first two letters
96 " (zip files have a leading PK as a "magic cookie")
97 if filereadable(a:zipfile) && readblob(a:zipfile, 0, 2) != 0z50.4B
98 exe "noswapfile noautocmd e " .. fnameescape(a:zipfile)
Bram Moolenaar94f76b72013-07-04 22:50:40 +020099 return
Bram Moolenaar94f76b72013-07-04 22:50:40 +0200100 endif
101
Christian Brabandt19636be2024-08-05 21:00:07 +0200102 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200103 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000104
105 " sanity checks
Bram Moolenaarccc18222007-05-10 18:25:20 +0000106 if !executable(g:zip_unzipcmd)
Christian Brabandt8d529262024-08-06 18:35:00 +0200107 call s:Mess('Error', "***error*** (zip#Browse) unzip not available on your system")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000108 return
109 endif
110 if !filereadable(a:zipfile)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000111 if a:zipfile !~# '^\a\+://'
Bram Moolenaar8024f932020-01-14 19:29:13 +0100112 " if it's an url, don't complain, let url-handlers such as vim do its thing
Christian Brabandt8d529262024-08-06 18:35:00 +0200113 call s:Mess('Error', "***error*** (zip#Browse) File not readable <".a:zipfile.">")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000114 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000115 return
116 endif
117 if &ma != 1
118 set ma
119 endif
Bram Moolenaarccc18222007-05-10 18:25:20 +0000120 let b:zipfile= a:zipfile
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000121
122 setlocal noswapfile
123 setlocal buftype=nofile
124 setlocal bufhidden=hide
125 setlocal nobuflisted
126 setlocal nowrap
Bram Moolenaar519cc552021-11-16 19:18:26 +0000127
128 " Oct 12, 2021: need to re-use Bram's syntax/tar.vim.
129 " Setting the filetype to zip doesn't do anything (currently),
130 " but it is perhaps less confusing to curious perusers who do
131 " a :echo &ft
132 setf zip
133 run! syntax/tar.vim
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000134
135 " give header
Bram Moolenaar251e1912011-06-19 05:09:16 +0200136 call append(0, ['" zip.vim version '.g:loaded_zip,
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100137 \ '" Browsing zipfile '.a:zipfile,
138 \ '" Select a file with cursor and press ENTER'])
Bram Moolenaar251e1912011-06-19 05:09:16 +0200139 keepj $
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000140
Damienf0e9b722024-08-05 20:21:18 +0200141 exe $"keepj sil r! {g:zip_unzipcmd} -Z1 -- {s:Escape(a:zipfile, 1)}"
Bram Moolenaard68071d2006-05-02 22:08:30 +0000142 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200143 call s:Mess('WarningMsg', "***warning*** (zip#Browse) ".fnameescape(a:zipfile)." is not a zip file")
Bram Moolenaar251e1912011-06-19 05:09:16 +0200144 keepj sil! %d
Bram Moolenaard68071d2006-05-02 22:08:30 +0000145 let eikeep= &ei
146 set ei=BufReadCmd,FileReadCmd
Bram Moolenaar251e1912011-06-19 05:09:16 +0200147 exe "keepj r ".fnameescape(a:zipfile)
Bram Moolenaard68071d2006-05-02 22:08:30 +0000148 let &ei= eikeep
Bram Moolenaar251e1912011-06-19 05:09:16 +0200149 keepj 1d
Bram Moolenaard68071d2006-05-02 22:08:30 +0000150 return
151 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000152
Bram Moolenaard0796902016-09-16 20:02:31 +0200153 " Maps associated with zip plugin
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000154 setlocal noma nomod ro
Bram Moolenaar29634562020-01-09 21:46:04 +0100155 noremap <silent> <buffer> <cr> :call <SID>ZipBrowseSelect()<cr>
156 noremap <silent> <buffer> x :call zip#Extract()<cr>
157 if &mouse != ""
158 noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>ZipBrowseSelect()<cr>
159 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000160
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000161endfun
162
163" ---------------------------------------------------------------------
164" ZipBrowseSelect: {{{2
165fun! s:ZipBrowseSelect()
Christian Brabandt19636be2024-08-05 21:00:07 +0200166 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200167 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000168 let fname= getline(".")
Bram Moolenaar71badf92023-04-22 22:40:14 +0100169 if !exists("b:zipfile")
Bram Moolenaar71badf92023-04-22 22:40:14 +0100170 return
171 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000172
173 " sanity check
174 if fname =~ '^"'
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000175 return
176 endif
177 if fname =~ '/$'
Christian Brabandt8d529262024-08-06 18:35:00 +0200178 call s:Mess('Error', "***error*** (zip#Browse) Please specify a file, not a directory")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000179 return
180 endif
181
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000182 " get zipfile to the new-window
Bram Moolenaarccc18222007-05-10 18:25:20 +0000183 let zipfile = b:zipfile
Bram Moolenaar29634562020-01-09 21:46:04 +0100184 let curfile = expand("%")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000185
Bram Moolenaar29634562020-01-09 21:46:04 +0100186 noswapfile new
Bram Moolenaar446cb832008-06-24 21:56:24 +0000187 if !exists("g:zip_nomax") || g:zip_nomax == 0
188 wincmd _
189 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000190 let s:zipfile_{winnr()}= curfile
Bram Moolenaar519cc552021-11-16 19:18:26 +0000191 exe "noswapfile e ".fnameescape("zipfile://".zipfile.'::'.fname)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000192 filetype detect
193
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000194endfun
195
196" ---------------------------------------------------------------------
197" zip#Read: {{{2
198fun! zip#Read(fname,mode)
Christian Brabandt19636be2024-08-05 21:00:07 +0200199 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200200 defer s:RestoreOpts(dict)
Bram Moolenaar36c31f72005-11-28 23:01:53 +0000201
Bram Moolenaard68071d2006-05-02 22:08:30 +0000202 if has("unix")
Bram Moolenaar519cc552021-11-16 19:18:26 +0000203 let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
204 let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000205 else
Bram Moolenaar519cc552021-11-16 19:18:26 +0000206 let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
207 let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000208 endif
Christian Brabandt7790ea02024-08-20 22:41:52 +0200209 let fname = fname->substitute('[', '[[]', 'g')->escape('?*\\')
Bram Moolenaard0796902016-09-16 20:02:31 +0200210 " sanity check
211 if !executable(substitute(g:zip_unzipcmd,'\s\+.*$','',''))
Christian Brabandt8d529262024-08-06 18:35:00 +0200212 call s:Mess('Error', "***error*** (zip#Read) sorry, your system doesn't appear to have the ".g:zip_unzipcmd." program")
Bram Moolenaard0796902016-09-16 20:02:31 +0200213 return
214 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000215
Bram Moolenaarff034192013-04-24 18:51:19 +0200216 " the following code does much the same thing as
zeertzjqc5bdd662024-08-04 18:35:50 +0200217 " exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
Bram Moolenaar519cc552021-11-16 19:18:26 +0000218 " but allows zipfile://... entries in quickfix lists
Bram Moolenaarff034192013-04-24 18:51:19 +0200219 let temp = tempname()
220 let fn = expand('%:p')
Damienf0e9b722024-08-05 20:21:18 +0200221 exe "sil !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1).' > '.temp
Bram Moolenaarff034192013-04-24 18:51:19 +0200222 sil exe 'keepalt file '.temp
223 sil keepj e!
224 sil exe 'keepalt file '.fnameescape(fn)
225 call delete(temp)
226
Bram Moolenaar251e1912011-06-19 05:09:16 +0200227 filetype detect
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000228
229 " cleanup
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000230 set nomod
231
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000232endfun
233
234" ---------------------------------------------------------------------
235" zip#Write: {{{2
236fun! zip#Write(fname)
Christian Brabandt19636be2024-08-05 21:00:07 +0200237 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200238 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000239
240 " sanity checks
Bram Moolenaard0796902016-09-16 20:02:31 +0200241 if !executable(substitute(g:zip_zipcmd,'\s\+.*$','',''))
Christian Brabandt8d529262024-08-06 18:35:00 +0200242 call s:Mess('Error', "***error*** (zip#Write) sorry, your system doesn't appear to have the ".g:zip_zipcmd." program")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000243 return
244 endif
245 if !exists("*mkdir")
Christian Brabandt8d529262024-08-06 18:35:00 +0200246 call s:Mess('Error', "***error*** (zip#Write) sorry, mkdir() doesn't work on your system")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000247 return
248 endif
249
250 let curdir= getcwd()
251 let tmpdir= tempname()
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000252 if tmpdir =~ '\.'
253 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
254 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000255 call mkdir(tmpdir,"p")
256
257 " attempt to change to the indicated directory
Bram Moolenaar9964e462007-05-05 17:54:07 +0000258 if s:ChgDir(tmpdir,s:ERROR,"(zip#Write) cannot cd to temporary directory")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000259 return
Bram Moolenaar9964e462007-05-05 17:54:07 +0000260 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000261
262 " place temporary files under .../_ZIPVIM_/
263 if isdirectory("_ZIPVIM_")
Damien2cad9412024-07-24 20:07:00 +0200264 call delete("_ZIPVIM_", "rf")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000265 endif
266 call mkdir("_ZIPVIM_")
267 cd _ZIPVIM_
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000268
Bram Moolenaard68071d2006-05-02 22:08:30 +0000269 if has("unix")
Bram Moolenaar519cc552021-11-16 19:18:26 +0000270 let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
271 let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000272 else
Bram Moolenaar519cc552021-11-16 19:18:26 +0000273 let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
274 let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000275 endif
Bram Moolenaarc7486e02005-12-29 22:48:26 +0000276
277 if fname =~ '/'
278 let dirpath = substitute(fname,'/[^/]\+$','','e')
Bram Moolenaarff034192013-04-24 18:51:19 +0200279 if has("win32unix") && executable("cygpath")
Bram Moolenaarc236c162008-07-13 17:41:49 +0000280 let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e')
Bram Moolenaarc7486e02005-12-29 22:48:26 +0000281 endif
282 call mkdir(dirpath,"p")
283 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000284 if zipfile !~ '/'
285 let zipfile= curdir.'/'.zipfile
286 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000287
Bram Moolenaarc236c162008-07-13 17:41:49 +0000288 exe "w! ".fnameescape(fname)
Bram Moolenaarff034192013-04-24 18:51:19 +0200289 if has("win32unix") && executable("cygpath")
Bram Moolenaarc236c162008-07-13 17:41:49 +0000290 let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e')
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000291 endif
292
Bram Moolenaar9964e462007-05-05 17:54:07 +0000293 if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$'
294 let fname = substitute(fname, '[', '[[]', 'g')
295 endif
296
Bram Moolenaare37d50a2008-08-06 17:06:04 +0000297 call system(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000298 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200299 call s:Mess('Error', "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000300
301 elseif s:zipfile_{winnr()} =~ '^\a\+://'
302 " support writing zipfiles across a network
303 let netzipfile= s:zipfile_{winnr()}
Bram Moolenaara5792f52005-11-23 21:25:05 +0000304 1split|enew
305 let binkeep= &binary
306 let eikeep = &ei
307 set binary ei=all
Bram Moolenaar29634562020-01-09 21:46:04 +0100308 exe "noswapfile e! ".fnameescape(zipfile)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000309 call netrw#NetWrite(netzipfile)
310 let &ei = eikeep
311 let &binary = binkeep
312 q!
313 unlet s:zipfile_{winnr()}
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000314 endif
Damien2cad9412024-07-24 20:07:00 +0200315
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000316 " cleanup and restore current directory
317 cd ..
Damien2cad9412024-07-24 20:07:00 +0200318 call delete("_ZIPVIM_", "rf")
Bram Moolenaar9964e462007-05-05 17:54:07 +0000319 call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
Damien2cad9412024-07-24 20:07:00 +0200320 call delete(tmpdir, "rf")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000321 setlocal nomod
322
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000323endfun
324
325" ---------------------------------------------------------------------
Bram Moolenaard0796902016-09-16 20:02:31 +0200326" zip#Extract: extract a file from a zip archive {{{2
327fun! zip#Extract()
Bram Moolenaard0796902016-09-16 20:02:31 +0200328
Christian Brabandt19636be2024-08-05 21:00:07 +0200329 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200330 defer s:RestoreOpts(dict)
Bram Moolenaard0796902016-09-16 20:02:31 +0200331 let fname= getline(".")
Bram Moolenaard0796902016-09-16 20:02:31 +0200332
333 " sanity check
334 if fname =~ '^"'
Bram Moolenaard0796902016-09-16 20:02:31 +0200335 return
336 endif
337 if fname =~ '/$'
Christian Brabandt8d529262024-08-06 18:35:00 +0200338 call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
Bram Moolenaard0796902016-09-16 20:02:31 +0200339 return
340 endif
Christian Brabandt7790ea02024-08-20 22:41:52 +0200341 if filereadable(fname)
342 call s:Mess('Error', "***error*** (zip#Extract) <" .. fname .."> already exists in directory, not overwriting!")
343 return
344 endif
345 let target = fname->substitute('\[', '[[]', 'g')
Christian Brabandtbc29ea62024-08-21 08:18:44 +0200346 if &shell =~ 'cmd' && has("win32")
Christian Brabandt7790ea02024-08-20 22:41:52 +0200347 let target = target
348 \ ->substitute('[?*]', '[&]', 'g')
349 \ ->substitute('[\\]', '?', 'g')
350 \ ->shellescape()
351 " there cannot be a file name with '\' in its name, unzip replaces it by _
352 let fname = fname->substitute('[\\?*]', '_', 'g')
353 else
354 let target = target->escape('*?\\')->shellescape()
355 endif
Bram Moolenaard0796902016-09-16 20:02:31 +0200356
357 " extract the file mentioned under the cursor
Christian Brabandt7790ea02024-08-20 22:41:52 +0200358 call system($"{g:zip_extractcmd} -o {shellescape(b:zipfile)} {target}")
Bram Moolenaard0796902016-09-16 20:02:31 +0200359 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200360 call s:Mess('Error', "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!")
Bram Moolenaard0796902016-09-16 20:02:31 +0200361 elseif !filereadable(fname)
Christian Brabandt8d529262024-08-06 18:35:00 +0200362 call s:Mess('Error', "***error*** attempted to extract ".fname." but it doesn't appear to be present!")
Bram Moolenaard0796902016-09-16 20:02:31 +0200363 else
Christian Brabandt120c0dd2024-08-05 20:51:47 +0200364 echomsg "***note*** successfully extracted ".fname
Bram Moolenaard0796902016-09-16 20:02:31 +0200365 endif
366
Bram Moolenaard0796902016-09-16 20:02:31 +0200367endfun
368
369" ---------------------------------------------------------------------
Bram Moolenaarc236c162008-07-13 17:41:49 +0000370" s:Escape: {{{2
371fun! s:Escape(fname,isfilt)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000372 if exists("*shellescape")
373 if a:isfilt
374 let qnameq= shellescape(a:fname,1)
375 else
376 let qnameq= shellescape(a:fname)
377 endif
Bram Moolenaar446cb832008-06-24 21:56:24 +0000378 else
379 let qnameq= g:zip_shq.escape(a:fname,g:zip_shq).g:zip_shq
380 endif
Bram Moolenaar446cb832008-06-24 21:56:24 +0000381 return qnameq
Bram Moolenaar9964e462007-05-05 17:54:07 +0000382endfun
383
384" ---------------------------------------------------------------------
Christian Brabandt19636be2024-08-05 21:00:07 +0200385" s:ChgDir: {{{2
Bram Moolenaar9964e462007-05-05 17:54:07 +0000386fun! s:ChgDir(newdir,errlvl,errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000387 try
Bram Moolenaare37d50a2008-08-06 17:06:04 +0000388 exe "cd ".fnameescape(a:newdir)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000389 catch /^Vim\%((\a\+)\)\=:E344/
390 redraw!
391 if a:errlvl == s:NOTE
Christian Brabandt120c0dd2024-08-05 20:51:47 +0200392 echomsg "***note*** ".a:errmsg
Bram Moolenaar9964e462007-05-05 17:54:07 +0000393 elseif a:errlvl == s:WARNING
Christian Brabandt8d529262024-08-06 18:35:00 +0200394 call s:Mess("WarningMsg", "***warning*** ".a:errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000395 elseif a:errlvl == s:ERROR
Christian Brabandt8d529262024-08-06 18:35:00 +0200396 call s:Mess("Error", "***error*** ".a:errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000397 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000398 return 1
399 endtry
400
Bram Moolenaar9964e462007-05-05 17:54:07 +0000401 return 0
402endfun
403
Christian Brabandt19636be2024-08-05 21:00:07 +0200404" ---------------------------------------------------------------------
405" s:SetSaneOpts: {{{2
406fun! s:SetSaneOpts()
407 let dict = {}
408 let dict.report = &report
409 let dict.shellslash = &shellslash
410
411 let &report = 10
412 let &shellslash = 0
413
414 return dict
415endfun
416
417" ---------------------------------------------------------------------
418" s:RestoreOpts: {{{2
419fun! s:RestoreOpts(dict)
420 for [key, val] in items(a:dict)
421 exe $"let &{key} = {val}"
422 endfor
423endfun
424
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000425" ------------------------------------------------------------------------
426" Modelines And Restoration: {{{1
427let &cpo= s:keepcpo
428unlet s:keepcpo
Bram Moolenaarccc18222007-05-10 18:25:20 +0000429" vim:ts=8 fdm=marker