tar.vim 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. " tar.vim: Handles browsing tarfiles - AUTOLOAD PORTION
  2. " Date: Mar 01, 2025
  3. " Version: 32b (with modifications from the Vim Project)
  4. " Maintainer: This runtime file is looking for a new maintainer.
  5. " Former Maintainer: Charles E Campbell
  6. " License: Vim License (see vim's :help license)
  7. " Last Change:
  8. " 2024 Jan 08 by Vim Project: fix a few problems (#138331, #12637, #8109)
  9. " 2024 Feb 19 by Vim Project: announce adoption
  10. " 2024 Nov 11 by Vim Project: support permissions (#7379)
  11. " 2025 Feb 06 by Vim Project: add support for lz4 (#16591)
  12. " 2025 Feb 28 by Vim Project: add support for bzip3 (#16755)
  13. " 2025 Mar 01 by Vim Project: fix syntax error in tar#Read()
  14. " 2025 Mar 02 by Vim Project: escape the filename before using :read
  15. "
  16. " Contains many ideas from Michael Toren's <tar.vim>
  17. "
  18. " Copyright: Copyright (C) 2005-2017 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. " tar.vim and tarPlugin.vim are provided *as is* and comes
  23. " with no warranty of any kind, either expressed or implied.
  24. " By using this plugin, you agree that in no event will the
  25. " copyright holder be liable for any damages resulting from
  26. " the use of this software.
  27. " ---------------------------------------------------------------------
  28. " Load Once: {{{1
  29. if &cp || exists("g:loaded_tar")
  30. finish
  31. endif
  32. let g:loaded_tar= "v32b"
  33. if v:version < 702
  34. echohl WarningMsg
  35. echo "***warning*** this version of tar needs vim 7.2"
  36. echohl Normal
  37. finish
  38. endif
  39. let s:keepcpo= &cpo
  40. set cpo&vim
  41. " ---------------------------------------------------------------------
  42. " Default Settings: {{{1
  43. if !exists("g:tar_browseoptions")
  44. let g:tar_browseoptions= "Ptf"
  45. endif
  46. if !exists("g:tar_readoptions")
  47. let g:tar_readoptions= "pPxf"
  48. endif
  49. if !exists("g:tar_cmd")
  50. let g:tar_cmd= "tar"
  51. endif
  52. if !exists("g:tar_writeoptions")
  53. let g:tar_writeoptions= "uf"
  54. endif
  55. if !exists("g:tar_delfile")
  56. let g:tar_delfile="--delete -f"
  57. endif
  58. if !exists("g:netrw_cygwin")
  59. if has("win32") || has("win95") || has("win64") || has("win16")
  60. if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
  61. let g:netrw_cygwin= 1
  62. else
  63. let g:netrw_cygwin= 0
  64. endif
  65. else
  66. let g:netrw_cygwin= 0
  67. endif
  68. endif
  69. if !exists("g:tar_copycmd")
  70. if !exists("g:netrw_localcopycmd")
  71. if has("win32") || has("win95") || has("win64") || has("win16")
  72. if g:netrw_cygwin
  73. let g:netrw_localcopycmd= "cp"
  74. else
  75. let g:netrw_localcopycmd= "copy"
  76. endif
  77. elseif has("unix") || has("macunix")
  78. let g:netrw_localcopycmd= "cp"
  79. else
  80. let g:netrw_localcopycmd= ""
  81. endif
  82. endif
  83. let g:tar_copycmd= g:netrw_localcopycmd
  84. endif
  85. if !exists("g:tar_extractcmd")
  86. let g:tar_extractcmd= "tar -pxf"
  87. endif
  88. " set up shell quoting character
  89. if !exists("g:tar_shq")
  90. if exists("+shq") && exists("&shq") && &shq != ""
  91. let g:tar_shq= &shq
  92. elseif has("win32") || has("win95") || has("win64") || has("win16")
  93. if exists("g:netrw_cygwin") && g:netrw_cygwin
  94. let g:tar_shq= "'"
  95. else
  96. let g:tar_shq= '"'
  97. endif
  98. else
  99. let g:tar_shq= "'"
  100. endif
  101. endif
  102. " ----------------
  103. " Functions: {{{1
  104. " ----------------
  105. " ---------------------------------------------------------------------
  106. " tar#Browse: {{{2
  107. fun! tar#Browse(tarfile)
  108. let repkeep= &report
  109. set report=10
  110. " sanity checks
  111. if !executable(g:tar_cmd)
  112. redraw!
  113. echohl Error | echo '***error*** (tar#Browse) "'.g:tar_cmd.'" not available on your system'
  114. let &report= repkeep
  115. return
  116. endif
  117. if !filereadable(a:tarfile)
  118. if a:tarfile !~# '^\a\+://'
  119. " if it's an url, don't complain, let url-handlers such as vim do its thing
  120. redraw!
  121. echohl Error | echo "***error*** (tar#Browse) File not readable<".a:tarfile.">" | echohl None
  122. endif
  123. let &report= repkeep
  124. return
  125. endif
  126. if &ma != 1
  127. set ma
  128. endif
  129. let b:tarfile= a:tarfile
  130. setlocal noswapfile
  131. setlocal buftype=nofile
  132. setlocal bufhidden=hide
  133. setlocal nobuflisted
  134. setlocal nowrap
  135. set ft=tar
  136. " give header
  137. let lastline= line("$")
  138. call setline(lastline+1,'" tar.vim version '.g:loaded_tar)
  139. call setline(lastline+2,'" Browsing tarfile '.a:tarfile)
  140. call setline(lastline+3,'" Select a file with cursor and press ENTER')
  141. keepj $put =''
  142. keepj sil! 0d
  143. keepj $
  144. let tarfile= a:tarfile
  145. if has("win32unix") && executable("cygpath")
  146. " assuming cygwin
  147. let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
  148. endif
  149. let curlast= line("$")
  150. if tarfile =~# '\.\(gz\)$'
  151. exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  152. elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' ||
  153. \ tarfile =~# '\.\(tzst\)$' || tarfile =~# '\.\(tlz4\)$'
  154. if has("unix") && executable("file")
  155. let filekind= system("file ".shellescape(tarfile,1))
  156. else
  157. let filekind= ""
  158. endif
  159. if filekind =~ "bzip2"
  160. exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  161. elseif filekind =~ "bzip3"
  162. exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  163. elseif filekind =~ "XZ"
  164. exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  165. elseif filekind =~ "Zstandard"
  166. exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  167. elseif filekind =~ "LZ4"
  168. exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  169. else
  170. exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  171. endif
  172. elseif tarfile =~# '\.lrp'
  173. exe "sil! r! cat -- ".shellescape(tarfile,1)."|gzip -d -c -|".g:tar_cmd." -".g:tar_browseoptions." - "
  174. elseif tarfile =~# '\.\(bz2\|tbz\|tb2\)$'
  175. exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  176. elseif tarfile =~# '\.\(bz3\|tb3\)$'
  177. exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  178. elseif tarfile =~# '\.\(lzma\|tlz\)$'
  179. exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  180. elseif tarfile =~# '\.\(xz\|txz\)$'
  181. exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  182. elseif tarfile =~# '\.\(zst\|tzst\)$'
  183. exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  184. elseif tarfile =~# '\.\(lz4\|tlz4\)$'
  185. exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
  186. else
  187. if tarfile =~ '^\s*-'
  188. " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
  189. let tarfile = substitute(tarfile, '-', './-', '')
  190. endif
  191. exe "sil! r! ".g:tar_cmd." -".g:tar_browseoptions." ".shellescape(tarfile,1)
  192. endif
  193. if v:shell_error != 0
  194. redraw!
  195. echohl WarningMsg | echo "***warning*** (tar#Browse) please check your g:tar_browseoptions<".g:tar_browseoptions.">"
  196. return
  197. endif
  198. "
  199. " The following should not be neccessary, since in case of errors the
  200. " previous if statement should have caught the problem (because tar exited
  201. " with a non-zero exit code).
  202. " if line("$") == curlast || ( line("$") == (curlast + 1) &&
  203. " \ getline("$") =~# '\c\<\%(warning\|error\|inappropriate\|unrecognized\)\>' &&
  204. " \ getline("$") =~ '\s' )
  205. " redraw!
  206. " echohl WarningMsg | echo "***warning*** (tar#Browse) ".a:tarfile." doesn't appear to be a tar file" | echohl None
  207. " keepj sil! %d
  208. " let eikeep= &ei
  209. " set ei=BufReadCmd,FileReadCmd
  210. " exe "r ".fnameescape(a:tarfile)
  211. " let &ei= eikeep
  212. " keepj sil! 1d
  213. " call Dret("tar#Browse : a:tarfile<".a:tarfile.">")
  214. " return
  215. " endif
  216. " set up maps supported for tar
  217. setlocal noma nomod ro
  218. noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
  219. noremap <silent> <buffer> x :call tar#Extract()<cr>
  220. if &mouse != ""
  221. noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>TarBrowseSelect()<cr>
  222. endif
  223. let &report= repkeep
  224. endfun
  225. " ---------------------------------------------------------------------
  226. " TarBrowseSelect: {{{2
  227. fun! s:TarBrowseSelect()
  228. let repkeep= &report
  229. set report=10
  230. let fname= getline(".")
  231. if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
  232. redraw!
  233. echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
  234. return
  235. endif
  236. " sanity check
  237. if fname =~ '^"'
  238. let &report= repkeep
  239. return
  240. endif
  241. " about to make a new window, need to use b:tarfile
  242. let tarfile= b:tarfile
  243. let curfile= expand("%")
  244. if has("win32unix") && executable("cygpath")
  245. " assuming cygwin
  246. let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
  247. endif
  248. " open a new window (tar#Read will read a file into it)
  249. noswapfile new
  250. if !exists("g:tar_nomax") || g:tar_nomax == 0
  251. wincmd _
  252. endif
  253. let s:tblfile_{winnr()}= curfile
  254. call tar#Read("tarfile:".tarfile.'::'.fname,1)
  255. filetype detect
  256. set nomod
  257. exe 'com! -buffer -nargs=? -complete=file TarDiff :call tar#Diff(<q-args>,"'.fnameescape(fname).'")'
  258. let &report= repkeep
  259. endfun
  260. " ---------------------------------------------------------------------
  261. " tar#Read: {{{2
  262. fun! tar#Read(fname,mode)
  263. let repkeep= &report
  264. set report=10
  265. let tarfile = substitute(a:fname,'tarfile:\(.\{-}\)::.*$','\1','')
  266. let fname = substitute(a:fname,'tarfile:.\{-}::\(.*\)$','\1','')
  267. " be careful not to execute special crafted files
  268. let escape_file = fname->fnameescape()
  269. " changing the directory to the temporary earlier to allow tar to extract the file with permissions intact
  270. if !exists("*mkdir")
  271. redraw!
  272. echohl Error | echo "***error*** (tar#Write) sorry, mkdir() doesn't work on your system" | echohl None
  273. let &report= repkeep
  274. return
  275. endif
  276. let curdir= getcwd()
  277. let tmpdir= tempname()
  278. let b:curdir= tmpdir
  279. let b:tmpdir= curdir
  280. if tmpdir =~ '\.'
  281. let tmpdir= substitute(tmpdir,'\.[^.]*$','','e')
  282. endif
  283. call mkdir(tmpdir,"p")
  284. " attempt to change to the indicated directory
  285. try
  286. exe "cd ".fnameescape(tmpdir)
  287. catch /^Vim\%((\a\+)\)\=:E344/
  288. redraw!
  289. echohl Error | echo "***error*** (tar#Write) cannot cd to temporary directory" | Echohl None
  290. let &report= repkeep
  291. return
  292. endtry
  293. " place temporary files under .../_ZIPVIM_/
  294. if isdirectory("_ZIPVIM_")
  295. call s:Rmdir("_ZIPVIM_")
  296. endif
  297. call mkdir("_ZIPVIM_")
  298. cd _ZIPVIM_
  299. if has("win32unix") && executable("cygpath")
  300. " assuming cygwin
  301. let tarfile=substitute(system("cygpath -u ".shellescape(tarfile,0)),'\n$','','e')
  302. endif
  303. if fname =~ '\.bz2$' && executable("bzcat")
  304. let decmp= "|bzcat"
  305. let doro = 1
  306. elseif fname =~ '\.bz3$' && executable("bz3cat")
  307. let decmp= "|bz3cat"
  308. let doro = 1
  309. elseif fname =~ '\.t\=gz$' && executable("zcat")
  310. let decmp= "|zcat"
  311. let doro = 1
  312. elseif fname =~ '\.lzma$' && executable("lzcat")
  313. let decmp= "|lzcat"
  314. let doro = 1
  315. elseif fname =~ '\.xz$' && executable("xzcat")
  316. let decmp= "|xzcat"
  317. let doro = 1
  318. elseif fname =~ '\.zst$' && executable("zstdcat")
  319. let decmp= "|zstdcat"
  320. let doro = 1
  321. elseif fname =~ '\.lz4$' && executable("lz4cat")
  322. let decmp= "|lz4cat"
  323. let doro = 1
  324. else
  325. let decmp=""
  326. let doro = 0
  327. if fname =~ '\.bz2$\|\.bz3$\|\.gz$\|\.lzma$\|\.xz$\|\.zip$\|\.Z$'
  328. setlocal bin
  329. endif
  330. endif
  331. if exists("g:tar_secure")
  332. let tar_secure= " -- "
  333. else
  334. let tar_secure= " "
  335. endif
  336. if tarfile =~# '\.bz2$'
  337. exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  338. exe "read ".escape_file
  339. elseif tarfile =~# '\.bz3$'
  340. exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  341. exe "read ".escape_file
  342. elseif tarfile =~# '\.\(gz\)$'
  343. exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  344. exe "read ".escape_file
  345. elseif tarfile =~# '\(\.tgz\|\.tbz\|\.txz\)'
  346. if has("unix") && executable("file")
  347. let filekind= system("file ".shellescape(tarfile,1))
  348. else
  349. let filekind= ""
  350. endif
  351. if filekind =~ "bzip2"
  352. exe "sil! r! bzip2 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  353. exe "read ".escape_file
  354. elseif filekind =~ "bzip3"
  355. exe "sil! r! bzip3 -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  356. exe "read ".escape_file
  357. elseif filekind =~ "XZ"
  358. exe "sil! r! xz -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  359. exe "read ".escape_file
  360. elseif filekind =~ "Zstandard"
  361. exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  362. exe "read ".escape_file
  363. else
  364. exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  365. exe "read ".escape_file
  366. endif
  367. elseif tarfile =~# '\.lrp$'
  368. exe "sil! r! cat -- ".shellescape(tarfile,1)." | gzip -d -c - | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  369. exe "read ".escape_file
  370. elseif tarfile =~# '\.lzma$'
  371. exe "sil! r! lzma -d -c -- ".shellescape(tarfile,1)."| ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  372. exe "read ".escape_file
  373. elseif tarfile =~# '\.\(xz\|txz\)$'
  374. exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  375. exe "read ".escape_file
  376. elseif tarfile =~# '\.\(lz4\|tlz4\)$'
  377. exe "sil! r! lz4 --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_readoptions." - ".tar_secure.shellescape(fname,1).decmp
  378. exe "read ".escape_file
  379. else
  380. if tarfile =~ '^\s*-'
  381. " A file name starting with a dash is taken as an option. Prepend ./ to avoid that.
  382. let tarfile = substitute(tarfile, '-', './-', '')
  383. endif
  384. exe "silent r! ".g:tar_cmd." -".g:tar_readoptions.shellescape(tarfile,1)." ".tar_secure.shellescape(fname,1).decmp
  385. exe "read ".escape_file
  386. endif
  387. redraw!
  388. if v:shell_error != 0
  389. cd ..
  390. call s:Rmdir("_ZIPVIM_")
  391. exe "cd ".fnameescape(curdir)
  392. echohl Error | echo "***error*** (tar#Read) sorry, unable to open or extract ".tarfile." with ".fname | echohl None
  393. endif
  394. if doro
  395. " because the reverse process of compressing changed files back into the tarball is not currently supported
  396. setlocal ro
  397. endif
  398. let b:tarfile= a:fname
  399. exe "file tarfile::".fnameescape(fname)
  400. " cleanup
  401. keepj sil! 0d
  402. set nomod
  403. let &report= repkeep
  404. endfun
  405. " ---------------------------------------------------------------------
  406. " tar#Write: {{{2
  407. fun! tar#Write(fname)
  408. let repkeep= &report
  409. set report=10
  410. " temporary buffer variable workaround because too fucking tired. but it works now
  411. let curdir= b:curdir
  412. let tmpdir= b:tmpdir
  413. if !exists("g:tar_secure") && a:fname =~ '^\s*-\|\s\+-'
  414. redraw!
  415. echohl WarningMsg | echo '***warning*** (tar#Write) rejecting tarfile member<'.a:fname.'> because of embedded "-"'
  416. return
  417. endif
  418. " sanity checks
  419. if !executable(g:tar_cmd)
  420. redraw!
  421. let &report= repkeep
  422. return
  423. endif
  424. let tarfile = substitute(b:tarfile,'tarfile:\(.\{-}\)::.*$','\1','')
  425. let fname = substitute(b:tarfile,'tarfile:.\{-}::\(.*\)$','\1','')
  426. " handle compressed archives
  427. if tarfile =~# '\.bz2'
  428. call system("bzip2 -d -- ".shellescape(tarfile,0))
  429. let tarfile = substitute(tarfile,'\.bz2','','e')
  430. let compress= "bzip2 -- ".shellescape(tarfile,0)
  431. elseif tarfile =~# '\.bz3'
  432. call system("bzip3 -d -- ".shellescape(tarfile,0))
  433. let tarfile = substitute(tarfile,'\.bz3','','e')
  434. let compress= "bzip3 -- ".shellescape(tarfile,0)
  435. elseif tarfile =~# '\.gz'
  436. call system("gzip -d -- ".shellescape(tarfile,0))
  437. let tarfile = substitute(tarfile,'\.gz','','e')
  438. let compress= "gzip -- ".shellescape(tarfile,0)
  439. elseif tarfile =~# '\.tgz'
  440. call system("gzip -d -- ".shellescape(tarfile,0))
  441. let tarfile = substitute(tarfile,'\.tgz','.tar','e')
  442. let compress= "gzip -- ".shellescape(tarfile,0)
  443. let tgz = 1
  444. elseif tarfile =~# '\.xz'
  445. call system("xz -d -- ".shellescape(tarfile,0))
  446. let tarfile = substitute(tarfile,'\.xz','','e')
  447. let compress= "xz -- ".shellescape(tarfile,0)
  448. elseif tarfile =~# '\.zst'
  449. call system("zstd --decompress --rm -- ".shellescape(tarfile,0))
  450. let tarfile = substitute(tarfile,'\.zst','','e')
  451. let compress= "zstd --rm -- ".shellescape(tarfile,0)
  452. elseif tarfile =~# '\.lz4'
  453. call system("lz4 --decompress --rm -- ".shellescape(tarfile,0))
  454. let tarfile = substitute(tarfile,'\.lz4','','e')
  455. let compress= "lz4 --rm -- ".shellescape(tarfile,0)
  456. elseif tarfile =~# '\.lzma'
  457. call system("lzma -d -- ".shellescape(tarfile,0))
  458. let tarfile = substitute(tarfile,'\.lzma','','e')
  459. let compress= "lzma -- ".shellescape(tarfile,0)
  460. endif
  461. if v:shell_error != 0
  462. redraw!
  463. echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".tarfile." with ".fname | echohl None
  464. else
  465. if fname =~ '/'
  466. let dirpath = substitute(fname,'/[^/]\+$','','e')
  467. if has("win32unix") && executable("cygpath")
  468. let dirpath = substitute(system("cygpath ".shellescape(dirpath, 0)),'\n','','e')
  469. endif
  470. call mkdir(dirpath,"p")
  471. endif
  472. if tarfile !~ '/'
  473. let tarfile= curdir.'/'.tarfile
  474. endif
  475. if tarfile =~ '^\s*-'
  476. " A file name starting with a dash may be taken as an option. Prepend ./ to avoid that.
  477. let tarfile = substitute(tarfile, '-', './-', '')
  478. endif
  479. if exists("g:tar_secure")
  480. let tar_secure= " -- "
  481. else
  482. let tar_secure= " "
  483. endif
  484. exe "w! ".fnameescape(fname)
  485. if has("win32unix") && executable("cygpath")
  486. let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
  487. endif
  488. " delete old file from tarfile
  489. call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
  490. if v:shell_error != 0
  491. redraw!
  492. echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
  493. else
  494. " update tarfile with new file
  495. call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
  496. if v:shell_error != 0
  497. redraw!
  498. echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
  499. elseif exists("compress")
  500. call system(compress)
  501. if exists("tgz")
  502. call rename(tarfile.".gz",substitute(tarfile,'\.tar$','.tgz','e'))
  503. endif
  504. endif
  505. endif
  506. " support writing tarfiles across a network
  507. if s:tblfile_{winnr()} =~ '^\a\+://'
  508. let tblfile= s:tblfile_{winnr()}
  509. 1split|noswapfile enew
  510. let binkeep= &l:binary
  511. let eikeep = &ei
  512. set binary ei=all
  513. exe "noswapfile e! ".fnameescape(tarfile)
  514. call netrw#NetWrite(tblfile)
  515. let &ei = eikeep
  516. let &l:binary = binkeep
  517. q!
  518. unlet s:tblfile_{winnr()}
  519. endif
  520. endif
  521. " cleanup and restore current directory
  522. cd ..
  523. call s:Rmdir("_ZIPVIM_")
  524. exe "cd ".fnameescape(curdir)
  525. setlocal nomod
  526. let &report= repkeep
  527. endfun
  528. " ---------------------------------------------------------------------
  529. " tar#Diff: {{{2
  530. fun! tar#Diff(userfname,fname)
  531. let fname= a:fname
  532. if a:userfname != ""
  533. let fname= a:userfname
  534. endif
  535. if filereadable(fname)
  536. " sets current file (from tarball) for diff'ing
  537. " splits window vertically
  538. " opens original file, sets it for diff'ing
  539. " sets up b:tardiff_otherbuf variables so each buffer knows about the other (for closing purposes)
  540. diffthis
  541. wincmd v
  542. exe "noswapfile e ".fnameescape(fname)
  543. diffthis
  544. else
  545. redraw!
  546. echo "***warning*** unable to read file<".fname.">"
  547. endif
  548. endfun
  549. " ---------------------------------------------------------------------
  550. " tar#Extract: extract a file from a (possibly compressed) tar archive {{{2
  551. fun! tar#Extract()
  552. let repkeep= &report
  553. set report=10
  554. let fname= getline(".")
  555. if !exists("g:tar_secure") && fname =~ '^\s*-\|\s\+-'
  556. redraw!
  557. echohl WarningMsg | echo '***warning*** (tar#BrowseSelect) rejecting tarfile member<'.fname.'> because of embedded "-"'
  558. return
  559. endif
  560. " sanity check
  561. if fname =~ '^"'
  562. let &report= repkeep
  563. return
  564. endif
  565. let tarball = expand("%")
  566. let tarbase = substitute(tarball,'\..*$','','')
  567. let extractcmd= netrw#WinPath(g:tar_extractcmd)
  568. if filereadable(tarbase.".tar")
  569. call system(extractcmd." ".shellescape(tarbase).".tar ".shellescape(fname))
  570. if v:shell_error != 0
  571. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar ".fname.": failed!" | echohl NONE
  572. else
  573. echo "***note*** successfully extracted ".fname
  574. endif
  575. elseif filereadable(tarbase.".tgz")
  576. let extractcmd= substitute(extractcmd,"-","-z","")
  577. call system(extractcmd." ".shellescape(tarbase).".tgz ".shellescape(fname))
  578. if v:shell_error != 0
  579. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tgz ".fname.": failed!" | echohl NONE
  580. else
  581. echo "***note*** successfully extracted ".fname
  582. endif
  583. elseif filereadable(tarbase.".tar.gz")
  584. let extractcmd= substitute(extractcmd,"-","-z","")
  585. call system(extractcmd." ".shellescape(tarbase).".tar.gz ".shellescape(fname))
  586. if v:shell_error != 0
  587. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.gz ".fname.": failed!" | echohl NONE
  588. else
  589. echo "***note*** successfully extracted ".fname
  590. endif
  591. elseif filereadable(tarbase.".tbz")
  592. let extractcmd= substitute(extractcmd,"-","-j","")
  593. call system(extractcmd." ".shellescape(tarbase).".tbz ".shellescape(fname))
  594. if v:shell_error != 0
  595. echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tbz ".fname.": failed!" | echohl NONE
  596. else
  597. echo "***note*** successfully extracted ".fname
  598. endif
  599. elseif filereadable(tarbase.".tar.bz2")
  600. let extractcmd= substitute(extractcmd,"-","-j","")
  601. call system(extractcmd." ".shellescape(tarbase).".tar.bz2 ".shellescape(fname))
  602. if v:shell_error != 0
  603. echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz2 ".fname.": failed!" | echohl NONE
  604. else
  605. echo "***note*** successfully extracted ".fname
  606. endif
  607. elseif filereadable(tarbase.".tar.bz3")
  608. let extractcmd= substitute(extractcmd,"-","-j","")
  609. call system(extractcmd." ".shellescape(tarbase).".tar.bz3 ".shellescape(fname))
  610. if v:shell_error != 0
  611. echohl Error | echo "***error*** ".extractcmd."j ".tarbase.".tar.bz3 ".fname.": failed!" | echohl NONE
  612. else
  613. echo "***note*** successfully extracted ".fname
  614. endif
  615. elseif filereadable(tarbase.".txz")
  616. let extractcmd= substitute(extractcmd,"-","-J","")
  617. call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
  618. if v:shell_error != 0
  619. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".txz ".fname.": failed!" | echohl NONE
  620. else
  621. echo "***note*** successfully extracted ".fname
  622. endif
  623. elseif filereadable(tarbase.".tar.xz")
  624. let extractcmd= substitute(extractcmd,"-","-J","")
  625. call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
  626. if v:shell_error != 0
  627. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.xz ".fname.": failed!" | echohl NONE
  628. else
  629. echo "***note*** successfully extracted ".fname
  630. endif
  631. elseif filereadable(tarbase.".tzst")
  632. let extractcmd= substitute(extractcmd,"-","--zstd","")
  633. call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
  634. if v:shell_error != 0
  635. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE
  636. else
  637. echo "***note*** successfully extracted ".fname
  638. endif
  639. elseif filereadable(tarbase.".tar.zst")
  640. let extractcmd= substitute(extractcmd,"-","--zstd","")
  641. call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
  642. if v:shell_error != 0
  643. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
  644. else
  645. echo "***note*** successfully extracted ".fname
  646. endif
  647. elseif filereadable(tarbase.".tlz4")
  648. let extractcmd= substitute(extractcmd,"-","-I lz4","")
  649. call system(extractcmd." ".shellescape(tarbase).".tlz4 ".shellescape(fname))
  650. if v:shell_error != 0
  651. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tlz4 ".fname.": failed!" | echohl NONE
  652. else
  653. echo "***note*** successfully extracted ".fname
  654. endif
  655. elseif filereadable(tarbase.".tar.lz4")
  656. let extractcmd= substitute(extractcmd,"-","-I lz4","")
  657. call system(extractcmd." ".shellescape(tarbase).".tar.lz4".shellescape(fname))
  658. if v:shell_error != 0
  659. echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.lz4 ".fname.": failed!" | echohl NONE
  660. else
  661. echo "***note*** successfully extracted ".fname
  662. endif
  663. endif
  664. " restore option
  665. let &report= repkeep
  666. endfun
  667. " ---------------------------------------------------------------------
  668. " s:Rmdir: {{{2
  669. fun! s:Rmdir(fname)
  670. if has("unix")
  671. call system("/bin/rm -rf -- ".shellescape(a:fname,0))
  672. elseif has("win32") || has("win95") || has("win64") || has("win16")
  673. if &shell =~? "sh$"
  674. call system("/bin/rm -rf -- ".shellescape(a:fname,0))
  675. else
  676. call system("del /S ".shellescape(a:fname,0))
  677. endif
  678. endif
  679. endfun
  680. " =====================================================================
  681. " Modelines And Restoration: {{{1
  682. let &cpo= s:keepcpo
  683. unlet s:keepcpo
  684. " vim:ts=8 fdm=marker