446
|
1 " Vim autoload file for editing compressed files.
|
|
2 " Maintainer: Bram Moolenaar <Bram@vim.org>
|
6336
|
3 " Last Change: 2014 Nov 05
|
446
|
4
|
|
5 " These functions are used by the gzip plugin.
|
|
6
|
|
7 " Function to check that executing "cmd [-f]" works.
|
|
8 " The result is cached in s:have_"cmd" for speed.
|
|
9 fun s:check(cmd)
|
|
10 let name = substitute(a:cmd, '\(\S*\).*', '\1', '')
|
|
11 if !exists("s:have_" . name)
|
|
12 let e = executable(name)
|
|
13 if e < 0
|
|
14 let r = system(name . " --version")
|
|
15 let e = (r !~ "not found" && r != "")
|
|
16 endif
|
|
17 exe "let s:have_" . name . "=" . e
|
|
18 endif
|
|
19 exe "return s:have_" . name
|
|
20 endfun
|
|
21
|
|
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
|
|
25 " compression (-9).
|
|
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
|
|
30 if l:cm == 8
|
|
31 " get the eXtra FLags
|
|
32 let l:xfl = char2nr(a:line[8])
|
|
33 " max compression
|
|
34 if l:xfl == 2
|
|
35 let b:gzip_comp_arg = "-9"
|
|
36 " min compression
|
|
37 elseif l:xfl == 4
|
|
38 let b:gzip_comp_arg = "-1"
|
|
39 endif
|
|
40 endif
|
|
41 endfun
|
|
42
|
|
43
|
|
44 " After reading compressed file: Uncompress text in buffer with "cmd"
|
|
45 fun gzip#read(cmd)
|
|
46 " don't do anything if the cmd is not supported
|
|
47 if !s:check(a:cmd)
|
|
48 return
|
|
49 endif
|
|
50
|
|
51 " for gzip check current compression level and set b:gzip_comp_arg.
|
|
52 silent! unlet b:gzip_comp_arg
|
|
53 if a:cmd[0] == 'g'
|
|
54 call s:set_compression(getline(1))
|
|
55 endif
|
|
56
|
|
57 " make 'patchmode' empty, we don't want a copy of the written file
|
|
58 let pm_save = &pm
|
|
59 set pm=
|
|
60 " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes
|
|
61 let cpo_save = &cpo
|
|
62 set cpo-=a cpo-=A
|
|
63 " set 'modifiable'
|
|
64 let ma_save = &ma
|
|
65 setlocal ma
|
1190
|
66 " Reset 'foldenable', otherwise line numbers get adjusted.
|
|
67 if has("folding")
|
|
68 let fen_save = &fen
|
|
69 setlocal nofen
|
|
70 endif
|
|
71
|
446
|
72 " when filtering the whole buffer, it will become empty
|
|
73 let empty = line("'[") == 1 && line("']") == line("$")
|
|
74 let tmp = tempname()
|
|
75 let tmpe = tmp . "." . expand("<afile>:e")
|
1592
|
76 if exists('*fnameescape')
|
|
77 let tmp_esc = fnameescape(tmp)
|
|
78 let tmpe_esc = fnameescape(tmpe)
|
|
79 else
|
|
80 let tmp_esc = escape(tmp, ' ')
|
|
81 let tmpe_esc = escape(tmpe, ' ')
|
|
82 endif
|
446
|
83 " write the just read lines to a temp file "'[,']w tmp.gz"
|
1592
|
84 execute "silent '[,']w " . tmpe_esc
|
446
|
85 " uncompress the temp file: call system("gzip -dn tmp.gz")
|
985
|
86 call system(a:cmd . " " . s:escape(tmpe))
|
446
|
87 if !filereadable(tmp)
|
|
88 " uncompress didn't work! Keep the compressed file then.
|
|
89 echoerr "Error: Could not read uncompressed file"
|
1190
|
90 let ok = 0
|
446
|
91 else
|
1190
|
92 let ok = 1
|
|
93 " delete the compressed lines; remember the line number
|
|
94 let l = line("'[") - 1
|
|
95 if exists(":lockmarks")
|
|
96 lockmarks '[,']d _
|
|
97 else
|
|
98 '[,']d _
|
|
99 endif
|
|
100 " read in the uncompressed lines "'[-1r tmp"
|
|
101 " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options.
|
|
102 setlocal nobin
|
|
103 if exists(":lockmarks")
|
|
104 if empty
|
1592
|
105 execute "silent lockmarks " . l . "r ++edit " . tmp_esc
|
1190
|
106 else
|
1592
|
107 execute "silent lockmarks " . l . "r " . tmp_esc
|
1190
|
108 endif
|
|
109 else
|
1592
|
110 execute "silent " . l . "r " . tmp_esc
|
1190
|
111 endif
|
|
112
|
|
113 " if buffer became empty, delete trailing blank line
|
819
|
114 if empty
|
1190
|
115 silent $delete _
|
|
116 1
|
819
|
117 endif
|
1190
|
118 " delete the temp file and the used buffers
|
|
119 call delete(tmp)
|
1592
|
120 silent! exe "bwipe " . tmp_esc
|
|
121 silent! exe "bwipe " . tmpe_esc
|
446
|
122 endif
|
6336
|
123 " Store the OK flag, so that we can use it when writing.
|
|
124 let b:uncompressOk = ok
|
446
|
125
|
1190
|
126 " Restore saved option values.
|
446
|
127 let &pm = pm_save
|
|
128 let &cpo = cpo_save
|
|
129 let &l:ma = ma_save
|
1190
|
130 if has("folding")
|
|
131 let &l:fen = fen_save
|
|
132 endif
|
|
133
|
446
|
134 " When uncompressed the whole buffer, do autocommands
|
1190
|
135 if ok && empty
|
1592
|
136 if exists('*fnameescape')
|
|
137 let fname = fnameescape(expand("%:r"))
|
|
138 else
|
|
139 let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
|
|
140 endif
|
446
|
141 if &verbose >= 8
|
1592
|
142 execute "doau BufReadPost " . fname
|
446
|
143 else
|
1592
|
144 execute "silent! doau BufReadPost " . fname
|
446
|
145 endif
|
|
146 endif
|
|
147 endfun
|
|
148
|
|
149 " After writing compressed file: Compress written file with "cmd"
|
|
150 fun gzip#write(cmd)
|
6336
|
151 if exists('b:uncompressOk') && !b:uncompressOk
|
|
152 echomsg "Not compressing file because uncompress failed; reset b:uncompressOk to compress anyway"
|
446
|
153 " don't do anything if the cmd is not supported
|
6336
|
154 elseif s:check(a:cmd)
|
446
|
155 " Rename the file before compressing it.
|
|
156 let nm = resolve(expand("<afile>"))
|
|
157 let nmt = s:tempname(nm)
|
|
158 if rename(nm, nmt) == 0
|
|
159 if exists("b:gzip_comp_arg")
|
1668
|
160 call system(a:cmd . " " . b:gzip_comp_arg . " -- " . s:escape(nmt))
|
446
|
161 else
|
1668
|
162 call system(a:cmd . " -- " . s:escape(nmt))
|
446
|
163 endif
|
|
164 call rename(nmt . "." . expand("<afile>:e"), nm)
|
|
165 endif
|
|
166 endif
|
|
167 endfun
|
|
168
|
|
169 " Before appending to compressed file: Uncompress file with "cmd"
|
|
170 fun gzip#appre(cmd)
|
|
171 " don't do anything if the cmd is not supported
|
|
172 if s:check(a:cmd)
|
|
173 let nm = expand("<afile>")
|
|
174
|
|
175 " for gzip check current compression level and set b:gzip_comp_arg.
|
|
176 silent! unlet b:gzip_comp_arg
|
|
177 if a:cmd[0] == 'g'
|
|
178 call s:set_compression(readfile(nm, "b", 1)[0])
|
|
179 endif
|
|
180
|
|
181 " Rename to a weird name to avoid the risk of overwriting another file
|
|
182 let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
|
|
183 let nmte = nmt . "." . expand("<afile>:e")
|
|
184 if rename(nm, nmte) == 0
|
|
185 if &patchmode != "" && getfsize(nm . &patchmode) == -1
|
|
186 " Create patchmode file by creating the decompressed file new
|
1668
|
187 call system(a:cmd . " -c -- " . s:escape(nmte) . " > " . s:escape(nmt))
|
446
|
188 call rename(nmte, nm . &patchmode)
|
|
189 else
|
1668
|
190 call system(a:cmd . " -- " . s:escape(nmte))
|
446
|
191 endif
|
|
192 call rename(nmt, nm)
|
|
193 endif
|
|
194 endif
|
|
195 endfun
|
|
196
|
|
197 " find a file name for the file to be compressed. Use "name" without an
|
|
198 " extension if possible. Otherwise use a weird name to avoid overwriting an
|
|
199 " existing file.
|
|
200 fun s:tempname(name)
|
|
201 let fn = fnamemodify(a:name, ":r")
|
|
202 if !filereadable(fn) && !isdirectory(fn)
|
|
203 return fn
|
|
204 endif
|
|
205 return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
|
|
206 endfun
|
|
207
|
985
|
208 fun s:escape(name)
|
|
209 " shellescape() was added by patch 7.0.111
|
1132
|
210 if exists("*shellescape")
|
985
|
211 return shellescape(a:name)
|
|
212 endif
|
|
213 return "'" . a:name . "'"
|
|
214 endfun
|
|
215
|
446
|
216 " vim: set sw=2 :
|