blob: f7c97a6d433210a6a9060f7786493e02b9fb177b [file] [log] [blame]
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00001" Vim autoload file for editing compressed files.
2" Maintainer: Bram Moolenaar <Bram@vim.org>
Bram Moolenaarc1762cc2007-05-10 16:56:30 +00003" Last Change: 2007 May 10
Bram Moolenaar87e25fd2005-07-27 21:13:01 +00004
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.
9fun 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
20endfun
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).
26fun 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
41endfun
42
43
44" After reading compressed file: Uncompress text in buffer with "cmd"
45fun 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
Bram Moolenaarc1762cc2007-05-10 16:56:30 +000066 " Reset 'foldenable', otherwise line numbers get adjusted.
67 if has("folding")
68 let fen_save = &fen
69 setlocal nofen
70 endif
71
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000072 " 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")
76 " write the just read lines to a temp file "'[,']w tmp.gz"
Bram Moolenaar60a495f2006-10-03 12:44:42 +000077 execute "silent '[,']w " . escape(tmpe, ' ')
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000078 " uncompress the temp file: call system("gzip -dn tmp.gz")
Bram Moolenaar60a495f2006-10-03 12:44:42 +000079 call system(a:cmd . " " . s:escape(tmpe))
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000080 if !filereadable(tmp)
81 " uncompress didn't work! Keep the compressed file then.
82 echoerr "Error: Could not read uncompressed file"
Bram Moolenaarc1762cc2007-05-10 16:56:30 +000083 let ok = 0
Bram Moolenaar87e25fd2005-07-27 21:13:01 +000084 else
Bram Moolenaarc1762cc2007-05-10 16:56:30 +000085 let ok = 1
86 " delete the compressed lines; remember the line number
87 let l = line("'[") - 1
88 if exists(":lockmarks")
89 lockmarks '[,']d _
Bram Moolenaar910f66f2006-04-05 20:41:53 +000090 else
Bram Moolenaarc1762cc2007-05-10 16:56:30 +000091 '[,']d _
Bram Moolenaar910f66f2006-04-05 20:41:53 +000092 endif
Bram Moolenaarc1762cc2007-05-10 16:56:30 +000093 " read in the uncompressed lines "'[-1r tmp"
94 " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options.
95 setlocal nobin
96 if exists(":lockmarks")
97 if empty
98 execute "silent lockmarks " . l . "r ++edit " . tmp
99 else
100 execute "silent lockmarks " . l . "r " . tmp
101 endif
102 else
103 execute "silent " . l . "r " . tmp
104 endif
105
106 " if buffer became empty, delete trailing blank line
107 if empty
108 silent $delete _
109 1
110 endif
111 " delete the temp file and the used buffers
112 call delete(tmp)
113 silent! exe "bwipe " . tmp
114 silent! exe "bwipe " . tmpe
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000115 endif
116
Bram Moolenaarc1762cc2007-05-10 16:56:30 +0000117 " Restore saved option values.
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000118 let &pm = pm_save
119 let &cpo = cpo_save
120 let &l:ma = ma_save
Bram Moolenaarc1762cc2007-05-10 16:56:30 +0000121 if has("folding")
122 let &l:fen = fen_save
123 endif
124
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000125 " When uncompressed the whole buffer, do autocommands
Bram Moolenaarc1762cc2007-05-10 16:56:30 +0000126 if ok && empty
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000127 if &verbose >= 8
128 execute "doau BufReadPost " . expand("%:r")
129 else
130 execute "silent! doau BufReadPost " . expand("%:r")
131 endif
132 endif
133endfun
134
135" After writing compressed file: Compress written file with "cmd"
136fun gzip#write(cmd)
137 " don't do anything if the cmd is not supported
138 if s:check(a:cmd)
139 " Rename the file before compressing it.
140 let nm = resolve(expand("<afile>"))
141 let nmt = s:tempname(nm)
142 if rename(nm, nmt) == 0
143 if exists("b:gzip_comp_arg")
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000144 call system(a:cmd . " " . b:gzip_comp_arg . " " . s:escape(nmt))
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000145 else
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000146 call system(a:cmd . " " . s:escape(nmt))
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000147 endif
148 call rename(nmt . "." . expand("<afile>:e"), nm)
149 endif
150 endif
151endfun
152
153" Before appending to compressed file: Uncompress file with "cmd"
154fun gzip#appre(cmd)
155 " don't do anything if the cmd is not supported
156 if s:check(a:cmd)
157 let nm = expand("<afile>")
158
159 " for gzip check current compression level and set b:gzip_comp_arg.
160 silent! unlet b:gzip_comp_arg
161 if a:cmd[0] == 'g'
162 call s:set_compression(readfile(nm, "b", 1)[0])
163 endif
164
165 " Rename to a weird name to avoid the risk of overwriting another file
166 let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
167 let nmte = nmt . "." . expand("<afile>:e")
168 if rename(nm, nmte) == 0
169 if &patchmode != "" && getfsize(nm . &patchmode) == -1
170 " Create patchmode file by creating the decompressed file new
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000171 call system(a:cmd . " -c " . s:escape(nmte) . " > " . s:escape(nmt))
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000172 call rename(nmte, nm . &patchmode)
173 else
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000174 call system(a:cmd . " " . s:escape(nmte))
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000175 endif
176 call rename(nmt, nm)
177 endif
178 endif
179endfun
180
181" find a file name for the file to be compressed. Use "name" without an
182" extension if possible. Otherwise use a weird name to avoid overwriting an
183" existing file.
184fun s:tempname(name)
185 let fn = fnamemodify(a:name, ":r")
186 if !filereadable(fn) && !isdirectory(fn)
187 return fn
188 endif
189 return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
190endfun
191
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000192fun s:escape(name)
193 " shellescape() was added by patch 7.0.111
Bram Moolenaar5c5b0942007-05-06 12:07:59 +0000194 if exists("*shellescape")
Bram Moolenaar60a495f2006-10-03 12:44:42 +0000195 return shellescape(a:name)
196 endif
197 return "'" . a:name . "'"
198endfun
199
Bram Moolenaar87e25fd2005-07-27 21:13:01 +0000200" vim: set sw=2 :