(insert-for-yank-1): If last inserted char has properties,
[emacs.git] / lisp / jka-cmpr-hook.el
blob12941e962a061beb9f77fb0d4696f8b56d12b975
1 ;;; jka-cmpr-hook.el --- preloaded code to enable jka-compr.el
3 ;; Copyright (C) 1993, 1994, 1995, 1997, 1999, 2000, 2002, 2003,
4 ;; 2004, 2005, 2006 Free Software Foundation, Inc.
6 ;; Author: jka@ece.cmu.edu (Jay K. Adams)
7 ;; Maintainer: FSF
8 ;; Keywords: data
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
15 ;; any later version.
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
27 ;;; Commentary:
29 ;; This file contains the code to enable and disable Auto-Compression mode.
30 ;; It is preloaded. The guts of this mode are in jka-compr.el, which
31 ;; is loaded only when you really try to uncompress something.
33 ;;; Code:
35 (defgroup compression nil
36 "Data compression utilities."
37 :group 'data)
39 (defgroup jka-compr nil
40 "jka-compr customization."
41 :group 'compression)
43 ;; List of all the elements we actually added to file-coding-system-alist.
44 (defvar jka-compr-added-to-file-coding-system-alist nil)
46 (defvar jka-compr-file-name-handler-entry
47 nil
48 "`file-name-handler-alist' entry used by jka-compr I/O functions.")
50 ;; Compiler defvars. These three variables will be defined later with
51 ;; `defcustom' when everything used in the :set functions is defined.
52 (defvar jka-compr-compression-info-list)
53 (defvar jka-compr-mode-alist-additions)
54 (defvar jka-compr-load-suffixes)
56 (defvar jka-compr-compression-info-list--internal nil
57 "Stored value of `jka-compr-compression-info-list'.
58 If Auto Compression mode is enabled, this is the value of
59 `jka-compr-compression-info-list' when `jka-compr-install' was last called.
60 Otherwise, it is nil.")
62 (defvar jka-compr-mode-alist-additions--internal nil
63 "Stored value of `jka-compr-mode-alist-additions'.
64 If Auto Compression mode is enabled, this is the value of
65 `jka-compr-mode-alist-additions' when `jka-compr-install' was last called.
66 Otherwise, it is nil.")
68 (defvar jka-compr-load-suffixes--internal nil
69 "Stored value of `jka-compr-load-suffixes'.
70 If Auto Compression mode is enabled, this is the value of
71 `jka-compr-load-suffixes' when `jka-compr-install' was last called.
72 Otherwise, it is nil.")
75 (defun jka-compr-build-file-regexp ()
76 (mapconcat
77 'jka-compr-info-regexp
78 jka-compr-compression-info-list
79 "\\|"))
81 ;; Functions for accessing the return value of jka-compr-get-compression-info
82 (defun jka-compr-info-regexp (info) (aref info 0))
83 (defun jka-compr-info-compress-message (info) (aref info 1))
84 (defun jka-compr-info-compress-program (info) (aref info 2))
85 (defun jka-compr-info-compress-args (info) (aref info 3))
86 (defun jka-compr-info-uncompress-message (info) (aref info 4))
87 (defun jka-compr-info-uncompress-program (info) (aref info 5))
88 (defun jka-compr-info-uncompress-args (info) (aref info 6))
89 (defun jka-compr-info-can-append (info) (aref info 7))
90 (defun jka-compr-info-strip-extension (info) (aref info 8))
91 (defun jka-compr-info-file-magic-bytes (info) (aref info 9))
94 (defun jka-compr-get-compression-info (filename)
95 "Return information about the compression scheme of FILENAME.
96 The determination as to which compression scheme, if any, to use is
97 based on the filename itself and `jka-compr-compression-info-list'."
98 (catch 'compression-info
99 (let ((case-fold-search nil))
100 (mapcar
101 (function (lambda (x)
102 (and (string-match (jka-compr-info-regexp x) filename)
103 (throw 'compression-info x))))
104 jka-compr-compression-info-list)
105 nil)))
107 (defun jka-compr-install ()
108 "Install jka-compr.
109 This adds entries to `file-name-handler-alist' and `auto-mode-alist'
110 and `inhibit-first-line-modes-suffixes'."
112 (setq jka-compr-file-name-handler-entry
113 (cons (jka-compr-build-file-regexp) 'jka-compr-handler))
115 (push jka-compr-file-name-handler-entry file-name-handler-alist)
117 (setq jka-compr-compression-info-list--internal
118 jka-compr-compression-info-list
119 jka-compr-mode-alist-additions--internal
120 jka-compr-mode-alist-additions
121 jka-compr-load-suffixes--internal
122 jka-compr-load-suffixes)
124 (dolist (x jka-compr-compression-info-list)
125 ;; Don't do multibyte encoding on the compressed files.
126 (let ((elt (cons (jka-compr-info-regexp x)
127 '(no-conversion . no-conversion))))
128 (push elt file-coding-system-alist)
129 (push elt jka-compr-added-to-file-coding-system-alist))
131 (and (jka-compr-info-strip-extension x)
132 ;; Make entries in auto-mode-alist so that modes
133 ;; are chosen right according to the file names
134 ;; sans `.gz'.
135 (push (list (jka-compr-info-regexp x) nil 'jka-compr) auto-mode-alist)
136 ;; Also add these regexps to
137 ;; inhibit-first-line-modes-suffixes, so that a
138 ;; -*- line in the first file of a compressed tar
139 ;; file doesn't override tar-mode.
140 (push (jka-compr-info-regexp x)
141 inhibit-first-line-modes-suffixes)))
142 (setq auto-mode-alist
143 (append auto-mode-alist jka-compr-mode-alist-additions))
145 ;; Make sure that (load "foo") will find /bla/foo.el.gz.
146 (setq load-file-rep-suffixes
147 (append load-file-rep-suffixes jka-compr-load-suffixes nil)))
149 (defun jka-compr-installed-p ()
150 "Return non-nil if jka-compr is installed.
151 The return value is the entry in `file-name-handler-alist' for jka-compr."
153 (let ((fnha file-name-handler-alist)
154 (installed nil))
156 (while (and fnha (not installed))
157 (and (eq (cdr (car fnha)) 'jka-compr-handler)
158 (setq installed (car fnha)))
159 (setq fnha (cdr fnha)))
161 installed))
163 (defun jka-compr-update ()
164 "Update Auto Compression mode for changes in option values.
165 If you change the options `jka-compr-compression-info-list',
166 `jka-compr-mode-alist-additions' or `jka-compr-load-suffixes'
167 outside Custom, while Auto Compression mode is already enabled
168 \(as it is by default), then you have to call this function
169 afterward to properly update other variables. Setting these
170 options through Custom does this automatically."
171 (when (jka-compr-installed-p)
172 (jka-compr-uninstall)
173 (jka-compr-install)))
175 (defun jka-compr-set (variable value)
176 "Internal Custom :set function."
177 (set-default variable value)
178 (jka-compr-update))
180 ;; I have this defined so that .Z files are assumed to be in unix
181 ;; compress format; and .gz files, in gzip format, and .bz2 files in bzip fmt.
182 (defcustom jka-compr-compression-info-list
183 ;;[regexp
184 ;; compr-message compr-prog compr-args
185 ;; uncomp-message uncomp-prog uncomp-args
186 ;; can-append auto-mode-flag strip-extension-flag file-magic-bytes]
187 '(["\\.Z\\(~\\|\\.~[0-9]+~\\)?\\'"
188 "compressing" "compress" ("-c")
189 "uncompressing" "uncompress" ("-c")
190 nil t "\037\235"]
191 ;; Formerly, these had an additional arg "-c", but that fails with
192 ;; "Version 0.1pl2, 29-Aug-97." (RedHat 5.1 GNU/Linux) and
193 ;; "Version 0.9.0b, 9-Sept-98".
194 ["\\.bz2\\'"
195 "bzip2ing" "bzip2" nil
196 "bunzip2ing" "bzip2" ("-d")
197 nil t "BZh"]
198 ["\\.tbz\\'"
199 "bzip2ing" "bzip2" nil
200 "bunzip2ing" "bzip2" ("-d")
201 nil nil "BZh"]
202 ["\\.tgz\\'"
203 "compressing" "gzip" ("-c" "-q")
204 "uncompressing" "gzip" ("-c" "-q" "-d")
205 t nil "\037\213"]
206 ["\\.g?z\\(~\\|\\.~[0-9]+~\\)?\\'"
207 "compressing" "gzip" ("-c" "-q")
208 "uncompressing" "gzip" ("-c" "-q" "-d")
209 t t "\037\213"]
210 ;; dzip is gzip with random access. Its compression program can't
211 ;; read/write stdin/out, so .dz files can only be viewed without
212 ;; saving, having their contents decompressed with gzip.
213 ["\\.dz\\'"
214 nil nil nil
215 "uncompressing" "gzip" ("-c" "-q" "-d")
216 nil t "\037\213"])
218 "List of vectors that describe available compression techniques.
219 Each element, which describes a compression technique, is a vector of
220 the form [REGEXP COMPRESS-MSG COMPRESS-PROGRAM COMPRESS-ARGS
221 UNCOMPRESS-MSG UNCOMPRESS-PROGRAM UNCOMPRESS-ARGS
222 APPEND-FLAG STRIP-EXTENSION-FLAG FILE-MAGIC-CHARS], where:
224 regexp is a regexp that matches filenames that are
225 compressed with this format
227 compress-msg is the message to issue to the user when doing this
228 type of compression (nil means no message)
230 compress-program is a program that performs this compression
231 (nil means visit file in read-only mode)
233 compress-args is a list of args to pass to the compress program
235 uncompress-msg is the message to issue to the user when doing this
236 type of uncompression (nil means no message)
238 uncompress-program is a program that performs this compression
240 uncompress-args is a list of args to pass to the uncompress program
242 append-flag is non-nil if this compression technique can be
243 appended
245 strip-extension-flag non-nil means strip the regexp from file names
246 before attempting to set the mode.
248 file-magic-chars is a string of characters that you would find
249 at the beginning of a file compressed in this way.
251 Because of the way `call-process' is defined, discarding the stderr output of
252 a program adds the overhead of starting a shell each time the program is
253 invoked.
255 If you set this outside Custom while Auto Compression mode is
256 already enabled \(as it is by default), you have to call
257 `jka-compr-update' after setting it to properly update other
258 variables. Setting this through Custom does that automatically."
259 :type '(repeat (vector regexp
260 (choice :tag "Compress Message"
261 (string :format "%v")
262 (const :tag "No Message" nil))
263 (choice :tag "Compress Program"
264 (string)
265 (const :tag "None" nil))
266 (repeat :tag "Compress Arguments" string)
267 (choice :tag "Uncompress Message"
268 (string :format "%v")
269 (const :tag "No Message" nil))
270 (choice :tag "Uncompress Program"
271 (string)
272 (const :tag "None" nil))
273 (repeat :tag "Uncompress Arguments" string)
274 (boolean :tag "Append")
275 (boolean :tag "Strip Extension")
276 (string :tag "Magic Bytes")))
277 :set 'jka-compr-set
278 :group 'jka-compr)
280 (defcustom jka-compr-mode-alist-additions
281 (list (cons "\\.tgz\\'" 'tar-mode) (cons "\\.tbz\\'" 'tar-mode))
282 "List of pairs added to `auto-mode-alist' when installing jka-compr.
283 Uninstalling jka-compr removes all pairs from `auto-mode-alist' that
284 installing added.
286 If you set this outside Custom while Auto Compression mode is
287 already enabled \(as it is by default), you have to call
288 `jka-compr-update' after setting it to properly update other
289 variables. Setting this through Custom does that automatically."
290 :type '(repeat (cons string symbol))
291 :set 'jka-compr-set
292 :group 'jka-compr)
294 (defcustom jka-compr-load-suffixes '(".gz")
295 "List of compression related suffixes to try when loading files.
296 Enabling Auto Compression mode appends this list to `load-file-rep-suffixes',
297 which see. Disabling Auto Compression mode removes all suffixes
298 from `load-file-rep-suffixes' that enabling added.
300 If you set this outside Custom while Auto Compression mode is
301 already enabled \(as it is by default), you have to call
302 `jka-compr-update' after setting it to properly update other
303 variables. Setting this through Custom does that automatically."
304 :type '(repeat string)
305 :set 'jka-compr-set
306 :group 'jka-compr)
308 (define-minor-mode auto-compression-mode
309 "Toggle automatic file compression and uncompression.
310 With prefix argument ARG, turn auto compression on if positive, else off.
311 Return the new status of auto compression (non-nil means on)."
312 :global t :init-value t :group 'jka-compr :version "22.1"
313 (let* ((installed (jka-compr-installed-p))
314 (flag auto-compression-mode))
315 (cond
316 ((and flag installed) t) ; already installed
317 ((and (not flag) (not installed)) nil) ; already not installed
318 (flag (jka-compr-install))
319 (t (jka-compr-uninstall)))))
321 (defmacro with-auto-compression-mode (&rest body)
322 "Evalute BODY with automatic file compression and uncompression enabled."
323 (let ((already-installed (make-symbol "already-installed")))
324 `(let ((,already-installed (jka-compr-installed-p)))
325 (unwind-protect
326 (progn
327 (unless ,already-installed
328 (jka-compr-install))
329 ,@body)
330 (unless ,already-installed
331 (jka-compr-uninstall))))))
332 (put 'with-auto-compression-mode 'lisp-indent-function 0)
335 ;; This is what we need to know about jka-compr-handler
336 ;; in order to decide when to call it.
338 (put 'jka-compr-handler 'safe-magic t)
339 (put 'jka-compr-handler 'operations '(byte-compiler-base-file-name
340 write-region insert-file-contents
341 file-local-copy load))
343 ;; Turn on the mode.
344 (when auto-compression-mode (auto-compression-mode 1))
346 (provide 'jka-cmpr-hook)
348 ;; arch-tag: 4bd73429-f400-45fe-a065-270a113e31a8
349 ;;; jka-cmpr-hook.el ends here