remove sigio blocking
[bpt/emacs.git] / lisp / jka-cmpr-hook.el
CommitLineData
550bd514 1;;; jka-cmpr-hook.el --- preloaded code to enable jka-compr.el
216b5993 2
fc23fe2d
GM
3;; Copyright (C) 1993-1995, 1997, 1999-2000, 2002-2014
4;; Free Software Foundation, Inc.
216b5993 5
fc23fe2d 6;; Author: Jay K. Adams <jka@ece.cmu.edu>
34dc21db 7;; Maintainer: emacs-devel@gnu.org
216b5993 8;; Keywords: data
bd78fa1d 9;; Package: emacs
216b5993
RS
10
11;; This file is part of GNU Emacs.
12
eb3fa2cf 13;; GNU Emacs is free software: you can redistribute it and/or modify
216b5993 14;; it under the terms of the GNU General Public License as published by
eb3fa2cf
GM
15;; the Free Software Foundation, either version 3 of the License, or
16;; (at your option) any later version.
216b5993
RS
17
18;; GNU Emacs is distributed in the hope that it will be useful,
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
22
23;; You should have received a copy of the GNU General Public License
eb3fa2cf 24;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
216b5993
RS
25
26;;; Commentary:
27
ea8e0537 28;; This file contains the code to enable and disable Auto-Compression mode.
216b5993
RS
29;; It is preloaded. The guts of this mode are in jka-compr.el, which
30;; is loaded only when you really try to uncompress something.
31
32;;; Code:
33
34(defgroup compression nil
7ae4587b 35 "Data compression utilities."
216b5993
RS
36 :group 'data)
37
38(defgroup jka-compr nil
7ae4587b 39 "jka-compr customization."
216b5993 40 :group 'compression)
c65bca65
GM
41
42(defcustom jka-compr-verbose t
43 "If non-nil, output messages whenever compressing or uncompressing files."
44 :version "24.1"
45 :type 'boolean
46 :group 'jka-compr)
216b5993 47
216b5993
RS
48;; List of all the elements we actually added to file-coding-system-alist.
49(defvar jka-compr-added-to-file-coding-system-alist nil)
50
51(defvar jka-compr-file-name-handler-entry
52 nil
ea8e0537
LT
53 "`file-name-handler-alist' entry used by jka-compr I/O functions.")
54
55;; Compiler defvars. These three variables will be defined later with
56;; `defcustom' when everything used in the :set functions is defined.
57(defvar jka-compr-compression-info-list)
58(defvar jka-compr-mode-alist-additions)
59(defvar jka-compr-load-suffixes)
60
61(defvar jka-compr-compression-info-list--internal nil
62 "Stored value of `jka-compr-compression-info-list'.
63If Auto Compression mode is enabled, this is the value of
64`jka-compr-compression-info-list' when `jka-compr-install' was last called.
65Otherwise, it is nil.")
66
67(defvar jka-compr-mode-alist-additions--internal nil
68 "Stored value of `jka-compr-mode-alist-additions'.
69If Auto Compression mode is enabled, this is the value of
70`jka-compr-mode-alist-additions' when `jka-compr-install' was last called.
71Otherwise, it is nil.")
72
73(defvar jka-compr-load-suffixes--internal nil
74 "Stored value of `jka-compr-load-suffixes'.
75If Auto Compression mode is enabled, this is the value of
76`jka-compr-load-suffixes' when `jka-compr-install' was last called.
77Otherwise, it is nil.")
78
216b5993
RS
79\f
80(defun jka-compr-build-file-regexp ()
6d341a2a 81 (purecopy
33cf0fb2
SM
82 (let ((re-anchored '())
83 (re-free '()))
84 (dolist (e jka-compr-compression-info-list)
85 (let ((re (jka-compr-info-regexp e)))
86 (if (string-match "\\\\'\\'" re)
87 (push (substring re 0 (match-beginning 0)) re-anchored)
88 (push re re-free))))
89 (concat
90 (if re-free (concat (mapconcat 'identity re-free "\\|") "\\|"))
91 "\\(?:"
92 (mapconcat 'identity re-anchored "\\|")
93 "\\)" file-name-version-regexp "?\\'"))))
216b5993 94
be93a2c4 95;; Functions for accessing the return value of jka-compr-get-compression-info
216b5993
RS
96(defun jka-compr-info-regexp (info) (aref info 0))
97(defun jka-compr-info-compress-message (info) (aref info 1))
98(defun jka-compr-info-compress-program (info) (aref info 2))
99(defun jka-compr-info-compress-args (info) (aref info 3))
100(defun jka-compr-info-uncompress-message (info) (aref info 4))
101(defun jka-compr-info-uncompress-program (info) (aref info 5))
102(defun jka-compr-info-uncompress-args (info) (aref info 6))
103(defun jka-compr-info-can-append (info) (aref info 7))
104(defun jka-compr-info-strip-extension (info) (aref info 8))
105(defun jka-compr-info-file-magic-bytes (info) (aref info 9))
106
107
108(defun jka-compr-get-compression-info (filename)
109 "Return information about the compression scheme of FILENAME.
110The determination as to which compression scheme, if any, to use is
111based on the filename itself and `jka-compr-compression-info-list'."
6247eff5 112 (setq filename (file-name-sans-versions filename))
216b5993
RS
113 (catch 'compression-info
114 (let ((case-fold-search nil))
33cf0fb2
SM
115 (dolist (x jka-compr-compression-info-list)
116 (and (string-match (jka-compr-info-regexp x) filename)
117 (throw 'compression-info x)))
216b5993
RS
118 nil)))
119
120(defun jka-compr-install ()
121 "Install jka-compr.
122This adds entries to `file-name-handler-alist' and `auto-mode-alist'
7b447e9b 123and `inhibit-local-variables-suffixes'."
216b5993
RS
124
125 (setq jka-compr-file-name-handler-entry
126 (cons (jka-compr-build-file-regexp) 'jka-compr-handler))
127
be93a2c4
SM
128 (push jka-compr-file-name-handler-entry file-name-handler-alist)
129
ea8e0537
LT
130 (setq jka-compr-compression-info-list--internal
131 jka-compr-compression-info-list
132 jka-compr-mode-alist-additions--internal
133 jka-compr-mode-alist-additions
134 jka-compr-load-suffixes--internal
135 jka-compr-load-suffixes)
136
be93a2c4
SM
137 (dolist (x jka-compr-compression-info-list)
138 ;; Don't do multibyte encoding on the compressed files.
139 (let ((elt (cons (jka-compr-info-regexp x)
140 '(no-conversion . no-conversion))))
141 (push elt file-coding-system-alist)
142 (push elt jka-compr-added-to-file-coding-system-alist))
143
144 (and (jka-compr-info-strip-extension x)
145 ;; Make entries in auto-mode-alist so that modes
146 ;; are chosen right according to the file names
147 ;; sans `.gz'.
148 (push (list (jka-compr-info-regexp x) nil 'jka-compr) auto-mode-alist)
7b447e9b
GM
149 ;; Also add these regexps to inhibit-local-variables-suffixes,
150 ;; so that a -*- line in the first file of a compressed tar file,
151 ;; or a Local Variables section in a member file at the end of
152 ;; the tar file don't override tar-mode.
be93a2c4 153 (push (jka-compr-info-regexp x)
7b447e9b 154 inhibit-local-variables-suffixes)))
216b5993
RS
155 (setq auto-mode-alist
156 (append auto-mode-alist jka-compr-mode-alist-additions))
157
158 ;; Make sure that (load "foo") will find /bla/foo.el.gz.
ea8e0537
LT
159 (setq load-file-rep-suffixes
160 (append load-file-rep-suffixes jka-compr-load-suffixes nil)))
216b5993
RS
161
162(defun jka-compr-installed-p ()
163 "Return non-nil if jka-compr is installed.
164The return value is the entry in `file-name-handler-alist' for jka-compr."
165
166 (let ((fnha file-name-handler-alist)
167 (installed nil))
168
169 (while (and fnha (not installed))
170 (and (eq (cdr (car fnha)) 'jka-compr-handler)
171 (setq installed (car fnha)))
172 (setq fnha (cdr fnha)))
173
174 installed))
175
ea8e0537
LT
176(defun jka-compr-update ()
177 "Update Auto Compression mode for changes in option values.
178If you change the options `jka-compr-compression-info-list',
179`jka-compr-mode-alist-additions' or `jka-compr-load-suffixes'
180outside Custom, while Auto Compression mode is already enabled
181\(as it is by default), then you have to call this function
182afterward to properly update other variables. Setting these
183options through Custom does this automatically."
184 (when (jka-compr-installed-p)
185 (jka-compr-uninstall)
186 (jka-compr-install)))
187
188(defun jka-compr-set (variable value)
189 "Internal Custom :set function."
190 (set-default variable value)
191 (jka-compr-update))
192
df66263e
LT
193;; I have this defined so that .Z files are assumed to be in unix
194;; compress format; and .gz files, in gzip format, and .bz2 files in bzip fmt.
195(defcustom jka-compr-compression-info-list
196 ;;[regexp
197 ;; compr-message compr-prog compr-args
198 ;; uncomp-message uncomp-prog uncomp-args
5b668628 199 ;; can-append strip-extension-flag file-magic-bytes]
1e8780b1 200 (mapcar 'purecopy
33cf0fb2 201 '(["\\.Z\\'"
df66263e 202 "compressing" "compress" ("-c")
13c8188a 203 ;; gzip is more common than uncompress. It can only read, not write.
aad96659 204 "uncompressing" "gzip" ("-c" "-q" "-d")
df66263e
LT
205 nil t "\037\235"]
206 ;; Formerly, these had an additional arg "-c", but that fails with
207 ;; "Version 0.1pl2, 29-Aug-97." (RedHat 5.1 GNU/Linux) and
208 ;; "Version 0.9.0b, 9-Sept-98".
33cf0fb2 209 ["\\.bz2\\'"
df66263e
LT
210 "bzip2ing" "bzip2" nil
211 "bunzip2ing" "bzip2" ("-d")
212 nil t "BZh"]
6f34ccdf 213 ["\\.tbz2?\\'"
df66263e
LT
214 "bzip2ing" "bzip2" nil
215 "bunzip2ing" "bzip2" ("-d")
216 nil nil "BZh"]
33cf0fb2 217 ["\\.\\(?:tgz\\|svgz\\|sifz\\)\\'"
df66263e
LT
218 "compressing" "gzip" ("-c" "-q")
219 "uncompressing" "gzip" ("-c" "-q" "-d")
220 t nil "\037\213"]
33cf0fb2 221 ["\\.g?z\\'"
df66263e
LT
222 "compressing" "gzip" ("-c" "-q")
223 "uncompressing" "gzip" ("-c" "-q" "-d")
224 t t "\037\213"]
907201af
EZ
225 ["\\.lz\\'"
226 "Lzip compressing" "lzip" ("-c" "-q")
227 "Lzip uncompressing" "lzip" ("-c" "-q" "-d")
228 t t "LZIP"]
229 ["\\.lzma\\'"
230 "LZMA compressing" "lzma" ("-c" "-q" "-z")
231 "LZMA uncompressing" "lzma" ("-c" "-q" "-d")
232 t t ""]
33cf0fb2 233 ["\\.xz\\'"
13a3f374
JM
234 "XZ compressing" "xz" ("-c" "-q")
235 "XZ uncompressing" "xz" ("-c" "-q" "-d")
236 t t "\3757zXZ\0"]
3bf1099f
UM
237 ["\\.txz\\'"
238 "XZ compressing" "xz" ("-c" "-q")
239 "XZ uncompressing" "xz" ("-c" "-q" "-d")
240 t nil "\3757zXZ\0"]
df66263e
LT
241 ;; dzip is gzip with random access. Its compression program can't
242 ;; read/write stdin/out, so .dz files can only be viewed without
243 ;; saving, having their contents decompressed with gzip.
244 ["\\.dz\\'"
245 nil nil nil
246 "uncompressing" "gzip" ("-c" "-q" "-d")
1e8780b1 247 nil t "\037\213"]))
df66263e
LT
248
249 "List of vectors that describe available compression techniques.
250Each element, which describes a compression technique, is a vector of
251the form [REGEXP COMPRESS-MSG COMPRESS-PROGRAM COMPRESS-ARGS
252UNCOMPRESS-MSG UNCOMPRESS-PROGRAM UNCOMPRESS-ARGS
253APPEND-FLAG STRIP-EXTENSION-FLAG FILE-MAGIC-CHARS], where:
254
255 regexp is a regexp that matches filenames that are
256 compressed with this format
257
258 compress-msg is the message to issue to the user when doing this
259 type of compression (nil means no message)
260
261 compress-program is a program that performs this compression
262 (nil means visit file in read-only mode)
263
264 compress-args is a list of args to pass to the compress program
265
266 uncompress-msg is the message to issue to the user when doing this
267 type of uncompression (nil means no message)
268
269 uncompress-program is a program that performs this compression
270
271 uncompress-args is a list of args to pass to the uncompress program
272
273 append-flag is non-nil if this compression technique can be
274 appended
275
276 strip-extension-flag non-nil means strip the regexp from file names
277 before attempting to set the mode.
278
279 file-magic-chars is a string of characters that you would find
280 at the beginning of a file compressed in this way.
281
df66263e
LT
282If you set this outside Custom while Auto Compression mode is
283already enabled \(as it is by default), you have to call
284`jka-compr-update' after setting it to properly update other
285variables. Setting this through Custom does that automatically."
286 :type '(repeat (vector regexp
287 (choice :tag "Compress Message"
288 (string :format "%v")
289 (const :tag "No Message" nil))
290 (choice :tag "Compress Program"
291 (string)
292 (const :tag "None" nil))
293 (repeat :tag "Compress Arguments" string)
294 (choice :tag "Uncompress Message"
295 (string :format "%v")
296 (const :tag "No Message" nil))
297 (choice :tag "Uncompress Program"
298 (string)
299 (const :tag "None" nil))
300 (repeat :tag "Uncompress Arguments" string)
301 (boolean :tag "Append")
302 (boolean :tag "Strip Extension")
303 (string :tag "Magic Bytes")))
304 :set 'jka-compr-set
6247eff5 305 :version "24.1" ; removed version extension piece
df66263e
LT
306 :group 'jka-compr)
307
308(defcustom jka-compr-mode-alist-additions
3bf1099f
UM
309 (purecopy '(("\\.tgz\\'" . tar-mode)
310 ("\\.tbz2?\\'" . tar-mode)
e54eeb9b 311 ("\\.txz\\'" . tar-mode)))
df66263e
LT
312 "List of pairs added to `auto-mode-alist' when installing jka-compr.
313Uninstalling jka-compr removes all pairs from `auto-mode-alist' that
314installing added.
315
316If you set this outside Custom while Auto Compression mode is
317already enabled \(as it is by default), you have to call
318`jka-compr-update' after setting it to properly update other
319variables. Setting this through Custom does that automatically."
320 :type '(repeat (cons string symbol))
e54eeb9b 321 :version "24.4" ; add txz
df66263e
LT
322 :set 'jka-compr-set
323 :group 'jka-compr)
324
3bf1099f 325(defcustom jka-compr-load-suffixes (purecopy '(".gz"))
df66263e
LT
326 "List of compression related suffixes to try when loading files.
327Enabling Auto Compression mode appends this list to `load-file-rep-suffixes',
328which see. Disabling Auto Compression mode removes all suffixes
329from `load-file-rep-suffixes' that enabling added.
330
331If you set this outside Custom while Auto Compression mode is
332already enabled \(as it is by default), you have to call
333`jka-compr-update' after setting it to properly update other
334variables. Setting this through Custom does that automatically."
335 :type '(repeat string)
336 :set 'jka-compr-set
337 :group 'jka-compr)
338
216b5993 339(define-minor-mode auto-compression-mode
06e21633
CY
340 "Toggle Auto Compression mode.
341With a prefix argument ARG, enable Auto Compression mode if ARG
342is positive, and disable it otherwise. If called from Lisp,
343enable the mode if ARG is omitted or nil.
344
345Auto Compression mode is a global minor mode. When enabled,
346compressed files are automatically uncompressed for reading, and
347compressed when writing."
e64a3dcf 348 :global t :init-value t :group 'jka-compr :version "22.1"
216b5993
RS
349 (let* ((installed (jka-compr-installed-p))
350 (flag auto-compression-mode))
351 (cond
352 ((and flag installed) t) ; already installed
353 ((and (not flag) (not installed)) nil) ; already not installed
354 (flag (jka-compr-install))
355 (t (jka-compr-uninstall)))))
356
357(defmacro with-auto-compression-mode (&rest body)
5eba16a3 358 "Evaluate BODY with automatic file compression and uncompression enabled."
f291fe60 359 (declare (indent 0))
216b5993
RS
360 (let ((already-installed (make-symbol "already-installed")))
361 `(let ((,already-installed (jka-compr-installed-p)))
362 (unwind-protect
363 (progn
364 (unless ,already-installed
365 (jka-compr-install))
366 ,@body)
367 (unless ,already-installed
368 (jka-compr-uninstall))))))
216b5993 369
be93a2c4
SM
370;; This is what we need to know about jka-compr-handler
371;; in order to decide when to call it.
216b5993
RS
372
373(put 'jka-compr-handler 'safe-magic t)
9c40111a 374(put 'jka-compr-handler 'operations '(byte-compiler-base-file-name
216b5993
RS
375 write-region insert-file-contents
376 file-local-copy load))
377
be93a2c4 378;; Turn on the mode.
12d94429 379(when auto-compression-mode (auto-compression-mode 1))
216b5993 380
550bd514 381(provide 'jka-cmpr-hook)
216b5993 382
550bd514 383;;; jka-cmpr-hook.el ends here