Merge branch 'vim-with-runtime' into feat/lua
[vim_extended.git] / runtime / autoload / gzip.vim
blob1245fdddc9ce3e580a2278a3641aa93fd2caa20d
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.
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
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
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
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
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
66   " Reset 'foldenable', otherwise line numbers get adjusted.
67   if has("folding")
68     let fen_save = &fen
69     setlocal nofen
70   endif
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")
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
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))
87   if !filereadable(tmp)
88     " uncompress didn't work!  Keep the compressed file then.
89     echoerr "Error: Could not read uncompressed file"
90     let ok = 0
91   else
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
105         execute "silent lockmarks " . l . "r ++edit " . tmp_esc
106       else
107         execute "silent lockmarks " . l . "r " . tmp_esc
108       endif
109     else
110       execute "silent " . l . "r " . tmp_esc
111     endif
113     " if buffer became empty, delete trailing blank line
114     if empty
115       silent $delete _
116       1
117     endif
118     " delete the temp file and the used buffers
119     call delete(tmp)
120     silent! exe "bwipe " . tmp_esc
121     silent! exe "bwipe " . tmpe_esc
122   endif
124   " Restore saved option values.
125   let &pm = pm_save
126   let &cpo = cpo_save
127   let &l:ma = ma_save
128   if has("folding")
129     let &l:fen = fen_save
130   endif
132   " When uncompressed the whole buffer, do autocommands
133   if ok && empty
134     if exists('*fnameescape')
135       let fname = fnameescape(expand("%:r"))
136     else
137       let fname = escape(expand("%:r"), " \t\n*?[{`$\\%#'\"|!<")
138     endif
139     if &verbose >= 8
140       execute "doau BufReadPost " . fname
141     else
142       execute "silent! doau BufReadPost " . fname
143     endif
144   endif
145 endfun
147 " After writing compressed file: Compress written file with "cmd"
148 fun gzip#write(cmd)
149   " don't do anything if the cmd is not supported
150   if s:check(a:cmd)
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))
157       else
158         call system(a:cmd . " -- " . s:escape(nmt))
159       endif
160       call rename(nmt . "." . expand("<afile>:e"), nm)
161     endif
162   endif
163 endfun
165 " Before appending to compressed file: Uncompress file with "cmd"
166 fun gzip#appre(cmd)
167   " don't do anything if the cmd is not supported
168   if s:check(a:cmd)
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
173     if a:cmd[0] == 'g'
174       call s:set_compression(readfile(nm, "b", 1)[0])
175     endif
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)
185       else
186         call system(a:cmd . " -- " . s:escape(nmte))
187       endif
188       call rename(nmt, nm)
189     endif
190   endif
191 endfun
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
195 " existing file.
196 fun s:tempname(name)
197   let fn = fnamemodify(a:name, ":r")
198   if !filereadable(fn) && !isdirectory(fn)
199     return fn
200   endif
201   return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
202 endfun
204 fun s:escape(name)
205   " shellescape() was added by patch 7.0.111
206   if exists("*shellescape")
207     return shellescape(a:name)
208   endif
209   return "'" . a:name . "'"
210 endfun
212 " vim: set sw=2 :