xref: /vim-8.2.3635/runtime/plugin/gzip.vim (revision dfccaf0f)
1" Vim plugin for editing compressed files.
2" Maintainer: Bram Moolenaar <[email protected]>
3" Last Change: 2004 Jul 30
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  if !filereadable(tmp)
75    " uncompress didn't work!  Keep the compressed file then.
76    echoerr "Error: Could not read uncompressed file"
77    return
78  endif
79  " delete the compressed lines; remember the line number
80  let l = line("'[") - 1
81  if exists(":lockmarks")
82    lockmarks '[,']d _
83  else
84    '[,']d _
85  endif
86  " read in the uncompressed lines "'[-1r tmp"
87  setlocal nobin
88  if exists(":lockmarks")
89    execute "silent lockmarks " . l . "r " . tmp
90  else
91    execute "silent " . l . "r " . tmp
92  endif
93
94  " if buffer became empty, delete trailing blank line
95  if empty
96    silent $delete _
97    1
98  endif
99  " delete the temp file and the used buffers
100  call delete(tmp)
101  silent! exe "bwipe " . tmp
102  silent! exe "bwipe " . tmpe
103  let &pm = pm_save
104  let &cpo = cpo_save
105  let &l:ma = ma_save
106  " When uncompressed the whole buffer, do autocommands
107  if empty
108    if &verbose >= 8
109      execute "doau BufReadPost " . expand("%:r")
110    else
111      execute "silent! doau BufReadPost " . expand("%:r")
112    endif
113  endif
114endfun
115
116" After writing compressed file: Compress written file with "cmd"
117fun s:write(cmd)
118  " don't do anything if the cmd is not supported
119  if s:check(a:cmd)
120    " Rename the file before compressing it.
121    let nm = expand("<afile>")
122    let nmt = s:tempname(nm)
123    if rename(nm, nmt) == 0
124      call system(a:cmd . " " . nmt)
125      call rename(nmt . "." . expand("<afile>:e"), nm)
126    endif
127  endif
128endfun
129
130" Before appending to compressed file: Uncompress file with "cmd"
131fun s:appre(cmd)
132  " don't do anything if the cmd is not supported
133  if s:check(a:cmd)
134    " Rename to a weird name to avoid the risk of overwriting another file
135    let nm = expand("<afile>")
136    let nmt = expand("<afile>:p:h") . "/X~=@l9q5"
137    let nmte = nmt . "." . expand("<afile>:e")
138    if rename(nm, nmte) == 0
139      if &patchmode != "" && getfsize(nm . &patchmode) == -1
140	" Create patchmode file by creating the decompressed file new
141	call system(a:cmd . " -c " . nmte . " > " . nmt)
142	call rename(nmte, nm . &patchmode)
143      else
144	call system(a:cmd . " " . nmte)
145      endif
146      call rename(nmt, nm)
147    endif
148  endif
149endfun
150
151" find a file name for the file to be compressed.  Use "name" without an
152" extension if possible.  Otherwise use a weird name to avoid overwriting an
153" existing file.
154fun s:tempname(name)
155  let fn = fnamemodify(a:name, ":r")
156  if !filereadable(fn) && !isdirectory(fn)
157    return fn
158  endif
159  return fnamemodify(a:name, ":p:h") . "/X~=@l9q5"
160endfun
161
162" vim: set sw=2 :
163