1" Vim plugin for editing compressed files. 2" Maintainer: Bram Moolenaar <[email protected]> 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 : 158