blob: a7a7e579a2f319dafc2feeded8192f3e8769f3c1 [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 Brabandt7790ea02024-08-20 22:41:52 +02003" Date: Aug 18, 2024
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
Bram Moolenaar9964e462007-05-05 17:54:07 +000016" License: Vim License (see vim's :help license)
Christian Brabandt1c673422024-06-15 14:49:24 +020017" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
18" Permission is hereby granted to use and distribute this code,
19" with or without modifications, provided that this copyright
20" notice is copied with it. Like anything else that's free,
21" zip.vim and zipPlugin.vim are provided *as is* and comes with
22" no warranty of any kind, either expressed or implied. By using
23" this plugin, you agree that in no event will the copyright
24" holder be liable for any damages resulting from the use
25" of this software.
Bram Moolenaar60a795a2005-09-16 21:55:43 +000026
27" ---------------------------------------------------------------------
Bram Moolenaar9964e462007-05-05 17:54:07 +000028" Load Once: {{{1
Bram Moolenaar00a927d2010-05-14 23:24:24 +020029if &cp || exists("g:loaded_zip")
Bram Moolenaar60a795a2005-09-16 21:55:43 +000030 finish
31endif
Christian Brabandta336d8f2024-08-05 21:26:46 +020032let g:loaded_zip= "v34"
Bram Moolenaar00a927d2010-05-14 23:24:24 +020033let s:keepcpo= &cpo
34set cpo&vim
Bram Moolenaar60a795a2005-09-16 21:55:43 +000035
Bram Moolenaardb552d602006-03-23 22:59:57 +000036let s:zipfile_escape = ' ?&;\'
Bram Moolenaar9964e462007-05-05 17:54:07 +000037let s:ERROR = 2
38let s:WARNING = 1
39let s:NOTE = 0
40
41" ---------------------------------------------------------------------
42" Global Values: {{{1
43if !exists("g:zip_shq")
Bram Moolenaar446cb832008-06-24 21:56:24 +000044 if &shq != ""
45 let g:zip_shq= &shq
46 elseif has("unix")
Bram Moolenaar9964e462007-05-05 17:54:07 +000047 let g:zip_shq= "'"
48 else
49 let g:zip_shq= '"'
50 endif
51endif
Bram Moolenaarccc18222007-05-10 18:25:20 +000052if !exists("g:zip_zipcmd")
53 let g:zip_zipcmd= "zip"
54endif
55if !exists("g:zip_unzipcmd")
56 let g:zip_unzipcmd= "unzip"
57endif
Bram Moolenaard0796902016-09-16 20:02:31 +020058if !exists("g:zip_extractcmd")
59 let g:zip_extractcmd= g:zip_unzipcmd
60endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +000061
Christian Brabandt8d529262024-08-06 18:35:00 +020062" ---------------------------------------------------------------------
63" required early
64" s:Mess: {{{2
65fun! s:Mess(group, msg)
66 redraw!
67 exe "echohl " . a:group
68 echomsg a:msg
69 echohl Normal
70endfun
71
Christian Brabandte2d9b0d2024-08-07 08:13:32 +020072if v:version < 901
73 " required for defer
74 call s:Mess('WarningMsg', "***warning*** this version of zip needs vim 9.1 or later")
Christian Brabandt8d529262024-08-06 18:35:00 +020075 finish
76endif
Christian Brabandt7790ea02024-08-20 22:41:52 +020077" sanity checks
78if !executable(g:zip_unzipcmd)
79 call s:Mess('Error', "***error*** (zip#Browse) unzip not available on your system")
80 finish
81endif
D. Ben Knoblecd8a3ea2023-11-04 05:11:17 -040082if !dist#vim#IsSafeExecutable('zip', g:zip_unzipcmd)
Christian Brabandt8d529262024-08-06 18:35:00 +020083 call s:Mess('Error', "Warning: NOT executing " .. g:zip_unzipcmd .. " from current directory!")
Christian Brabandt816fbcc2023-08-31 23:52:30 +020084 finish
85endif
Anton Sharonov67c951d2023-09-05 21:03:27 +020086
Bram Moolenaar60a795a2005-09-16 21:55:43 +000087" ----------------
88" Functions: {{{1
89" ----------------
90
91" ---------------------------------------------------------------------
92" zip#Browse: {{{2
93fun! zip#Browse(zipfile)
Damienc4be0662024-07-30 19:14:35 +020094 " sanity check: ensure that the zipfile has "PK" as its first two letters
95 " (zip files have a leading PK as a "magic cookie")
96 if filereadable(a:zipfile) && readblob(a:zipfile, 0, 2) != 0z50.4B
97 exe "noswapfile noautocmd e " .. fnameescape(a:zipfile)
Bram Moolenaar94f76b72013-07-04 22:50:40 +020098 return
Bram Moolenaar94f76b72013-07-04 22:50:40 +020099 endif
100
Christian Brabandt19636be2024-08-05 21:00:07 +0200101 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200102 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000103
104 " sanity checks
Bram Moolenaarccc18222007-05-10 18:25:20 +0000105 if !executable(g:zip_unzipcmd)
Christian Brabandt8d529262024-08-06 18:35:00 +0200106 call s:Mess('Error', "***error*** (zip#Browse) unzip not available on your system")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000107 return
108 endif
109 if !filereadable(a:zipfile)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000110 if a:zipfile !~# '^\a\+://'
Bram Moolenaar8024f932020-01-14 19:29:13 +0100111 " if it's an url, don't complain, let url-handlers such as vim do its thing
Christian Brabandt8d529262024-08-06 18:35:00 +0200112 call s:Mess('Error', "***error*** (zip#Browse) File not readable <".a:zipfile.">")
Bram Moolenaara5792f52005-11-23 21:25:05 +0000113 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000114 return
115 endif
116 if &ma != 1
117 set ma
118 endif
Bram Moolenaarccc18222007-05-10 18:25:20 +0000119 let b:zipfile= a:zipfile
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000120
121 setlocal noswapfile
122 setlocal buftype=nofile
123 setlocal bufhidden=hide
124 setlocal nobuflisted
125 setlocal nowrap
Bram Moolenaar519cc552021-11-16 19:18:26 +0000126
127 " Oct 12, 2021: need to re-use Bram's syntax/tar.vim.
128 " Setting the filetype to zip doesn't do anything (currently),
129 " but it is perhaps less confusing to curious perusers who do
130 " a :echo &ft
131 setf zip
132 run! syntax/tar.vim
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000133
134 " give header
Bram Moolenaar251e1912011-06-19 05:09:16 +0200135 call append(0, ['" zip.vim version '.g:loaded_zip,
Bram Moolenaar6be7f872012-01-20 21:08:56 +0100136 \ '" Browsing zipfile '.a:zipfile,
137 \ '" Select a file with cursor and press ENTER'])
Bram Moolenaar251e1912011-06-19 05:09:16 +0200138 keepj $
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000139
Damienf0e9b722024-08-05 20:21:18 +0200140 exe $"keepj sil r! {g:zip_unzipcmd} -Z1 -- {s:Escape(a:zipfile, 1)}"
Bram Moolenaard68071d2006-05-02 22:08:30 +0000141 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200142 call s:Mess('WarningMsg', "***warning*** (zip#Browse) ".fnameescape(a:zipfile)." is not a zip file")
Bram Moolenaar251e1912011-06-19 05:09:16 +0200143 keepj sil! %d
Bram Moolenaard68071d2006-05-02 22:08:30 +0000144 let eikeep= &ei
145 set ei=BufReadCmd,FileReadCmd
Bram Moolenaar251e1912011-06-19 05:09:16 +0200146 exe "keepj r ".fnameescape(a:zipfile)
Bram Moolenaard68071d2006-05-02 22:08:30 +0000147 let &ei= eikeep
Bram Moolenaar251e1912011-06-19 05:09:16 +0200148 keepj 1d
Bram Moolenaard68071d2006-05-02 22:08:30 +0000149 return
150 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000151
Bram Moolenaard0796902016-09-16 20:02:31 +0200152 " Maps associated with zip plugin
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000153 setlocal noma nomod ro
Bram Moolenaar29634562020-01-09 21:46:04 +0100154 noremap <silent> <buffer> <cr> :call <SID>ZipBrowseSelect()<cr>
155 noremap <silent> <buffer> x :call zip#Extract()<cr>
156 if &mouse != ""
157 noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>ZipBrowseSelect()<cr>
158 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000159
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000160endfun
161
162" ---------------------------------------------------------------------
163" ZipBrowseSelect: {{{2
164fun! s:ZipBrowseSelect()
Christian Brabandt19636be2024-08-05 21:00:07 +0200165 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200166 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000167 let fname= getline(".")
Bram Moolenaar71badf92023-04-22 22:40:14 +0100168 if !exists("b:zipfile")
Bram Moolenaar71badf92023-04-22 22:40:14 +0100169 return
170 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000171
172 " sanity check
173 if fname =~ '^"'
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000174 return
175 endif
176 if fname =~ '/$'
Christian Brabandt8d529262024-08-06 18:35:00 +0200177 call s:Mess('Error', "***error*** (zip#Browse) Please specify a file, not a directory")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000178 return
179 endif
180
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000181 " get zipfile to the new-window
Bram Moolenaarccc18222007-05-10 18:25:20 +0000182 let zipfile = b:zipfile
Bram Moolenaar29634562020-01-09 21:46:04 +0100183 let curfile = expand("%")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000184
Bram Moolenaar29634562020-01-09 21:46:04 +0100185 noswapfile new
Bram Moolenaar446cb832008-06-24 21:56:24 +0000186 if !exists("g:zip_nomax") || g:zip_nomax == 0
187 wincmd _
188 endif
Bram Moolenaara5792f52005-11-23 21:25:05 +0000189 let s:zipfile_{winnr()}= curfile
Bram Moolenaar519cc552021-11-16 19:18:26 +0000190 exe "noswapfile e ".fnameescape("zipfile://".zipfile.'::'.fname)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000191 filetype detect
192
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000193endfun
194
195" ---------------------------------------------------------------------
196" zip#Read: {{{2
197fun! zip#Read(fname,mode)
Christian Brabandt19636be2024-08-05 21:00:07 +0200198 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200199 defer s:RestoreOpts(dict)
Bram Moolenaar36c31f72005-11-28 23:01:53 +0000200
Bram Moolenaard68071d2006-05-02 22:08:30 +0000201 if has("unix")
Bram Moolenaar519cc552021-11-16 19:18:26 +0000202 let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
203 let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000204 else
Bram Moolenaar519cc552021-11-16 19:18:26 +0000205 let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
206 let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000207 endif
Christian Brabandt7790ea02024-08-20 22:41:52 +0200208 let fname = fname->substitute('[', '[[]', 'g')->escape('?*\\')
Bram Moolenaard0796902016-09-16 20:02:31 +0200209 " sanity check
210 if !executable(substitute(g:zip_unzipcmd,'\s\+.*$','',''))
Christian Brabandt8d529262024-08-06 18:35:00 +0200211 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 +0200212 return
213 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000214
Bram Moolenaarff034192013-04-24 18:51:19 +0200215 " the following code does much the same thing as
zeertzjqc5bdd662024-08-04 18:35:50 +0200216 " exe "keepj sil! r! ".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1)
Bram Moolenaar519cc552021-11-16 19:18:26 +0000217 " but allows zipfile://... entries in quickfix lists
Bram Moolenaarff034192013-04-24 18:51:19 +0200218 let temp = tempname()
219 let fn = expand('%:p')
Damienf0e9b722024-08-05 20:21:18 +0200220 exe "sil !".g:zip_unzipcmd." -p -- ".s:Escape(zipfile,1)." ".s:Escape(fname,1).' > '.temp
Bram Moolenaarff034192013-04-24 18:51:19 +0200221 sil exe 'keepalt file '.temp
222 sil keepj e!
223 sil exe 'keepalt file '.fnameescape(fn)
224 call delete(temp)
225
Bram Moolenaar251e1912011-06-19 05:09:16 +0200226 filetype detect
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000227
228 " cleanup
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000229 set nomod
230
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000231endfun
232
233" ---------------------------------------------------------------------
234" zip#Write: {{{2
235fun! zip#Write(fname)
Christian Brabandt19636be2024-08-05 21:00:07 +0200236 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200237 defer s:RestoreOpts(dict)
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000238
239 " sanity checks
Bram Moolenaard0796902016-09-16 20:02:31 +0200240 if !executable(substitute(g:zip_zipcmd,'\s\+.*$','',''))
Christian Brabandt8d529262024-08-06 18:35:00 +0200241 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 +0000242 return
243 endif
244 if !exists("*mkdir")
Christian Brabandt8d529262024-08-06 18:35:00 +0200245 call s:Mess('Error', "***error*** (zip#Write) sorry, mkdir() doesn't work on your system")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000246 return
247 endif
248
249 let curdir= getcwd()
250 let tmpdir= tempname()
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000251 if tmpdir =~ '\.'
252 let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
253 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000254 call mkdir(tmpdir,"p")
255
256 " attempt to change to the indicated directory
Bram Moolenaar9964e462007-05-05 17:54:07 +0000257 if s:ChgDir(tmpdir,s:ERROR,"(zip#Write) cannot cd to temporary directory")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000258 return
Bram Moolenaar9964e462007-05-05 17:54:07 +0000259 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000260
261 " place temporary files under .../_ZIPVIM_/
262 if isdirectory("_ZIPVIM_")
Damien2cad9412024-07-24 20:07:00 +0200263 call delete("_ZIPVIM_", "rf")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000264 endif
265 call mkdir("_ZIPVIM_")
266 cd _ZIPVIM_
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000267
Bram Moolenaard68071d2006-05-02 22:08:30 +0000268 if has("unix")
Bram Moolenaar519cc552021-11-16 19:18:26 +0000269 let zipfile = substitute(a:fname,'zipfile://\(.\{-}\)::[^\\].*$','\1','')
270 let fname = substitute(a:fname,'zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000271 else
Bram Moolenaar519cc552021-11-16 19:18:26 +0000272 let zipfile = substitute(a:fname,'^.\{-}zipfile://\(.\{-}\)::[^\\].*$','\1','')
273 let fname = substitute(a:fname,'^.\{-}zipfile://.\{-}::\([^\\].*\)$','\1','')
Bram Moolenaard68071d2006-05-02 22:08:30 +0000274 endif
Bram Moolenaarc7486e02005-12-29 22:48:26 +0000275
276 if fname =~ '/'
277 let dirpath = substitute(fname,'/[^/]\+$','','e')
Bram Moolenaarff034192013-04-24 18:51:19 +0200278 if has("win32unix") && executable("cygpath")
Bram Moolenaarc236c162008-07-13 17:41:49 +0000279 let dirpath = substitute(system("cygpath ".s:Escape(dirpath,0)),'\n','','e')
Bram Moolenaarc7486e02005-12-29 22:48:26 +0000280 endif
281 call mkdir(dirpath,"p")
282 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000283 if zipfile !~ '/'
284 let zipfile= curdir.'/'.zipfile
285 endif
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000286
Bram Moolenaarc236c162008-07-13 17:41:49 +0000287 exe "w! ".fnameescape(fname)
Bram Moolenaarff034192013-04-24 18:51:19 +0200288 if has("win32unix") && executable("cygpath")
Bram Moolenaarc236c162008-07-13 17:41:49 +0000289 let zipfile = substitute(system("cygpath ".s:Escape(zipfile,0)),'\n','','e')
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000290 endif
291
Bram Moolenaar9964e462007-05-05 17:54:07 +0000292 if (has("win32") || has("win95") || has("win64") || has("win16")) && &shell !~? 'sh$'
293 let fname = substitute(fname, '[', '[[]', 'g')
294 endif
295
Bram Moolenaare37d50a2008-08-06 17:06:04 +0000296 call system(g:zip_zipcmd." -u ".s:Escape(fnamemodify(zipfile,":p"),0)." ".s:Escape(fname,0))
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000297 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200298 call s:Mess('Error', "***error*** (zip#Write) sorry, unable to update ".zipfile." with ".fname)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000299
300 elseif s:zipfile_{winnr()} =~ '^\a\+://'
301 " support writing zipfiles across a network
302 let netzipfile= s:zipfile_{winnr()}
Bram Moolenaara5792f52005-11-23 21:25:05 +0000303 1split|enew
304 let binkeep= &binary
305 let eikeep = &ei
306 set binary ei=all
Bram Moolenaar29634562020-01-09 21:46:04 +0100307 exe "noswapfile e! ".fnameescape(zipfile)
Bram Moolenaara5792f52005-11-23 21:25:05 +0000308 call netrw#NetWrite(netzipfile)
309 let &ei = eikeep
310 let &binary = binkeep
311 q!
312 unlet s:zipfile_{winnr()}
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000313 endif
Damien2cad9412024-07-24 20:07:00 +0200314
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000315 " cleanup and restore current directory
316 cd ..
Damien2cad9412024-07-24 20:07:00 +0200317 call delete("_ZIPVIM_", "rf")
Bram Moolenaar9964e462007-05-05 17:54:07 +0000318 call s:ChgDir(curdir,s:WARNING,"(zip#Write) unable to return to ".curdir."!")
Damien2cad9412024-07-24 20:07:00 +0200319 call delete(tmpdir, "rf")
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000320 setlocal nomod
321
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000322endfun
323
324" ---------------------------------------------------------------------
Bram Moolenaard0796902016-09-16 20:02:31 +0200325" zip#Extract: extract a file from a zip archive {{{2
326fun! zip#Extract()
Bram Moolenaard0796902016-09-16 20:02:31 +0200327
Christian Brabandt19636be2024-08-05 21:00:07 +0200328 let dict = s:SetSaneOpts()
Christian Brabandtafea6b92024-08-06 18:50:59 +0200329 defer s:RestoreOpts(dict)
Bram Moolenaard0796902016-09-16 20:02:31 +0200330 let fname= getline(".")
Bram Moolenaard0796902016-09-16 20:02:31 +0200331
332 " sanity check
333 if fname =~ '^"'
Bram Moolenaard0796902016-09-16 20:02:31 +0200334 return
335 endif
336 if fname =~ '/$'
Christian Brabandt8d529262024-08-06 18:35:00 +0200337 call s:Mess('Error', "***error*** (zip#Extract) Please specify a file, not a directory")
Bram Moolenaard0796902016-09-16 20:02:31 +0200338 return
339 endif
Christian Brabandt7790ea02024-08-20 22:41:52 +0200340 if filereadable(fname)
341 call s:Mess('Error', "***error*** (zip#Extract) <" .. fname .."> already exists in directory, not overwriting!")
342 return
343 endif
344 let target = fname->substitute('\[', '[[]', 'g')
345 if &shell =~ 'cmd' && (has("win32") || has("win64"))
346 let target = target
347 \ ->substitute('[?*]', '[&]', 'g')
348 \ ->substitute('[\\]', '?', 'g')
349 \ ->shellescape()
350 " there cannot be a file name with '\' in its name, unzip replaces it by _
351 let fname = fname->substitute('[\\?*]', '_', 'g')
352 else
353 let target = target->escape('*?\\')->shellescape()
354 endif
Bram Moolenaard0796902016-09-16 20:02:31 +0200355
356 " extract the file mentioned under the cursor
Christian Brabandt7790ea02024-08-20 22:41:52 +0200357 call system($"{g:zip_extractcmd} -o {shellescape(b:zipfile)} {target}")
Bram Moolenaard0796902016-09-16 20:02:31 +0200358 if v:shell_error != 0
Christian Brabandt8d529262024-08-06 18:35:00 +0200359 call s:Mess('Error', "***error*** ".g:zip_extractcmd." ".b:zipfile." ".fname.": failed!")
Bram Moolenaard0796902016-09-16 20:02:31 +0200360 elseif !filereadable(fname)
Christian Brabandt8d529262024-08-06 18:35:00 +0200361 call s:Mess('Error', "***error*** attempted to extract ".fname." but it doesn't appear to be present!")
Bram Moolenaard0796902016-09-16 20:02:31 +0200362 else
Christian Brabandt120c0dd2024-08-05 20:51:47 +0200363 echomsg "***note*** successfully extracted ".fname
Bram Moolenaard0796902016-09-16 20:02:31 +0200364 endif
365
Bram Moolenaard0796902016-09-16 20:02:31 +0200366endfun
367
368" ---------------------------------------------------------------------
Bram Moolenaarc236c162008-07-13 17:41:49 +0000369" s:Escape: {{{2
370fun! s:Escape(fname,isfilt)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000371 if exists("*shellescape")
372 if a:isfilt
373 let qnameq= shellescape(a:fname,1)
374 else
375 let qnameq= shellescape(a:fname)
376 endif
Bram Moolenaar446cb832008-06-24 21:56:24 +0000377 else
378 let qnameq= g:zip_shq.escape(a:fname,g:zip_shq).g:zip_shq
379 endif
Bram Moolenaar446cb832008-06-24 21:56:24 +0000380 return qnameq
Bram Moolenaar9964e462007-05-05 17:54:07 +0000381endfun
382
383" ---------------------------------------------------------------------
Christian Brabandt19636be2024-08-05 21:00:07 +0200384" s:ChgDir: {{{2
Bram Moolenaar9964e462007-05-05 17:54:07 +0000385fun! s:ChgDir(newdir,errlvl,errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000386 try
Bram Moolenaare37d50a2008-08-06 17:06:04 +0000387 exe "cd ".fnameescape(a:newdir)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000388 catch /^Vim\%((\a\+)\)\=:E344/
389 redraw!
390 if a:errlvl == s:NOTE
Christian Brabandt120c0dd2024-08-05 20:51:47 +0200391 echomsg "***note*** ".a:errmsg
Bram Moolenaar9964e462007-05-05 17:54:07 +0000392 elseif a:errlvl == s:WARNING
Christian Brabandt8d529262024-08-06 18:35:00 +0200393 call s:Mess("WarningMsg", "***warning*** ".a:errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000394 elseif a:errlvl == s:ERROR
Christian Brabandt8d529262024-08-06 18:35:00 +0200395 call s:Mess("Error", "***error*** ".a:errmsg)
Bram Moolenaar9964e462007-05-05 17:54:07 +0000396 endif
Bram Moolenaar9964e462007-05-05 17:54:07 +0000397 return 1
398 endtry
399
Bram Moolenaar9964e462007-05-05 17:54:07 +0000400 return 0
401endfun
402
Christian Brabandt19636be2024-08-05 21:00:07 +0200403" ---------------------------------------------------------------------
404" s:SetSaneOpts: {{{2
405fun! s:SetSaneOpts()
406 let dict = {}
407 let dict.report = &report
408 let dict.shellslash = &shellslash
409
410 let &report = 10
411 let &shellslash = 0
412
413 return dict
414endfun
415
416" ---------------------------------------------------------------------
417" s:RestoreOpts: {{{2
418fun! s:RestoreOpts(dict)
419 for [key, val] in items(a:dict)
420 exe $"let &{key} = {val}"
421 endfor
422endfun
423
Bram Moolenaar60a795a2005-09-16 21:55:43 +0000424" ------------------------------------------------------------------------
425" Modelines And Restoration: {{{1
426let &cpo= s:keepcpo
427unlet s:keepcpo
Bram Moolenaarccc18222007-05-10 18:25:20 +0000428" vim:ts=8 fdm=marker