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