1*87e25fdfSBram Moolenaar" Vim autoload file for editing compressed files. 2*87e25fdfSBram Moolenaar" Maintainer: Bram Moolenaar <[email protected]> 3*87e25fdfSBram Moolenaar" Last Change: 2005 Jul 26 4*87e25fdfSBram Moolenaar 5*87e25fdfSBram Moolenaar" These functions are used by the gzip plugin. 6*87e25fdfSBram Moolenaar 7*87e25fdfSBram Moolenaar" Function to check that executing "cmd [-f]" works. 8*87e25fdfSBram Moolenaar" The result is cached in s:have_"cmd" for speed. 9*87e25fdfSBram Moolenaarfun s:check(cmd) 10*87e25fdfSBram Moolenaar let name = substitute(a:cmd, '\(\S*\).*', '\1', '') 11*87e25fdfSBram Moolenaar if !exists("s:have_" . name) 12*87e25fdfSBram Moolenaar let e = executable(name) 13*87e25fdfSBram Moolenaar if e < 0 14*87e25fdfSBram Moolenaar let r = system(name . " --version") 15*87e25fdfSBram Moolenaar let e = (r !~ "not found" && r != "") 16*87e25fdfSBram Moolenaar endif 17*87e25fdfSBram Moolenaar exe "let s:have_" . name . "=" . e 18*87e25fdfSBram Moolenaar endif 19*87e25fdfSBram Moolenaar exe "return s:have_" . name 20*87e25fdfSBram Moolenaarendfun 21*87e25fdfSBram Moolenaar 22*87e25fdfSBram Moolenaar" Set b:gzip_comp_arg to the gzip argument to be used for compression, based on 23*87e25fdfSBram Moolenaar" the flags in the compressed file. 24*87e25fdfSBram Moolenaar" The only compression methods that can be detected are max speed (-1) and max 25*87e25fdfSBram Moolenaar" compression (-9). 26*87e25fdfSBram Moolenaarfun s:set_compression(line) 27*87e25fdfSBram Moolenaar " get the Compression Method 28*87e25fdfSBram Moolenaar let l:cm = char2nr(a:line[2]) 29*87e25fdfSBram Moolenaar " if it's 8 (DEFLATE), we can check for the compression level 30*87e25fdfSBram Moolenaar if l:cm == 8 31*87e25fdfSBram Moolenaar " get the eXtra FLags 32*87e25fdfSBram Moolenaar let l:xfl = char2nr(a:line[8]) 33*87e25fdfSBram Moolenaar " max compression 34*87e25fdfSBram Moolenaar if l:xfl == 2 35*87e25fdfSBram Moolenaar let b:gzip_comp_arg = "-9" 36*87e25fdfSBram Moolenaar " min compression 37*87e25fdfSBram Moolenaar elseif l:xfl == 4 38*87e25fdfSBram Moolenaar let b:gzip_comp_arg = "-1" 39*87e25fdfSBram Moolenaar endif 40*87e25fdfSBram Moolenaar endif 41*87e25fdfSBram Moolenaarendfun 42*87e25fdfSBram Moolenaar 43*87e25fdfSBram Moolenaar 44*87e25fdfSBram Moolenaar" After reading compressed file: Uncompress text in buffer with "cmd" 45*87e25fdfSBram Moolenaarfun gzip#read(cmd) 46*87e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 47*87e25fdfSBram Moolenaar if !s:check(a:cmd) 48*87e25fdfSBram Moolenaar return 49*87e25fdfSBram Moolenaar endif 50*87e25fdfSBram Moolenaar 51*87e25fdfSBram Moolenaar " for gzip check current compression level and set b:gzip_comp_arg. 52*87e25fdfSBram Moolenaar silent! unlet b:gzip_comp_arg 53*87e25fdfSBram Moolenaar if a:cmd[0] == 'g' 54*87e25fdfSBram Moolenaar call s:set_compression(getline(1)) 55*87e25fdfSBram Moolenaar endif 56*87e25fdfSBram Moolenaar 57*87e25fdfSBram Moolenaar " make 'patchmode' empty, we don't want a copy of the written file 58*87e25fdfSBram Moolenaar let pm_save = &pm 59*87e25fdfSBram Moolenaar set pm= 60*87e25fdfSBram Moolenaar " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes 61*87e25fdfSBram Moolenaar let cpo_save = &cpo 62*87e25fdfSBram Moolenaar set cpo-=a cpo-=A 63*87e25fdfSBram Moolenaar " set 'modifiable' 64*87e25fdfSBram Moolenaar let ma_save = &ma 65*87e25fdfSBram Moolenaar setlocal ma 66*87e25fdfSBram Moolenaar " when filtering the whole buffer, it will become empty 67*87e25fdfSBram Moolenaar let empty = line("'[") == 1 && line("']") == line("$") 68*87e25fdfSBram Moolenaar let tmp = tempname() 69*87e25fdfSBram Moolenaar let tmpe = tmp . "." . expand("<afile>:e") 70*87e25fdfSBram Moolenaar " write the just read lines to a temp file "'[,']w tmp.gz" 71*87e25fdfSBram Moolenaar execute "silent '[,']w " . tmpe 72*87e25fdfSBram Moolenaar " uncompress the temp file: call system("gzip -dn tmp.gz") 73*87e25fdfSBram Moolenaar call system(a:cmd . " " . tmpe) 74*87e25fdfSBram Moolenaar if !filereadable(tmp) 75*87e25fdfSBram Moolenaar " uncompress didn't work! Keep the compressed file then. 76*87e25fdfSBram Moolenaar echoerr "Error: Could not read uncompressed file" 77*87e25fdfSBram Moolenaar return 78*87e25fdfSBram Moolenaar endif 79*87e25fdfSBram Moolenaar " delete the compressed lines; remember the line number 80*87e25fdfSBram Moolenaar let l = line("'[") - 1 81*87e25fdfSBram Moolenaar if exists(":lockmarks") 82*87e25fdfSBram Moolenaar lockmarks '[,']d _ 83*87e25fdfSBram Moolenaar else 84*87e25fdfSBram Moolenaar '[,']d _ 85*87e25fdfSBram Moolenaar endif 86*87e25fdfSBram Moolenaar " read in the uncompressed lines "'[-1r tmp" 87*87e25fdfSBram Moolenaar setlocal nobin 88*87e25fdfSBram Moolenaar if exists(":lockmarks") 89*87e25fdfSBram Moolenaar execute "silent lockmarks " . l . "r " . tmp 90*87e25fdfSBram Moolenaar else 91*87e25fdfSBram Moolenaar execute "silent " . l . "r " . tmp 92*87e25fdfSBram Moolenaar endif 93*87e25fdfSBram Moolenaar 94*87e25fdfSBram Moolenaar " if buffer became empty, delete trailing blank line 95*87e25fdfSBram Moolenaar if empty 96*87e25fdfSBram Moolenaar silent $delete _ 97*87e25fdfSBram Moolenaar 1 98*87e25fdfSBram Moolenaar endif 99*87e25fdfSBram Moolenaar " delete the temp file and the used buffers 100*87e25fdfSBram Moolenaar call delete(tmp) 101*87e25fdfSBram Moolenaar silent! exe "bwipe " . tmp 102*87e25fdfSBram Moolenaar silent! exe "bwipe " . tmpe 103*87e25fdfSBram Moolenaar let &pm = pm_save 104*87e25fdfSBram Moolenaar let &cpo = cpo_save 105*87e25fdfSBram Moolenaar let &l:ma = ma_save 106*87e25fdfSBram Moolenaar " When uncompressed the whole buffer, do autocommands 107*87e25fdfSBram Moolenaar if empty 108*87e25fdfSBram Moolenaar if &verbose >= 8 109*87e25fdfSBram Moolenaar execute "doau BufReadPost " . expand("%:r") 110*87e25fdfSBram Moolenaar else 111*87e25fdfSBram Moolenaar execute "silent! doau BufReadPost " . expand("%:r") 112*87e25fdfSBram Moolenaar endif 113*87e25fdfSBram Moolenaar endif 114*87e25fdfSBram Moolenaarendfun 115*87e25fdfSBram Moolenaar 116*87e25fdfSBram Moolenaar" After writing compressed file: Compress written file with "cmd" 117*87e25fdfSBram Moolenaarfun gzip#write(cmd) 118*87e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 119*87e25fdfSBram Moolenaar if s:check(a:cmd) 120*87e25fdfSBram Moolenaar " Rename the file before compressing it. 121*87e25fdfSBram Moolenaar let nm = resolve(expand("<afile>")) 122*87e25fdfSBram Moolenaar let nmt = s:tempname(nm) 123*87e25fdfSBram Moolenaar if rename(nm, nmt) == 0 124*87e25fdfSBram Moolenaar if exists("b:gzip_comp_arg") 125*87e25fdfSBram Moolenaar call system(a:cmd . " " . b:gzip_comp_arg . " " . nmt) 126*87e25fdfSBram Moolenaar else 127*87e25fdfSBram Moolenaar call system(a:cmd . " " . nmt) 128*87e25fdfSBram Moolenaar endif 129*87e25fdfSBram Moolenaar call rename(nmt . "." . expand("<afile>:e"), nm) 130*87e25fdfSBram Moolenaar endif 131*87e25fdfSBram Moolenaar endif 132*87e25fdfSBram Moolenaarendfun 133*87e25fdfSBram Moolenaar 134*87e25fdfSBram Moolenaar" Before appending to compressed file: Uncompress file with "cmd" 135*87e25fdfSBram Moolenaarfun gzip#appre(cmd) 136*87e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 137*87e25fdfSBram Moolenaar if s:check(a:cmd) 138*87e25fdfSBram Moolenaar let nm = expand("<afile>") 139*87e25fdfSBram Moolenaar 140*87e25fdfSBram Moolenaar " for gzip check current compression level and set b:gzip_comp_arg. 141*87e25fdfSBram Moolenaar silent! unlet b:gzip_comp_arg 142*87e25fdfSBram Moolenaar if a:cmd[0] == 'g' 143*87e25fdfSBram Moolenaar call s:set_compression(readfile(nm, "b", 1)[0]) 144*87e25fdfSBram Moolenaar endif 145*87e25fdfSBram Moolenaar 146*87e25fdfSBram Moolenaar " Rename to a weird name to avoid the risk of overwriting another file 147*87e25fdfSBram Moolenaar let nmt = expand("<afile>:p:h") . "/X~=@l9q5" 148*87e25fdfSBram Moolenaar let nmte = nmt . "." . expand("<afile>:e") 149*87e25fdfSBram Moolenaar if rename(nm, nmte) == 0 150*87e25fdfSBram Moolenaar if &patchmode != "" && getfsize(nm . &patchmode) == -1 151*87e25fdfSBram Moolenaar " Create patchmode file by creating the decompressed file new 152*87e25fdfSBram Moolenaar call system(a:cmd . " -c " . nmte . " > " . nmt) 153*87e25fdfSBram Moolenaar call rename(nmte, nm . &patchmode) 154*87e25fdfSBram Moolenaar else 155*87e25fdfSBram Moolenaar call system(a:cmd . " " . nmte) 156*87e25fdfSBram Moolenaar endif 157*87e25fdfSBram Moolenaar call rename(nmt, nm) 158*87e25fdfSBram Moolenaar endif 159*87e25fdfSBram Moolenaar endif 160*87e25fdfSBram Moolenaarendfun 161*87e25fdfSBram Moolenaar 162*87e25fdfSBram Moolenaar" find a file name for the file to be compressed. Use "name" without an 163*87e25fdfSBram Moolenaar" extension if possible. Otherwise use a weird name to avoid overwriting an 164*87e25fdfSBram Moolenaar" existing file. 165*87e25fdfSBram Moolenaarfun s:tempname(name) 166*87e25fdfSBram Moolenaar let fn = fnamemodify(a:name, ":r") 167*87e25fdfSBram Moolenaar if !filereadable(fn) && !isdirectory(fn) 168*87e25fdfSBram Moolenaar return fn 169*87e25fdfSBram Moolenaar endif 170*87e25fdfSBram Moolenaar return fnamemodify(a:name, ":p:h") . "/X~=@l9q5" 171*87e25fdfSBram Moolenaarendfun 172*87e25fdfSBram Moolenaar 173*87e25fdfSBram Moolenaar" vim: set sw=2 : 174