xref: /vim-8.2.3635/runtime/autoload/gzip.vim (revision 32efaf61)
187e25fdfSBram Moolenaar" Vim autoload file for editing compressed files.
287e25fdfSBram Moolenaar" Maintainer: Bram Moolenaar <[email protected]>
3*32efaf61SBram Moolenaar" Last Change: 2014 Nov 05
487e25fdfSBram Moolenaar
587e25fdfSBram Moolenaar" These functions are used by the gzip plugin.
687e25fdfSBram Moolenaar
787e25fdfSBram Moolenaar" Function to check that executing "cmd [-f]" works.
887e25fdfSBram Moolenaar" The result is cached in s:have_"cmd" for speed.
987e25fdfSBram Moolenaarfun s:check(cmd)
1087e25fdfSBram Moolenaar  let name = substitute(a:cmd, '\(\S*\).*', '\1', '')
1187e25fdfSBram Moolenaar  if !exists("s:have_" . name)
1287e25fdfSBram Moolenaar    let e = executable(name)
1387e25fdfSBram Moolenaar    if e < 0
1487e25fdfSBram Moolenaar      let r = system(name . " --version")
1587e25fdfSBram Moolenaar      let e = (r !~ "not found" && r != "")
1687e25fdfSBram Moolenaar    endif
1787e25fdfSBram Moolenaar    exe "let s:have_" . name . "=" . e
1887e25fdfSBram Moolenaar  endif
1987e25fdfSBram Moolenaar  exe "return s:have_" . name
2087e25fdfSBram Moolenaarendfun
2187e25fdfSBram Moolenaar
2287e25fdfSBram Moolenaar" Set b:gzip_comp_arg to the gzip argument to be used for compression, based on
2387e25fdfSBram Moolenaar" the flags in the compressed file.
2487e25fdfSBram Moolenaar" The only compression methods that can be detected are max speed (-1) and max
2587e25fdfSBram Moolenaar" compression (-9).
2687e25fdfSBram Moolenaarfun s:set_compression(line)
2787e25fdfSBram Moolenaar  " get the Compression Method
2887e25fdfSBram Moolenaar  let l:cm = char2nr(a:line[2])
2987e25fdfSBram Moolenaar  " if it's 8 (DEFLATE), we can check for the compression level
3087e25fdfSBram Moolenaar  if l:cm == 8
3187e25fdfSBram Moolenaar    " get the eXtra FLags
3287e25fdfSBram Moolenaar    let l:xfl = char2nr(a:line[8])
3387e25fdfSBram Moolenaar    " max compression
3487e25fdfSBram Moolenaar    if l:xfl == 2
3587e25fdfSBram Moolenaar      let b:gzip_comp_arg = "-9"
3687e25fdfSBram Moolenaar    " min compression
3787e25fdfSBram Moolenaar    elseif l:xfl == 4
3887e25fdfSBram Moolenaar      let b:gzip_comp_arg = "-1"
3987e25fdfSBram Moolenaar    endif
4087e25fdfSBram Moolenaar  endif
4187e25fdfSBram Moolenaarendfun
4287e25fdfSBram Moolenaar
4387e25fdfSBram Moolenaar
4487e25fdfSBram Moolenaar" After reading compressed file: Uncompress text in buffer with "cmd"
4587e25fdfSBram Moolenaarfun gzip#read(cmd)
4687e25fdfSBram Moolenaar  " don't do anything if the cmd is not supported
4787e25fdfSBram Moolenaar  if !s:check(a:cmd)
4887e25fdfSBram Moolenaar    return
4987e25fdfSBram Moolenaar  endif
5087e25fdfSBram Moolenaar
5187e25fdfSBram Moolenaar  " for gzip check current compression level and set b:gzip_comp_arg.
5287e25fdfSBram Moolenaar  silent! unlet b:gzip_comp_arg
5387e25fdfSBram Moolenaar  if a:cmd[0] == 'g'
5487e25fdfSBram Moolenaar    call s:set_compression(getline(1))
5587e25fdfSBram Moolenaar  endif
5687e25fdfSBram Moolenaar
5787e25fdfSBram Moolenaar  " make 'patchmode' empty, we don't want a copy of the written file
5887e25fdfSBram Moolenaar  let pm_save = &pm
5987e25fdfSBram Moolenaar  set pm=
6087e25fdfSBram Moolenaar  " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes
6187e25fdfSBram Moolenaar  let cpo_save = &cpo
6287e25fdfSBram Moolenaar  set cpo-=a cpo-=A
6387e25fdfSBram Moolenaar  " set 'modifiable'
6487e25fdfSBram Moolenaar  let ma_save = &ma
6587e25fdfSBram Moolenaar  setlocal ma
66c1762ccbSBram Moolenaar  " Reset 'foldenable', otherwise line numbers get adjusted.
67c1762ccbSBram Moolenaar  if has("folding")
68c1762ccbSBram Moolenaar    let fen_save = &fen
69c1762ccbSBram Moolenaar    setlocal nofen
70c1762ccbSBram Moolenaar  endif
71c1762ccbSBram Moolenaar
7287e25fdfSBram Moolenaar  " when filtering the whole buffer, it will become empty
7387e25fdfSBram Moolenaar  let empty = line("'[") == 1 && line("']") == line("$")
7487e25fdfSBram Moolenaar  let tmp = tempname()
7587e25fdfSBram Moolenaar  let tmpe = tmp . "." . expand("<afile>:e")
76c24dca26SBram Moolenaar  if exists('*fnameescape')
77c24dca26SBram Moolenaar    let tmp_esc = fnameescape(tmp)
78c24dca26SBram Moolenaar    let tmpe_esc = fnameescape(tmpe)
79c24dca26SBram Moolenaar  else
80c24dca26SBram Moolenaar    let tmp_esc = escape(tmp, ' ')
81c24dca26SBram Moolenaar    let tmpe_esc = escape(tmpe, ' ')
82c24dca26SBram Moolenaar  endif
8387e25fdfSBram Moolenaar  " write the just read lines to a temp file "'[,']w tmp.gz"
84c24dca26SBram Moolenaar  execute "silent '[,']w " . tmpe_esc
8587e25fdfSBram Moolenaar  " uncompress the temp file: call system("gzip -dn tmp.gz")
8660a495f0SBram Moolenaar  call system(a:cmd . " " . s:escape(tmpe))
8787e25fdfSBram Moolenaar  if !filereadable(tmp)
8887e25fdfSBram Moolenaar    " uncompress didn't work!  Keep the compressed file then.
8987e25fdfSBram Moolenaar    echoerr "Error: Could not read uncompressed file"
90c1762ccbSBram Moolenaar    let ok = 0
91c1762ccbSBram Moolenaar  else
92c1762ccbSBram Moolenaar    let ok = 1
9387e25fdfSBram Moolenaar    " delete the compressed lines; remember the line number
9487e25fdfSBram Moolenaar    let l = line("'[") - 1
9587e25fdfSBram Moolenaar    if exists(":lockmarks")
9687e25fdfSBram Moolenaar      lockmarks '[,']d _
9787e25fdfSBram Moolenaar    else
9887e25fdfSBram Moolenaar      '[,']d _
9987e25fdfSBram Moolenaar    endif
10087e25fdfSBram Moolenaar    " read in the uncompressed lines "'[-1r tmp"
101910f66f9SBram Moolenaar    " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options.
10287e25fdfSBram Moolenaar    setlocal nobin
10387e25fdfSBram Moolenaar    if exists(":lockmarks")
104910f66f9SBram Moolenaar      if empty
105c24dca26SBram Moolenaar	execute "silent lockmarks " . l . "r ++edit " . tmp_esc
106910f66f9SBram Moolenaar      else
107c24dca26SBram Moolenaar	execute "silent lockmarks " . l . "r " . tmp_esc
108910f66f9SBram Moolenaar      endif
10987e25fdfSBram Moolenaar    else
110c24dca26SBram Moolenaar      execute "silent " . l . "r " . tmp_esc
11187e25fdfSBram Moolenaar    endif
11287e25fdfSBram Moolenaar
11387e25fdfSBram Moolenaar    " if buffer became empty, delete trailing blank line
11487e25fdfSBram Moolenaar    if empty
11587e25fdfSBram Moolenaar      silent $delete _
11687e25fdfSBram Moolenaar      1
11787e25fdfSBram Moolenaar    endif
11887e25fdfSBram Moolenaar    " delete the temp file and the used buffers
11987e25fdfSBram Moolenaar    call delete(tmp)
120c24dca26SBram Moolenaar    silent! exe "bwipe " . tmp_esc
121c24dca26SBram Moolenaar    silent! exe "bwipe " . tmpe_esc
122c1762ccbSBram Moolenaar  endif
123*32efaf61SBram Moolenaar  " Store the OK flag, so that we can use it when writing.
124*32efaf61SBram Moolenaar  let b:uncompressOk = ok
125c1762ccbSBram Moolenaar
126c1762ccbSBram Moolenaar  " Restore saved option values.
12787e25fdfSBram Moolenaar  let &pm = pm_save
12887e25fdfSBram Moolenaar  let &cpo = cpo_save
12987e25fdfSBram Moolenaar  let &l:ma = ma_save
130c1762ccbSBram Moolenaar  if has("folding")
131c1762ccbSBram Moolenaar    let &l:fen = fen_save
132c1762ccbSBram Moolenaar  endif
133c1762ccbSBram Moolenaar
13487e25fdfSBram Moolenaar  " When uncompressed the whole buffer, do autocommands
135c1762ccbSBram Moolenaar  if ok && empty
136c24dca26SBram Moolenaar    if exists('*fnameescape')
137c24dca26SBram Moolenaar      let fname = fnameescape(expand("%:r"))
13887e25fdfSBram Moolenaar    else
139c24dca26SBram Moolenaar      let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
140c24dca26SBram Moolenaar    endif
141c24dca26SBram Moolenaar    if &verbose >= 8
142c24dca26SBram Moolenaar      execute "doau BufReadPost " . fname
143c24dca26SBram Moolenaar    else
144c24dca26SBram Moolenaar      execute "silent! doau BufReadPost " . fname
14587e25fdfSBram Moolenaar    endif
14687e25fdfSBram Moolenaar  endif
14787e25fdfSBram Moolenaarendfun
14887e25fdfSBram Moolenaar
14987e25fdfSBram Moolenaar" After writing compressed file: Compress written file with "cmd"
15087e25fdfSBram Moolenaarfun gzip#write(cmd)
151*32efaf61SBram Moolenaar  if exists('b:uncompressOk') && !b:uncompressOk
152*32efaf61SBram Moolenaar    echomsg "Not compressing file because uncompress failed; reset b:uncompressOk to compress anyway"
15387e25fdfSBram Moolenaar  " don't do anything if the cmd is not supported
154*32efaf61SBram Moolenaar  elseif s:check(a:cmd)
15587e25fdfSBram Moolenaar    " Rename the file before compressing it.
15687e25fdfSBram Moolenaar    let nm = resolve(expand("<afile>"))
15787e25fdfSBram Moolenaar    let nmt = s:tempname(nm)
15887e25fdfSBram Moolenaar    if rename(nm, nmt) == 0
15987e25fdfSBram Moolenaar      if exists("b:gzip_comp_arg")
160c236c16dSBram Moolenaar	call system(a:cmd . " " . b:gzip_comp_arg . " -- " . s:escape(nmt))
16187e25fdfSBram Moolenaar      else
162c236c16dSBram Moolenaar	call system(a:cmd . " -- " . s:escape(nmt))
16387e25fdfSBram Moolenaar      endif
16487e25fdfSBram Moolenaar      call rename(nmt . "." . expand("<afile>:e"), nm)
16587e25fdfSBram Moolenaar    endif
16687e25fdfSBram Moolenaar  endif
16787e25fdfSBram Moolenaarendfun
16887e25fdfSBram Moolenaar
16987e25fdfSBram Moolenaar" Before appending to compressed file: Uncompress file with "cmd"
17087e25fdfSBram Moolenaarfun gzip#appre(cmd)
17187e25fdfSBram Moolenaar  " don't do anything if the cmd is not supported
17287e25fdfSBram Moolenaar  if s:check(a:cmd)
17387e25fdfSBram Moolenaar    let nm = expand("<afile>")
17487e25fdfSBram Moolenaar
17587e25fdfSBram Moolenaar    " for gzip check current compression level and set b:gzip_comp_arg.
17687e25fdfSBram Moolenaar    silent! unlet b:gzip_comp_arg
17787e25fdfSBram Moolenaar    if a:cmd[0] == 'g'
17887e25fdfSBram Moolenaar      call s:set_compression(readfile(nm, "b", 1)[0])
17987e25fdfSBram Moolenaar    endif
18087e25fdfSBram Moolenaar
18187e25fdfSBram Moolenaar    " Rename to a weird name to avoid the risk of overwriting another file
18287e25fdfSBram Moolenaar    let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
18387e25fdfSBram Moolenaar    let nmte = nmt . "." . expand("<afile>:e")
18487e25fdfSBram Moolenaar    if rename(nm, nmte) == 0
18587e25fdfSBram Moolenaar      if &patchmode != "" && getfsize(nm . &patchmode) == -1
18687e25fdfSBram Moolenaar	" Create patchmode file by creating the decompressed file new
187c236c16dSBram Moolenaar	call system(a:cmd . " -c -- " . s:escape(nmte) . " > " . s:escape(nmt))
18887e25fdfSBram Moolenaar	call rename(nmte, nm . &patchmode)
18987e25fdfSBram Moolenaar      else
190c236c16dSBram Moolenaar	call system(a:cmd . " -- " . s:escape(nmte))
19187e25fdfSBram Moolenaar      endif
19287e25fdfSBram Moolenaar      call rename(nmt, nm)
19387e25fdfSBram Moolenaar    endif
19487e25fdfSBram Moolenaar  endif
19587e25fdfSBram Moolenaarendfun
19687e25fdfSBram Moolenaar
19787e25fdfSBram Moolenaar" find a file name for the file to be compressed.  Use "name" without an
19887e25fdfSBram Moolenaar" extension if possible.  Otherwise use a weird name to avoid overwriting an
19987e25fdfSBram Moolenaar" existing file.
20087e25fdfSBram Moolenaarfun s:tempname(name)
20187e25fdfSBram Moolenaar  let fn = fnamemodify(a:name, ":r")
20287e25fdfSBram Moolenaar  if !filereadable(fn) && !isdirectory(fn)
20387e25fdfSBram Moolenaar    return fn
20487e25fdfSBram Moolenaar  endif
20587e25fdfSBram Moolenaar  return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
20687e25fdfSBram Moolenaarendfun
20787e25fdfSBram Moolenaar
20860a495f0SBram Moolenaarfun s:escape(name)
20960a495f0SBram Moolenaar  " shellescape() was added by patch 7.0.111
2105c5b0941SBram Moolenaar  if exists("*shellescape")
21160a495f0SBram Moolenaar    return shellescape(a:name)
21260a495f0SBram Moolenaar  endif
21360a495f0SBram Moolenaar  return "'" . a:name . "'"
21460a495f0SBram Moolenaarendfun
21560a495f0SBram Moolenaar
21687e25fdfSBram Moolenaar" vim: set sw=2 :
217