home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: gnu.emacs.help
- Path: sparky!uunet!decwrl!access.usask.ca!ccu.umanitoba.ca!ccu!buhr
- From: buhr@umanitoba.ca (Kevin Andrew Buhr)
- Subject: autoZ.el -- auto (un)compress [was: Creating a *.Z file from scratch]
- In-Reply-To: ralph@laas.fr's message of 2 Sep 92 18:01:22 GMT
- Message-ID: <BUHR.92Sep5170009@ccu.umanitoba.ca>
- Followup-To: gnu.emacs.help
- Sender: news@ccu.umanitoba.ca
- Nntp-Posting-Host: ccu.umanitoba.ca
- Organization: University of Manitoba, Canada
- References: <RALPH.92Sep2200122@orion.laas.fr>
- Date: Sat, 5 Sep 1992 23:00:09 GMT
- Lines: 187
-
- In <RALPH.92Sep2200122@orion.laas.fr>, ralph@laas.fr writes:
-
- Under GNUS or VM, or even elsewhere, crypt.el works *very* nicely when
- you save to compressed files, uncompressing the data in the buffer and
- then recompressing before writing the data out!
-
- I was interested in a general purpose compressor/decompressor, too. I
- looked at "ange-crypt.el" and "zcat.el" and couldn't get them to work
- exactly the way I liked, either.
-
- I tried writing my own which recognized the two-byte magic cookie at
- the file's beginning as an indication it was compressed and then
- stored this fact in a buffer-local variable. Unfortunately, many
- modes cleared local variables, messing up the saving of these files.
-
- In the end, I settled on using a regular expression to recognize file
- *names* that indicated a file was compressed. With the default
- variable values, the code will treat files ending in ".Z" as
- compressed. When loaded, they will be uncompressed if the magic
- cookie is found at file start, and, when saved, they will be
- recompressed if the absence of the cookie indicates they haven't
- already been compressed. This scheme has the disadvantage that *all*
- files whose names end in ".Z" will be compressed when saved, whether
- they were originally compressed or not.
-
- I've tested this using compressed Rmail files and compressed GNUS
- ".newsrc" files. The only problem I have encountered is this:
- attempts to append articles to the end of compressed Rmail files on
- disk will fail; the uncompressed message will be tacked onto the end
- of the compressed file. Just don't try using compressed Rmail files
- to automatically store author copies or save outgoing mail: if you
- forget to load the appropriate Rmail buffer before a message is
- automatically saved, you'll trash the file. To save a message to a
- compressed Rmail file, run Rmail on the buffer first. Then, use a
- function that saves the article or message to the end of the *buffer*
- rather than the file. Better yet, uncompress the disk file first,
- save your articles, and then recompress it.
-
- I have also tested the code using "ange-ftp.el" to a limited extent.
- Loading compressed files works fine, though I haven't tried saving
- them.
-
- Inserting compressed files in an existing buffer does not work in the
- current version, either. You have to load the compressed file into
- another buffer and then "insert-buffer" it.
-
- This is alpha code, provided as-is, with no guarantees or warranties
- of any kind including fitness for a particular purpose. Please do not
- redistribute it in modified form. I will be releasing a cleaner
- version in the near future. That version will be governed by GNU's
- copyleft and will be redistributable subject to the terms of that
- document.
-
- Kevin Buhr <buhr@ccu.UManitoba.CA>
-
- ;;; autoZ.el
- ;;;
- ;;; Copyright (c) 1992 by Kevin Buhr
- ;;;
- ;;; This program code is provided as-is, with no guarantees or
- ;;; warranties of any kind including, but not limited to, fitness for
- ;;; any particular purpose. The author is not responsible for the
- ;;; loss of data or other damages caused by the use of this software.
- ;;; USE IT AT YOUR OWN RISK.
- ;;;
- ;;; This code incorporates modified GNU emacs lisp code, which is
- ;;; distributed under the GNU Copyleft document. The distribution of
- ;;; this software may therefore be subject to additional limitations
- ;;; or considerations outlined in that document. You are advised to
- ;;; consult that document before redistributing this program.
- ;;;
- ;;; -----
- ;;;
- ;;; "autoZ.el" provides automatic decompression and compression of
- ;;; data files from within GNU emacs. To use it, optionally byte
- ;;; compile it, and load it in your initialization file.
- ;;;
- ;;; If you find any bugs in this code or come up with a good patch to
- ;;; increase its usefulness, please e-mail the author at the following
- ;;; address:
- ;;;
- ;;; Kevin Buhr <buhr@ccu.UManitoba.CA>
-
- ;; Define variables
- (defvar autoZ-magic-cookie "\037\235"
- "*A regular expression to match the beginning of a buffer and identify
- its contents as compressed. See also autoZ-compressed-filename-regexp.")
-
- (defvar autoZ-compressed-filename-regexp ".\\.Z$"
- "*A regular expression that matches the filenames of compressed
- files. If a file has a name that is matched by this expression, autoZ
- considers it a compressed file. It will be uncompressed when read, if
- necessary, and compressed when written, if necessary.
-
- The \"if necessary\" qualification depends on the value of
- autoZ-magic-cookie.")
-
-
- ;; Function to uncompress the buffer if necessary
- (defun autoZ-uncompress-buffer-if-necessary ()
- "Uncompresses the current buffer if the autoZ-magic-cookie is
- found at the start and the filename is matched by
- autoZ-compressed-filename-regexp."
- (if (and (string-match autoZ-compressed-filename-regexp (buffer-file-name))
- (save-excursion
- (goto-char (point-min))
- (looking-at autoZ-magic-cookie)))
- (progn (message "Auto-uncompressing buffer...")
- (let ((ro buffer-read-only) (bufmod (buffer-modified-p)))
- (if ro (toggle-read-only))
- (call-process-region (point-min) (point-max) "zcat" t t nil)
- (if ro (toggle-read-only))
- (set-buffer-modified-p bufmod))
- (message "Auto-uncompressing buffer... done"))))
-
- ;; Function to recompress buffer if necessary
- (defun autoZ-compress-buffer-if-necessary ()
- "Recompress and save the current buffer if the filename matches
- autoZ-compressed-filename-regexp and the absence of the
- autoZ-magic-cookie at the beginning of the buffer indicates it has not
- already been compressed."
- (save-excursion
- (if (and (string-match autoZ-compressed-filename-regexp (buffer-file-name))
- (progn (goto-char (point-min))
- (not (looking-at autoZ-magic-cookie))))
- ;; so, remember uncompressed version and then compress and save it
- (let ((ro buffer-read-only) (saved-point-max (point-max)))
- (message "Auto-compressing buffer...")
- (if ro (toggle-read-only))
- (goto-char saved-point-max)
- (call-process-region
- (point-min) saved-point-max "compress" nil t nil "-c")
- (message "Auto-compressing buffer... done")
- ;; following code stolen from basic-save-file defun
- (if file-precious-flag
- ;; If file is precious, rename it away before
- ;; overwriting it.
- (let ((rename t) nodelete
- (file (concat buffer-file-name "#")))
- (condition-case ()
- (progn (rename-file buffer-file-name file t)
- (setq setmodes (file-modes file)))
- (file-error (setq rename nil nodelete t)))
- (unwind-protect
- (progn (clear-visited-file-modtime)
- (write-region saved-point-max (point-max)
- buffer-file-name nil t)
- (setq rename nil))
- ;; If rename is still t, writing failed.
- ;; So rename the old file back to original name,
- (if rename
- (progn
- (rename-file file buffer-file-name t)
- (clear-visited-file-modtime))
- ;; Otherwise we don't need the original file,
- ;; so flush it. Unless we already lost it.
- (or nodelete
- (condition-case ()
- (delete-file file)
- (error nil))))))
- ;; If file not writable, see if we can make it writable
- ;; temporarily while we write it.
- ;; But no need to do so if we have just backed it up
- ;; (setmodes is set) because that says we're superseding.
- (cond ((and tempsetmodes (not setmodes))
- ;; Change the mode back, after writing.
- (setq setmodes (file-modes buffer-file-name))
- (set-file-modes buffer-file-name 511)))
- (write-region saved-point-max (point-max)
- buffer-file-name nil t))
- (delete-region saved-point-max (point-max))
- (set-buffer-modified-p nil)
- (setq buffer-read-only ro)
- t)
- ;; otherwise, we didn't save anything
- nil)))
-
- ;; Add functions to appropriate hooks
- (or (memq 'autoZ-uncompress-buffer-if-necessary find-file-hooks)
- (setq find-file-hooks
- (append find-file-hooks
- (list 'autoZ-uncompress-buffer-if-necessary))))
-
- (or (memq 'autoZ-compress-buffer-if-necessary write-file-hooks)
- (setq write-file-hooks
- (append write-file-hooks
- (list 'autoZ-compress-buffer-if-necessary))))
-