1 " Vim autoload file for editing compressed files.
2 " Maintainer: Bram Moolenaar <Bram@vim.org>
3 " Last Change: 2008 Jul 04
5 " These functions are used by the gzip plugin.
7 " Function to check that executing "cmd [-f]" works.
8 " The result is cached in s:have_"cmd" for speed.
10 let name = substitute(a:cmd, '\(\S*\).*', '\1', '')
11 if !exists("s:have_" . name)
12 let e = executable(name)
14 let r = system(name . " --version")
15 let e = (r !~ "not found" && r != "")
17 exe "let s:have_" . name . "=" . e
19 exe "return s:have_" . name
22 " Set b:gzip_comp_arg to the gzip argument to be used for compression, based on
23 " the flags in the compressed file.
24 " The only compression methods that can be detected are max speed (-1) and max
26 fun s:set_compression(line)
27 " get the Compression Method
28 let l:cm = char2nr(a:line[2])
29 " if it's 8 (DEFLATE), we can check for the compression level
32 let l:xfl = char2nr(a:line[8])
35 let b:gzip_comp_arg = "-9"
38 let b:gzip_comp_arg = "-1"
44 " After reading compressed file: Uncompress text in buffer with "cmd"
46 " don't do anything if the cmd is not supported
51 " for gzip check current compression level and set b:gzip_comp_arg.
52 silent! unlet b:gzip_comp_arg
54 call s:set_compression(getline(1))
57 " make 'patchmode' empty, we don't want a copy of the written file
60 " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes
66 " Reset 'foldenable', otherwise line numbers get adjusted.
72 " when filtering the whole buffer, it will become empty
73 let empty = line("'[") == 1 && line("']") == line("$")
75 let tmpe = tmp . "." . expand("<afile>:e")
76 if exists('*fnameescape')
77 let tmp_esc = fnameescape(tmp)
78 let tmpe_esc = fnameescape(tmpe)
80 let tmp_esc = escape(tmp, ' ')
81 let tmpe_esc = escape(tmpe, ' ')
83 " write the just read lines to a temp file "'[,']w tmp.gz"
84 execute "silent '[,']w " . tmpe_esc
85 " uncompress the temp file: call system("gzip -dn tmp.gz")
86 call system(a:cmd . " " . s:escape(tmpe))
88 " uncompress didn't work! Keep the compressed file then.
89 echoerr "Error: Could not read uncompressed file"
93 " delete the compressed lines; remember the line number
94 let l = line("'[") - 1
95 if exists(":lockmarks")
100 " read in the uncompressed lines "'[-1r tmp"
101 " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options.
103 if exists(":lockmarks")
105 execute "silent lockmarks " . l . "r ++edit " . tmp_esc
107 execute "silent lockmarks " . l . "r " . tmp_esc
110 execute "silent " . l . "r " . tmp_esc
113 " if buffer became empty, delete trailing blank line
118 " delete the temp file and the used buffers
120 silent! exe "bwipe " . tmp_esc
121 silent! exe "bwipe " . tmpe_esc
124 " Restore saved option values.
129 let &l:fen = fen_save
132 " When uncompressed the whole buffer, do autocommands
134 if exists('*fnameescape')
135 let fname = fnameescape(expand("%:r"))
137 let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
140 execute "doau BufReadPost " . fname
142 execute "silent! doau BufReadPost " . fname
147 " After writing compressed file: Compress written file with "cmd"
149 " don't do anything if the cmd is not supported
151 " Rename the file before compressing it.
152 let nm = resolve(expand("<afile>"))
153 let nmt = s:tempname(nm)
154 if rename(nm, nmt) == 0
155 if exists("b:gzip_comp_arg")
156 call system(a:cmd . " " . b:gzip_comp_arg . " -- " . s:escape(nmt))
158 call system(a:cmd . " -- " . s:escape(nmt))
160 call rename(nmt . "." . expand("<afile>:e"), nm)
165 " Before appending to compressed file: Uncompress file with "cmd"
167 " don't do anything if the cmd is not supported
169 let nm = expand("<afile>")
171 " for gzip check current compression level and set b:gzip_comp_arg.
172 silent! unlet b:gzip_comp_arg
174 call s:set_compression(readfile(nm, "b", 1)[0])
177 " Rename to a weird name to avoid the risk of overwriting another file
178 let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
179 let nmte = nmt . "." . expand("<afile>:e")
180 if rename(nm, nmte) == 0
181 if &patchmode != "" && getfsize(nm . &patchmode) == -1
182 " Create patchmode file by creating the decompressed file new
183 call system(a:cmd . " -c -- " . s:escape(nmte) . " > " . s:escape(nmt))
184 call rename(nmte, nm . &patchmode)
186 call system(a:cmd . " -- " . s:escape(nmte))
193 " find a file name for the file to be compressed. Use "name" without an
194 " extension if possible. Otherwise use a weird name to avoid overwriting an
197 let fn = fnamemodify(a:name, ":r")
198 if !filereadable(fn) && !isdirectory(fn)
201 return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
205 " shellescape() was added by patch 7.0.111
206 if exists("*shellescape")
207 return shellescape(a:name)
209 return "'" . a:name . "'"