blob: 39b0cbc36f2d2ca87b9d7e472b941ebb435e6e83 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim plugin for editing compressed files.
2" Maintainer: Bram Moolenaar <Bram@vim.org>
3" Last Change: 2004 Jan 12
4
5" Exit quickly when:
6" - this plugin was already loaded
7" - when 'compatible' is set
8" - some autocommands are already taking care of compressed files
9if exists("loaded_gzip") || &cp || exists("#BufReadPre#*.gz")
10 finish
11endif
12let loaded_gzip = 1
13
14augroup gzip
15 " Remove all gzip autocommands
16 au!
17
18 " Enable editing of gzipped files
19 " set binary mode before reading the file
20 " use "gzip -d", gunzip isn't always available
21 autocmd BufReadPre,FileReadPre *.gz,*.bz2,*.Z setlocal bin
22 autocmd BufReadPost,FileReadPost *.gz call s:read("gzip -dn")
23 autocmd BufReadPost,FileReadPost *.bz2 call s:read("bzip2 -d")
24 autocmd BufReadPost,FileReadPost *.Z call s:read("uncompress")
25 autocmd BufWritePost,FileWritePost *.gz call s:write("gzip")
26 autocmd BufWritePost,FileWritePost *.bz2 call s:write("bzip2")
27 autocmd BufWritePost,FileWritePost *.Z call s:write("compress -f")
28 autocmd FileAppendPre *.gz call s:appre("gzip -dn")
29 autocmd FileAppendPre *.bz2 call s:appre("bzip2 -d")
30 autocmd FileAppendPre *.Z call s:appre("uncompress")
31 autocmd FileAppendPost *.gz call s:write("gzip")
32 autocmd FileAppendPost *.bz2 call s:write("bzip2")
33 autocmd FileAppendPost *.Z call s:write("compress -f")
34augroup END
35
36" Function to check that executing "cmd [-f]" works.
37" The result is cached in s:have_"cmd" for speed.
38fun s:check(cmd)
39 let name = substitute(a:cmd, '\(\S*\).*', '\1', '')
40 if !exists("s:have_" . name)
41 let e = executable(name)
42 if e < 0
43 let r = system(name . " --version")
44 let e = (r !~ "not found" && r != "")
45 endif
46 exe "let s:have_" . name . "=" . e
47 endif
48 exe "return s:have_" . name
49endfun
50
51" After reading compressed file: Uncompress text in buffer with "cmd"
52fun s:read(cmd)
53 " don't do anything if the cmd is not supported
54 if !s:check(a:cmd)
55 return
56 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 " when filtering the whole buffer, it will become empty
67 let empty = line("'[") == 1 && line("']") == line("$")
68 let tmp = tempname()
69 let tmpe = tmp . "." . expand("<afile>:e")
70 " write the just read lines to a temp file "'[,']w tmp.gz"
71 execute "silent '[,']w " . tmpe
72 " uncompress the temp file: call system("gzip -dn tmp.gz")
73 call system(a:cmd . " " . tmpe)
74 " delete the compressed lines; remember the line number
75 let l = line("'[") - 1
76 if exists(":lockmarks")
77 lockmarks '[,']d _
78 else
79 '[,']d _
80 endif
81 " read in the uncompressed lines "'[-1r tmp"
82 setlocal nobin
83 if exists(":lockmarks")
84 execute "silent lockmarks " . l . "r " . tmp
85 else
86 execute "silent " . l . "r " . tmp
87 endif
88
89 " if buffer became empty, delete trailing blank line
90 if empty
91 silent $delete _
92 1
93 endif
94 " delete the temp file and the used buffers
95 call delete(tmp)
96 silent! exe "bwipe " . tmp
97 silent! exe "bwipe " . tmpe
98 let &pm = pm_save
99 let &cpo = cpo_save
100 let &l:ma = ma_save
101 " When uncompressed the whole buffer, do autocommands
102 if empty
103 if &verbose >= 8
104 execute "doau BufReadPost " . expand("%:r")
105 else
106 execute "silent! doau BufReadPost " . expand("%:r")
107 endif
108 endif
109endfun
110
111" After writing compressed file: Compress written file with "cmd"
112fun s:write(cmd)
113 " don't do anything if the cmd is not supported
114 if s:check(a:cmd)
115 " Rename the file before compressing it.
116 let nm = expand("<afile>")
117 let nmt = s:tempname(nm)
118 if rename(nm, nmt) == 0
119 call system(a:cmd . " " . nmt)
120 call rename(nmt . "." . expand("<afile>:e"), nm)
121 endif
122 endif
123endfun
124
125" Before appending to compressed file: Uncompress file with "cmd"
126fun s:appre(cmd)
127 " don't do anything if the cmd is not supported
128 if s:check(a:cmd)
129 " Rename to a weird name to avoid the risk of overwriting another file
130 let nm = expand("<afile>")
131 let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
132 let nmte = nmt . "." . expand("<afile>:e")
133 if rename(nm, nmte) == 0
134 if &patchmode != "" && getfsize(nm . &patchmode) == -1
135 " Create patchmode file by creating the decompressed file new
136 call system(a:cmd . " -c " . nmte . " > " . nmt)
137 call rename(nmte, nm . &patchmode)
138 else
139 call system(a:cmd . " " . nmte)
140 endif
141 call rename(nmt, nm)
142 endif
143 endif
144endfun
145
146" find a file name for the file to be compressed. Use "name" without an
147" extension if possible. Otherwise use a weird name to avoid overwriting an
148" existing file.
149fun s:tempname(name)
150 let fn = fnamemodify(a:name, ":r")
151 if !filereadable(fn) && !isdirectory(fn)
152 return fn
153 endif
154 return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
155endfun
156
157" vim: set sw=2 :