187e25fdfSBram Moolenaar" Vim autoload file for editing compressed files. 287e25fdfSBram Moolenaar" Maintainer: Bram Moolenaar <[email protected]> 3*60a495f0SBram Moolenaar" Last Change: 2006 Oct 03 487e25fdfSBram Moolenaar 587e25fdfSBram Moolenaar" These functions are used by the gzip plugin. 687e25fdfSBram Moolenaar 787e25fdfSBram Moolenaar" Function to check that executing "cmd [-f]" works. 887e25fdfSBram Moolenaar" The result is cached in s:have_"cmd" for speed. 987e25fdfSBram Moolenaarfun s:check(cmd) 1087e25fdfSBram Moolenaar let name = substitute(a:cmd, '\(\S*\).*', '\1', '') 1187e25fdfSBram Moolenaar if !exists("s:have_" . name) 1287e25fdfSBram Moolenaar let e = executable(name) 1387e25fdfSBram Moolenaar if e < 0 1487e25fdfSBram Moolenaar let r = system(name . " --version") 1587e25fdfSBram Moolenaar let e = (r !~ "not found" && r != "") 1687e25fdfSBram Moolenaar endif 1787e25fdfSBram Moolenaar exe "let s:have_" . name . "=" . e 1887e25fdfSBram Moolenaar endif 1987e25fdfSBram Moolenaar exe "return s:have_" . name 2087e25fdfSBram Moolenaarendfun 2187e25fdfSBram Moolenaar 2287e25fdfSBram Moolenaar" Set b:gzip_comp_arg to the gzip argument to be used for compression, based on 2387e25fdfSBram Moolenaar" the flags in the compressed file. 2487e25fdfSBram Moolenaar" The only compression methods that can be detected are max speed (-1) and max 2587e25fdfSBram Moolenaar" compression (-9). 2687e25fdfSBram Moolenaarfun s:set_compression(line) 2787e25fdfSBram Moolenaar " get the Compression Method 2887e25fdfSBram Moolenaar let l:cm = char2nr(a:line[2]) 2987e25fdfSBram Moolenaar " if it's 8 (DEFLATE), we can check for the compression level 3087e25fdfSBram Moolenaar if l:cm == 8 3187e25fdfSBram Moolenaar " get the eXtra FLags 3287e25fdfSBram Moolenaar let l:xfl = char2nr(a:line[8]) 3387e25fdfSBram Moolenaar " max compression 3487e25fdfSBram Moolenaar if l:xfl == 2 3587e25fdfSBram Moolenaar let b:gzip_comp_arg = "-9" 3687e25fdfSBram Moolenaar " min compression 3787e25fdfSBram Moolenaar elseif l:xfl == 4 3887e25fdfSBram Moolenaar let b:gzip_comp_arg = "-1" 3987e25fdfSBram Moolenaar endif 4087e25fdfSBram Moolenaar endif 4187e25fdfSBram Moolenaarendfun 4287e25fdfSBram Moolenaar 4387e25fdfSBram Moolenaar 4487e25fdfSBram Moolenaar" After reading compressed file: Uncompress text in buffer with "cmd" 4587e25fdfSBram Moolenaarfun gzip#read(cmd) 4687e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 4787e25fdfSBram Moolenaar if !s:check(a:cmd) 4887e25fdfSBram Moolenaar return 4987e25fdfSBram Moolenaar endif 5087e25fdfSBram Moolenaar 5187e25fdfSBram Moolenaar " for gzip check current compression level and set b:gzip_comp_arg. 5287e25fdfSBram Moolenaar silent! unlet b:gzip_comp_arg 5387e25fdfSBram Moolenaar if a:cmd[0] == 'g' 5487e25fdfSBram Moolenaar call s:set_compression(getline(1)) 5587e25fdfSBram Moolenaar endif 5687e25fdfSBram Moolenaar 5787e25fdfSBram Moolenaar " make 'patchmode' empty, we don't want a copy of the written file 5887e25fdfSBram Moolenaar let pm_save = &pm 5987e25fdfSBram Moolenaar set pm= 6087e25fdfSBram Moolenaar " remove 'a' and 'A' from 'cpo' to avoid the alternate file changes 6187e25fdfSBram Moolenaar let cpo_save = &cpo 6287e25fdfSBram Moolenaar set cpo-=a cpo-=A 6387e25fdfSBram Moolenaar " set 'modifiable' 6487e25fdfSBram Moolenaar let ma_save = &ma 6587e25fdfSBram Moolenaar setlocal ma 6687e25fdfSBram Moolenaar " when filtering the whole buffer, it will become empty 6787e25fdfSBram Moolenaar let empty = line("'[") == 1 && line("']") == line("$") 6887e25fdfSBram Moolenaar let tmp = tempname() 6987e25fdfSBram Moolenaar let tmpe = tmp . "." . expand("<afile>:e") 7087e25fdfSBram Moolenaar " write the just read lines to a temp file "'[,']w tmp.gz" 71*60a495f0SBram Moolenaar execute "silent '[,']w " . escape(tmpe, ' ') 7287e25fdfSBram Moolenaar " uncompress the temp file: call system("gzip -dn tmp.gz") 73*60a495f0SBram Moolenaar call system(a:cmd . " " . s:escape(tmpe)) 7487e25fdfSBram Moolenaar if !filereadable(tmp) 7587e25fdfSBram Moolenaar " uncompress didn't work! Keep the compressed file then. 7687e25fdfSBram Moolenaar echoerr "Error: Could not read uncompressed file" 7787e25fdfSBram Moolenaar return 7887e25fdfSBram Moolenaar endif 7987e25fdfSBram Moolenaar " delete the compressed lines; remember the line number 8087e25fdfSBram Moolenaar let l = line("'[") - 1 8187e25fdfSBram Moolenaar if exists(":lockmarks") 8287e25fdfSBram Moolenaar lockmarks '[,']d _ 8387e25fdfSBram Moolenaar else 8487e25fdfSBram Moolenaar '[,']d _ 8587e25fdfSBram Moolenaar endif 8687e25fdfSBram Moolenaar " read in the uncompressed lines "'[-1r tmp" 87910f66f9SBram Moolenaar " Use ++edit if the buffer was empty, keep the 'ff' and 'fenc' options. 8887e25fdfSBram Moolenaar setlocal nobin 8987e25fdfSBram Moolenaar if exists(":lockmarks") 90910f66f9SBram Moolenaar if empty 91910f66f9SBram Moolenaar execute "silent lockmarks " . l . "r ++edit " . tmp 92910f66f9SBram Moolenaar else 9387e25fdfSBram Moolenaar execute "silent lockmarks " . l . "r " . tmp 94910f66f9SBram Moolenaar endif 9587e25fdfSBram Moolenaar else 9687e25fdfSBram Moolenaar execute "silent " . l . "r " . tmp 9787e25fdfSBram Moolenaar endif 9887e25fdfSBram Moolenaar 9987e25fdfSBram Moolenaar " if buffer became empty, delete trailing blank line 10087e25fdfSBram Moolenaar if empty 10187e25fdfSBram Moolenaar silent $delete _ 10287e25fdfSBram Moolenaar 1 10387e25fdfSBram Moolenaar endif 10487e25fdfSBram Moolenaar " delete the temp file and the used buffers 10587e25fdfSBram Moolenaar call delete(tmp) 10687e25fdfSBram Moolenaar silent! exe "bwipe " . tmp 10787e25fdfSBram Moolenaar silent! exe "bwipe " . tmpe 10887e25fdfSBram Moolenaar let &pm = pm_save 10987e25fdfSBram Moolenaar let &cpo = cpo_save 11087e25fdfSBram Moolenaar let &l:ma = ma_save 11187e25fdfSBram Moolenaar " When uncompressed the whole buffer, do autocommands 11287e25fdfSBram Moolenaar if empty 11387e25fdfSBram Moolenaar if &verbose >= 8 11487e25fdfSBram Moolenaar execute "doau BufReadPost " . expand("%:r") 11587e25fdfSBram Moolenaar else 11687e25fdfSBram Moolenaar execute "silent! doau BufReadPost " . expand("%:r") 11787e25fdfSBram Moolenaar endif 11887e25fdfSBram Moolenaar endif 11987e25fdfSBram Moolenaarendfun 12087e25fdfSBram Moolenaar 12187e25fdfSBram Moolenaar" After writing compressed file: Compress written file with "cmd" 12287e25fdfSBram Moolenaarfun gzip#write(cmd) 12387e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 12487e25fdfSBram Moolenaar if s:check(a:cmd) 12587e25fdfSBram Moolenaar " Rename the file before compressing it. 12687e25fdfSBram Moolenaar let nm = resolve(expand("<afile>")) 12787e25fdfSBram Moolenaar let nmt = s:tempname(nm) 12887e25fdfSBram Moolenaar if rename(nm, nmt) == 0 12987e25fdfSBram Moolenaar if exists("b:gzip_comp_arg") 130*60a495f0SBram Moolenaar call system(a:cmd . " " . b:gzip_comp_arg . " " . s:escape(nmt)) 13187e25fdfSBram Moolenaar else 132*60a495f0SBram Moolenaar call system(a:cmd . " " . s:escape(nmt)) 13387e25fdfSBram Moolenaar endif 13487e25fdfSBram Moolenaar call rename(nmt . "." . expand("<afile>:e"), nm) 13587e25fdfSBram Moolenaar endif 13687e25fdfSBram Moolenaar endif 13787e25fdfSBram Moolenaarendfun 13887e25fdfSBram Moolenaar 13987e25fdfSBram Moolenaar" Before appending to compressed file: Uncompress file with "cmd" 14087e25fdfSBram Moolenaarfun gzip#appre(cmd) 14187e25fdfSBram Moolenaar " don't do anything if the cmd is not supported 14287e25fdfSBram Moolenaar if s:check(a:cmd) 14387e25fdfSBram Moolenaar let nm = expand("<afile>") 14487e25fdfSBram Moolenaar 14587e25fdfSBram Moolenaar " for gzip check current compression level and set b:gzip_comp_arg. 14687e25fdfSBram Moolenaar silent! unlet b:gzip_comp_arg 14787e25fdfSBram Moolenaar if a:cmd[0] == 'g' 14887e25fdfSBram Moolenaar call s:set_compression(readfile(nm, "b", 1)[0]) 14987e25fdfSBram Moolenaar endif 15087e25fdfSBram Moolenaar 15187e25fdfSBram Moolenaar " Rename to a weird name to avoid the risk of overwriting another file 15287e25fdfSBram Moolenaar let nmt = expand("<afile>:p:h") . "/X~=@l9q5" 15387e25fdfSBram Moolenaar let nmte = nmt . "." . expand("<afile>:e") 15487e25fdfSBram Moolenaar if rename(nm, nmte) == 0 15587e25fdfSBram Moolenaar if &patchmode != "" && getfsize(nm . &patchmode) == -1 15687e25fdfSBram Moolenaar " Create patchmode file by creating the decompressed file new 157*60a495f0SBram Moolenaar call system(a:cmd . " -c " . s:escape(nmte) . " > " . s:escape(nmt)) 15887e25fdfSBram Moolenaar call rename(nmte, nm . &patchmode) 15987e25fdfSBram Moolenaar else 160*60a495f0SBram Moolenaar call system(a:cmd . " " . s:escape(nmte)) 16187e25fdfSBram Moolenaar endif 16287e25fdfSBram Moolenaar call rename(nmt, nm) 16387e25fdfSBram Moolenaar endif 16487e25fdfSBram Moolenaar endif 16587e25fdfSBram Moolenaarendfun 16687e25fdfSBram Moolenaar 16787e25fdfSBram Moolenaar" find a file name for the file to be compressed. Use "name" without an 16887e25fdfSBram Moolenaar" extension if possible. Otherwise use a weird name to avoid overwriting an 16987e25fdfSBram Moolenaar" existing file. 17087e25fdfSBram Moolenaarfun s:tempname(name) 17187e25fdfSBram Moolenaar let fn = fnamemodify(a:name, ":r") 17287e25fdfSBram Moolenaar if !filereadable(fn) && !isdirectory(fn) 17387e25fdfSBram Moolenaar return fn 17487e25fdfSBram Moolenaar endif 17587e25fdfSBram Moolenaar return fnamemodify(a:name, ":p:h") . "/X~=@l9q5" 17687e25fdfSBram Moolenaarendfun 17787e25fdfSBram Moolenaar 178*60a495f0SBram Moolenaarfun s:escape(name) 179*60a495f0SBram Moolenaar " shellescape() was added by patch 7.0.111 180*60a495f0SBram Moolenaar if v:version > 700 || (v:version == 700 && has('patch111')) 181*60a495f0SBram Moolenaar return shellescape(a:name) 182*60a495f0SBram Moolenaar endif 183*60a495f0SBram Moolenaar return "'" . a:name . "'" 184*60a495f0SBram Moolenaarendfun 185*60a495f0SBram Moolenaar 18687e25fdfSBram Moolenaar" vim: set sw=2 : 187