aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Love1999-01-23 21:52:40 +0000
committerDave Love1999-01-23 21:52:40 +0000
commit823139fba4f440369de17bfb725ec333b7bfdded (patch)
treeaddc7070bad80b13956d9716ac4c40bc75b521e9
parenta0184aeb8f58ec6249e1d15bfb272fea00bab2d1 (diff)
downloademacs-823139fba4f440369de17bfb725ec333b7bfdded.tar.gz
emacs-823139fba4f440369de17bfb725ec333b7bfdded.zip
Doc fixes.
(format-encode-run-method): Have things happen in the right buffer. Deal with errors from method. Set coding-system-for-write. (format-decode-run-method): Have things happen in the right buffer. Deal with errors from method. Set coding-system-for-read. (format-alist): Use nil instead of unmatchable regexps.
-rw-r--r--lisp/format.el251
1 files changed, 140 insertions, 111 deletions
diff --git a/lisp/format.el b/lisp/format.el
index 33200a3546c..3bfe556364e 100644
--- a/lisp/format.el
+++ b/lisp/format.el
@@ -1,8 +1,8 @@
1;;; format.el --- read and save files in multiple formats 1;;; format.el --- read and save files in multiple formats
2 2
3;; Copyright (c) 1994, 1995, 1997 Free Software Foundation 3;; Copyright (c) 1994, 1995, 1997, 1999 Free Software Foundation
4 4
5;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu> 5;; Author: Boris Goldowsky <boris@gnu.org>
6 6
7;; This file is part of GNU Emacs. 7;; This file is part of GNU Emacs.
8 8
@@ -26,7 +26,7 @@
26;; This file defines a unified mechanism for saving & loading files stored 26;; This file defines a unified mechanism for saving & loading files stored
27;; in different formats. `format-alist' contains information that directs 27;; in different formats. `format-alist' contains information that directs
28;; Emacs to call an encoding or decoding function when reading or writing 28;; Emacs to call an encoding or decoding function when reading or writing
29;; files that match certain conditions. 29;; files that match certain conditions.
30;; 30;;
31;; When a file is visited, its format is determined by matching the 31;; When a file is visited, its format is determined by matching the
32;; beginning of the file against regular expressions stored in 32;; beginning of the file against regular expressions stored in
@@ -45,7 +45,7 @@
45;; You can manually translate a buffer into or out of a particular format 45;; You can manually translate a buffer into or out of a particular format
46;; with the functions `format-encode-buffer' and `format-decode-buffer'. 46;; with the functions `format-encode-buffer' and `format-decode-buffer'.
47;; To translate just the region use the functions `format-encode-region' 47;; To translate just the region use the functions `format-encode-region'
48;; and `format-decode-region'. 48;; and `format-decode-region'.
49;; 49;;
50;; You can define a new format by writing the encoding and decoding 50;; You can define a new format by writing the encoding and decoding
51;; functions, and adding an entry to `format-alist'. See enriched.el for 51;; functions, and adding an entry to `format-alist'. See enriched.el for
@@ -63,7 +63,7 @@
63 63
64(put 'buffer-file-format 'permanent-local t) 64(put 'buffer-file-format 'permanent-local t)
65 65
66(defvar format-alist 66(defvar format-alist
67 '((text/enriched "Extended MIME text/enriched format." 67 '((text/enriched "Extended MIME text/enriched format."
68 "Content-[Tt]ype:[ \t]*text/enriched" 68 "Content-[Tt]ype:[ \t]*text/enriched"
69 enriched-decode enriched-encode t enriched-mode) 69 enriched-decode enriched-encode t enriched-mode)
@@ -71,38 +71,38 @@
71 ;; Plain only exists so that there is an obvious neutral choice in 71 ;; Plain only exists so that there is an obvious neutral choice in
72 ;; the completion list. 72 ;; the completion list.
73 nil nil nil nil nil) 73 nil nil nil nil nil)
74 (ibm "IBM Code Page 850 (DOS)" 74 (ibm "IBM Code Page 850 (DOS)"
75 "1\\(^\\)" 75 nil ; The original "1\\(^\\)" is obscure.
76 "recode -f ibm-pc:latin1" "recode -f latin1:ibm-pc" t nil) 76 "recode -f ibm-pc:latin1" "recode -f latin1:ibm-pc" t nil)
77 (mac "Apple Macintosh" 77 (mac "Apple Macintosh"
78 "1\\(^\\)" 78 nil
79 "recode -f mac:latin1" "recode -f latin1:mac" t nil) 79 "recode -f mac:latin1" "recode -f latin1:mac" t nil)
80 (hp "HP Roman8" 80 (hp "HP Roman8"
81 "1\\(^\\)" 81 nil
82 "recode -f roman8:latin1" "recode -f latin1:roman8" t nil) 82 "recode -f roman8:latin1" "recode -f latin1:roman8" t nil)
83 (TeX "TeX (encoding)" 83 (TeX "TeX (encoding)"
84 "1\\(^\\)" 84 nil
85 iso-tex2iso iso-iso2tex t nil) 85 iso-tex2iso iso-iso2tex t nil)
86 (gtex "German TeX (encoding)" 86 (gtex "German TeX (encoding)"
87 "1\\(^\\)" 87 nil
88 iso-gtex2iso iso-iso2gtex t nil) 88 iso-gtex2iso iso-iso2gtex t nil)
89 (html "HTML (encoding)" 89 (html "HTML (encoding)"
90 "1\\(^\\)" 90 nil
91 "recode -f html:latin1" "recode -f latin1:html" t nil) 91 "recode -f html:latin1" "recode -f latin1:html" t nil)
92 (rot13 "rot13" 92 (rot13 "rot13"
93 "1\\(^\\)" 93 nil
94 "tr a-mn-z n-za-m" "tr a-mn-z n-za-m" t nil) 94 "tr a-mn-z n-za-m" "tr a-mn-z n-za-m" t nil)
95 (duden "Duden Ersatzdarstellung" 95 (duden "Duden Ersatzdarstellung"
96 "1\\(^\\)" 96 nil
97 "diac" iso-iso2duden t nil) 97 "diac" iso-iso2duden t nil)
98 (de646 "German ASCII (ISO 646)" 98 (de646 "German ASCII (ISO 646)"
99 "1\\(^\\)" 99 nil
100 "recode -f iso646-ge:latin1" "recode -f latin1:iso646-ge" t nil) 100 "recode -f iso646-ge:latin1" "recode -f latin1:iso646-ge" t nil)
101 (denet "net German" 101 (denet "net German"
102 "1\\(^\\)" 102 nil
103 iso-german iso-cvt-read-only t nil) 103 iso-german iso-cvt-read-only t nil)
104 (esnet "net Spanish" 104 (esnet "net Spanish"
105 "1\\(^\\)" 105 nil
106 iso-spanish iso-cvt-read-only t nil)) 106 iso-spanish iso-cvt-read-only t nil))
107 "List of information about understood file formats. 107 "List of information about understood file formats.
108Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN). 108Elements are of the form \(NAME DOC-STR REGEXP FROM-FN TO-FN MODIFY MODE-FN).
@@ -114,9 +114,11 @@ DOC-STR should be a single line providing more information about the
114 the user if they ask for more information. 114 the user if they ask for more information.
115 115
116REGEXP is a regular expression to match against the beginning of the file; 116REGEXP is a regular expression to match against the beginning of the file;
117 it should match only files in that format. 117 it should match only files in that format. Use nil to avoid
118 matching at all for formats for which this isn't appropriate to
119 require explicit encoding/decoding.
118 120
119FROM-FN is called to decode files in that format; it gets two args, BEGIN 121FROM-FN is called to decode files in that format; it gets two args, BEGIN
120 and END, and can make any modifications it likes, returning the new 122 and END, and can make any modifications it likes, returning the new
121 end. It must make sure that the beginning of the file no longer 123 end. It must make sure that the beginning of the file no longer
122 matches REGEXP, or else it will get called again. 124 matches REGEXP, or else it will get called again.
@@ -134,7 +136,7 @@ TO-FN is called to encode a region into that format; it is passed three
134 136
135MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil, 137MODIFY, if non-nil, means the TO-FN wants to modify the region. If nil,
136 TO-FN will not make any changes but will instead return a list of 138 TO-FN will not make any changes but will instead return a list of
137 annotations. 139 annotations.
138 140
139MODE-FN, if specified, is called when visiting a file with that format.") 141MODE-FN, if specified, is called when visiting a file with that format.")
140 142
@@ -146,26 +148,50 @@ If METHOD is a string, it is a shell command;
146otherwise, it should be a Lisp function. 148otherwise, it should be a Lisp function.
147BUFFER should be the buffer that the output originally came from." 149BUFFER should be the buffer that the output originally came from."
148 (if (stringp method) 150 (if (stringp method)
149 (save-current-buffer 151 (let ((error-buff (get-buffer-create "*Format Errors*"))
150 (set-buffer buffer) 152 (coding-system-for-write 'no-conversion)
151 (with-output-to-temp-buffer "*Format Errors*" 153 format-alist)
152 (shell-command-on-region from to method t nil standard-output)) 154 (with-current-buffer error-buff
153 (point)) 155 (widen)
156 (erase-buffer))
157 (if (and (zerop (shell-command-on-region from to method t t
158 error-buff))
159 ;; gzip gives zero exit status with bad args, for instance.
160 (zerop (with-current-buffer error-buff
161 (buffer-size))))
162 (bury-buffer error-buff)
163 (switch-to-buffer-other-window error-buff)
164 (error "Format decoding failed")))
154 (funcall method from to buffer))) 165 (funcall method from to buffer)))
155 166
156(defun format-decode-run-method (method from to &optional buffer) 167(defun format-decode-run-method (method from to &optional buffer)
157 "Decode using function or shell script METHOD the text from FROM to TO. 168 "Decode using function or shell script METHOD the text from FROM to TO.
158If METHOD is a string, it is a shell command; 169If METHOD is a string, it is a shell command; otherwise, it should be
159otherwise, it should be a Lisp function." 170a Lisp function. Decoding is done for the given BUFFER."
160 (if (stringp method) 171 (if (stringp method)
161 (progn 172 (let ((error-buff (get-buffer-create "*Format Errors*"))
162 (with-output-to-temp-buffer "*Format Errors*" 173 (coding-system-for-read 'no-conversion) ; like jka-compr
163 (shell-command-on-region from to method t nil standard-output)) 174 format-alist)
175 (with-current-buffer error-buff
176 (widen)
177 (erase-buffer))
178 ;; We should perhaps go via a temporary buffer and copy it
179 ;; back, in case of errors.
180 (if (and (zerop (save-window-excursion
181 (shell-command-on-region (point-min) (point-max)
182 method t t
183 error-buff)))
184 ;; gzip gives zero exit status with bad args, for instance.
185 (zerop (with-current-buffer error-buff
186 (buffer-size))))
187 (bury-buffer error-buff)
188 (switch-to-buffer-other-window error-buff)
189 (error "Format decoding failed"))
164 (point)) 190 (point))
165 (funcall method from to))) 191 (funcall method from to)))
166 192
167(defun format-annotate-function (format from to orig-buf) 193(defun format-annotate-function (format from to orig-buf)
168 "Returns annotations for writing region as FORMAT. 194 "Return annotations for writing region as FORMAT.
169FORMAT is a symbol naming one of the formats defined in `format-alist', 195FORMAT is a symbol naming one of the formats defined in `format-alist',
170it must be a single symbol, not a list like `buffer-file-format'. 196it must be a single symbol, not a list like `buffer-file-format'.
171FROM and TO delimit the region to be operated on in the current buffer. 197FROM and TO delimit the region to be operated on in the current buffer.
@@ -175,7 +201,7 @@ it either returns a list of annotations, or returns with a different buffer
175current, which contains the modified text to write. 201current, which contains the modified text to write.
176 202
177For most purposes, consider using `format-encode-region' instead." 203For most purposes, consider using `format-encode-region' instead."
178 ;; This function is called by write-region (actually build-annotations) 204 ;; This function is called by write-region (actually build-annotations)
179 ;; for each element of buffer-file-format. 205 ;; for each element of buffer-file-format.
180 (let* ((info (assq format format-alist)) 206 (let* ((info (assq format format-alist))
181 (to-fn (nth 4 info)) 207 (to-fn (nth 4 info))
@@ -195,7 +221,7 @@ For most purposes, consider using `format-encode-region' instead."
195(defun format-decode (format length &optional visit-flag) 221(defun format-decode (format length &optional visit-flag)
196 ;; This function is called by insert-file-contents whenever a file is read. 222 ;; This function is called by insert-file-contents whenever a file is read.
197 "Decode text from any known FORMAT. 223 "Decode text from any known FORMAT.
198FORMAT is a symbol appearing in `format-alist' or a list of such symbols, 224FORMAT is a symbol appearing in `format-alist' or a list of such symbols,
199or nil, in which case this function tries to guess the format of the data by 225or nil, in which case this function tries to guess the format of the data by
200matching against the regular expressions in `format-alist'. After a match is 226matching against the regular expressions in `format-alist'. After a match is
201found and the region decoded, the alist is searched again from the beginning 227found and the region decoded, the alist is searched again from the beginning
@@ -210,7 +236,7 @@ Returns the new length of the decoded region.
210 236
211For most purposes, consider using `format-decode-region' instead." 237For most purposes, consider using `format-decode-region' instead."
212 (let ((mod (buffer-modified-p)) 238 (let ((mod (buffer-modified-p))
213 (begin (point)) 239 (begin (point))
214 (end (+ (point) length))) 240 (end (+ (point) length)))
215 (if (null format) 241 (if (null format)
216 ;; Figure out which format it is in, remember list in `format'. 242 ;; Figure out which format it is in, remember list in `format'.
@@ -258,7 +284,7 @@ For most purposes, consider using `format-decode-region' instead."
258(defun format-decode-buffer (&optional format) 284(defun format-decode-buffer (&optional format)
259 "Translate the buffer from some FORMAT. 285 "Translate the buffer from some FORMAT.
260If the format is not specified, this function attempts to guess. 286If the format is not specified, this function attempts to guess.
261`buffer-file-format' is set to the format used, and any mode-functions 287`buffer-file-format' is set to the format used, and any mode-functions
262for the format are called." 288for the format are called."
263 (interactive 289 (interactive
264 (list (format-read "Translate buffer from format (default: guess): "))) 290 (list (format-read "Translate buffer from format (default: guess): ")))
@@ -271,7 +297,7 @@ for the format are called."
271Arg FORMAT is optional; if omitted the format will be determined by looking 297Arg FORMAT is optional; if omitted the format will be determined by looking
272for identifying regular expressions at the beginning of the region." 298for identifying regular expressions at the beginning of the region."
273 (interactive 299 (interactive
274 (list (region-beginning) (region-end) 300 (list (region-beginning) (region-end)
275 (format-read "Translate region from format (default: guess): "))) 301 (format-read "Translate region from format (default: guess): ")))
276 (save-excursion 302 (save-excursion
277 (goto-char from) 303 (goto-char from)
@@ -287,37 +313,37 @@ formats defined in `format-alist', or a list of such symbols."
287 (format-encode-region (point-min) (point-max) format)) 313 (format-encode-region (point-min) (point-max) format))
288 314
289(defun format-encode-region (beg end &optional format) 315(defun format-encode-region (beg end &optional format)
290 "Translate the region into some FORMAT. 316 "Translate the region into some FORMAT.
291FORMAT defaults to `buffer-file-format', it is a symbol naming 317FORMAT defaults to `buffer-file-format', it is a symbol naming
292one of the formats defined in `format-alist', or a list of such symbols." 318one of the formats defined in `format-alist', or a list of such symbols."
293 (interactive 319 (interactive
294 (list (region-beginning) (region-end) 320 (list (region-beginning) (region-end)
295 (format-read (format "Translate region to format (default %s): " 321 (format-read (format "Translate region to format (default %s): "
296 buffer-file-format)))) 322 buffer-file-format))))
297 (if (null format) (setq format buffer-file-format)) 323 (if (null format) (setq format buffer-file-format))
298 (if (symbolp format) (setq format (list format))) 324 (if (symbolp format) (setq format (list format)))
299 (save-excursion 325 (save-excursion
300 (goto-char end) 326 (goto-char end)
301 (let ((cur-buf (current-buffer)) 327 (let ((cur-buf (current-buffer))
302 (end (point-marker))) 328 (end (point-marker)))
303 (while format 329 (while format
304 (let* ((info (assq (car format) format-alist)) 330 (let* ((info (assq (car format) format-alist))
305 (to-fn (nth 4 info)) 331 (to-fn (nth 4 info))
306 (modify (nth 5 info)) 332 (modify (nth 5 info))
307 result) 333 result)
308 (if to-fn 334 (if to-fn
309 (if modify 335 (if modify
310 (setq end (format-encode-run-method to-fn beg end 336 (setq end (format-encode-run-method to-fn beg end
311 (current-buffer))) 337 (current-buffer)))
312 (format-insert-annotations 338 (format-insert-annotations
313 (funcall to-fn beg end (current-buffer))))) 339 (funcall to-fn beg end (current-buffer)))))
314 (setq format (cdr format))))))) 340 (setq format (cdr format)))))))
315 341
316(defun format-write-file (filename format) 342(defun format-write-file (filename format)
317 "Write current buffer into a FILE using some FORMAT. 343 "Write current buffer into file FILENAME using some FORMAT.
318Makes buffer visit that file and sets the format as the default for future 344Makes buffer visit that file and sets the format as the default for future
319saves. If the buffer is already visiting a file, you can specify a directory 345saves. If the buffer is already visiting a file, you can specify a directory
320name as FILE, to write a file of the same old name in that directory." 346name as FILENAME, to write a file of the same old name in that directory."
321 (interactive 347 (interactive
322 ;; Same interactive spec as write-file, plus format question. 348 ;; Same interactive spec as write-file, plus format question.
323 (let* ((file (if buffer-file-name 349 (let* ((file (if buffer-file-name
@@ -327,19 +353,19 @@ name as FILE, to write a file of the same old name in that directory."
327 (cdr (assq 'default-directory 353 (cdr (assq 'default-directory
328 (buffer-local-variables))) 354 (buffer-local-variables)))
329 nil nil (buffer-name)))) 355 nil nil (buffer-name))))
330 (fmt (format-read (format "Write file `%s' in format: " 356 (fmt (format-read (format "Write file `%s' in format: "
331 (file-name-nondirectory file))))) 357 (file-name-nondirectory file)))))
332 (list file fmt))) 358 (list file fmt)))
333 (setq buffer-file-format format) 359 (setq buffer-file-format format)
334 (write-file filename)) 360 (write-file filename))
335 361
336(defun format-find-file (filename format) 362(defun format-find-file (filename format)
337 "Find the file FILE using data format FORMAT. 363 "Find the file FILENAME using data format FORMAT.
338If FORMAT is nil then do not do any format conversion." 364If FORMAT is nil then do not do any format conversion."
339 (interactive 365 (interactive
340 ;; Same interactive spec as write-file, plus format question. 366 ;; Same interactive spec as write-file, plus format question.
341 (let* ((file (read-file-name "Find file: ")) 367 (let* ((file (read-file-name "Find file: "))
342 (fmt (format-read (format "Read file `%s' in format: " 368 (fmt (format-read (format "Read file `%s' in format: "
343 (file-name-nondirectory file))))) 369 (file-name-nondirectory file)))))
344 (list file fmt))) 370 (list file fmt)))
345 (let ((format-alist nil)) 371 (let ((format-alist nil))
@@ -348,7 +374,7 @@ If FORMAT is nil then do not do any format conversion."
348 (format-decode-buffer format))) 374 (format-decode-buffer format)))
349 375
350(defun format-insert-file (filename format &optional beg end) 376(defun format-insert-file (filename format &optional beg end)
351 "Insert the contents of file FILE using data format FORMAT. 377 "Insert the contents of file FILENAME using data format FORMAT.
352If FORMAT is nil then do not do any format conversion. 378If FORMAT is nil then do not do any format conversion.
353The optional third and fourth arguments BEG and END specify 379The optional third and fourth arguments BEG and END specify
354the part of the file to read. 380the part of the file to read.
@@ -358,7 +384,7 @@ a list (ABSOLUTE-FILE-NAME . SIZE)."
358 (interactive 384 (interactive
359 ;; Same interactive spec as write-file, plus format question. 385 ;; Same interactive spec as write-file, plus format question.
360 (let* ((file (read-file-name "Find file: ")) 386 (let* ((file (read-file-name "Find file: "))
361 (fmt (format-read (format "Read file `%s' in format: " 387 (fmt (format-read (format "Read file `%s' in format: "
362 (file-name-nondirectory file))))) 388 (file-name-nondirectory file)))))
363 (list file fmt))) 389 (list file fmt)))
364 (let (value size) 390 (let (value size)
@@ -391,8 +417,8 @@ ALIST is a list of (from . to) pairs, which should be proper arguments to
391`search-forward' and `replace-match' respectively. 417`search-forward' and `replace-match' respectively.
392Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that 418Optional 2nd arg REVERSE, if non-nil, means the pairs are (to . from), so that
393you can use the same list in both directions if it contains only literal 419you can use the same list in both directions if it contains only literal
394strings. 420strings.
395Optional args BEGIN and END specify a region of the buffer to operate on." 421Optional args BEG and END specify a region of the buffer on which to operate."
396 (save-excursion 422 (save-excursion
397 (save-restriction 423 (save-restriction
398 (or beg (setq beg (point-min))) 424 (or beg (setq beg (point-min)))
@@ -413,10 +439,10 @@ Optional args BEGIN and END specify a region of the buffer to operate on."
413;;; Some list-manipulation functions that we need. 439;;; Some list-manipulation functions that we need.
414 440
415(defun format-delq-cons (cons list) 441(defun format-delq-cons (cons list)
416 "Remove the given CONS from LIST by side effect, 442 "Remove the given CONS from LIST by side effect and return the new LIST.
417and return the new LIST. Since CONS could be the first element 443Since CONS could be the first element of LIST, write
418of LIST, write `\(setq foo \(format-delq-cons element foo))' to be sure of 444`\(setq foo \(format-delq-cons element foo))' to be sure of changing
419changing the value of `foo'." 445the value of `foo'."
420 (if (eq cons list) 446 (if (eq cons list)
421 (cdr list) 447 (cdr list)
422 (let ((p list)) 448 (let ((p list))
@@ -449,7 +475,7 @@ returns nil."
449 (let ((la (length a)) 475 (let ((la (length a))
450 (lb (length b))) 476 (lb (length b)))
451 ;; Make sure they are the same length 477 ;; Make sure they are the same length
452 (if (> la lb) 478 (if (> la lb)
453 (setq a (nthcdr (- la lb) a)) 479 (setq a (nthcdr (- la lb) a))
454 (setq b (nthcdr (- lb la) b)))) 480 (setq b (nthcdr (- lb la) b))))
455 (while (not (equal a b)) 481 (while (not (equal a b))
@@ -464,7 +490,7 @@ ORDER. Unmatched items will go last."
464 (if order 490 (if order
465 (let ((item (member (car order) items))) 491 (let ((item (member (car order) items)))
466 (if item 492 (if item
467 (cons (car item) 493 (cons (car item)
468 (format-reorder (format-delq-cons item items) 494 (format-reorder (format-delq-cons item items)
469 (cdr order))) 495 (cdr order)))
470 (format-reorder items (cdr order)))) 496 (format-reorder items (cdr order))))
@@ -482,7 +508,7 @@ ORDER. Unmatched items will go last."
482 508
483(defun format-deannotate-region (from to translations next-fn) 509(defun format-deannotate-region (from to translations next-fn)
484 "Translate annotations in the region into text properties. 510 "Translate annotations in the region into text properties.
485This sets text properties between FROM to TO as directed by the 511This sets text properties between FROM to TO as directed by the
486TRANSLATIONS and NEXT-FN arguments. 512TRANSLATIONS and NEXT-FN arguments.
487 513
488NEXT-FN is a function that searches forward from point for an annotation. 514NEXT-FN is a function that searches forward from point for an annotation.
@@ -669,19 +695,20 @@ to write these unknown annotations back into the file."
669 (message "Unknown annotations: %s" unknown-ans)))))) 695 (message "Unknown annotations: %s" unknown-ans))))))
670 696
671(defun format-subtract-regions (minu subtra) 697(defun format-subtract-regions (minu subtra)
672 "Remove the regions in SUBTRAHEND from the regions in MINUEND. A region 698 "Remove from the regions in MINUend the regions in SUBTRAhend.
673is a dotted pair (from . to). Both parameters are lists of regions. Each 699A region is a dotted pair (from . to). Both parameters are lists of
674list must contain nonoverlapping, noncontiguous regions, in descending 700regions. Each list must contain nonoverlapping, noncontiguous
675order. The result is also nonoverlapping, noncontiguous, and in descending 701regions, in descending order. The result is also nonoverlapping,
676order. The first element of MINUEND can have a cdr of nil, indicating that 702noncontiguous, and in descending order. The first element of MINUEND
677the end of that region is not yet known." 703can have a cdr of nil, indicating that the end of that region is not
704yet known."
678 (let* ((minuend (copy-alist minu)) 705 (let* ((minuend (copy-alist minu))
679 (subtrahend (copy-alist subtra)) 706 (subtrahend (copy-alist subtra))
680 (m (car minuend)) 707 (m (car minuend))
681 (s (car subtrahend)) 708 (s (car subtrahend))
682 results) 709 results)
683 (while (and minuend subtrahend) 710 (while (and minuend subtrahend)
684 (cond 711 (cond
685 ;; The minuend starts after the subtrahend ends; keep it. 712 ;; The minuend starts after the subtrahend ends; keep it.
686 ((> (car m) (cdr s)) 713 ((> (car m) (cdr s))
687 (setq results (cons m results) 714 (setq results (cons m results)
@@ -707,8 +734,8 @@ the end of that region is not yet known."
707;; next-single-property-change instead of text-property-not-all, but then 734;; next-single-property-change instead of text-property-not-all, but then
708;; we have to see if we passed TO. 735;; we have to see if we passed TO.
709(defun format-property-increment-region (from to prop delta default) 736(defun format-property-increment-region (from to prop delta default)
710 "Increment property PROP over the region between FROM and TO by the 737 "Over the region between FROM and TO increment property PROP by amount DELTA.
711amount DELTA (which may be negative). If property PROP is nil anywhere 738DELTA may be negative. If property PROP is nil anywhere
712in the region, it is treated as though it were DEFAULT." 739in the region, it is treated as though it were DEFAULT."
713 (let ((cur from) val newval next) 740 (let ((cur from) val newval next)
714 (while cur 741 (while cur
@@ -729,7 +756,7 @@ appropriate place. Use second arg OFFSET if the annotations' locations are
729not relative to the beginning of the buffer: annotations will be inserted 756not relative to the beginning of the buffer: annotations will be inserted
730at their location-OFFSET+1 \(ie, the offset is treated as the character number 757at their location-OFFSET+1 \(ie, the offset is treated as the character number
731of the first character in the buffer)." 758of the first character in the buffer)."
732 (if (not offset) 759 (if (not offset)
733 (setq offset 0) 760 (setq offset 0)
734 (setq offset (1- offset))) 761 (setq offset (1- offset)))
735 (let ((l (reverse list))) 762 (let ((l (reverse list)))
@@ -746,7 +773,7 @@ property is the name of the annotation that you want to use, as it is for the
746 (cons (if old (list old)) 773 (cons (if old (list old))
747 (if new (list new)))) 774 (if new (list new))))
748 775
749(defun format-annotate-region (from to trans format-fn ignore) 776(defun format-annotate-region (from to translations format-fn ignore)
750 "Generate annotations for text properties in the region. 777 "Generate annotations for text properties in the region.
751Searches for changes between FROM and TO, and describes them with a list of 778Searches for changes between FROM and TO, and describes them with a list of
752annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text 779annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text
@@ -763,7 +790,7 @@ ANNOTATIONS. Whenever the property takes on that value, the annotations
763\(as formatted by FORMAT-FN) are inserted into the file. 790\(as formatted by FORMAT-FN) are inserted into the file.
764When the property stops having that value, the matching negated annotation 791When the property stops having that value, the matching negated annotation
765will be inserted \(it may actually be closed earlier and reopened, if 792will be inserted \(it may actually be closed earlier and reopened, if
766necessary, to keep proper nesting). 793necessary, to keep proper nesting).
767 794
768If the property's value is a list, then each element of the list is dealt with 795If the property's value is a list, then each element of the list is dealt with
769separately. 796separately.
@@ -788,7 +815,7 @@ lists of annotations like `format-annotate-location' does.
788 (and (setq loc (next-property-change loc nil to)) 815 (and (setq loc (next-property-change loc nil to))
789 (< loc to))) 816 (< loc to)))
790 (or loc (setq loc from)) 817 (or loc (setq loc from))
791 (let* ((ans (format-annotate-location loc (= loc from) ignore trans)) 818 (let* ((ans (format-annotate-location loc (= loc from) ignore translations))
792 (neg-ans (format-reorder (aref ans 0) open-ans)) 819 (neg-ans (format-reorder (aref ans 0) open-ans))
793 (pos-ans (aref ans 1)) 820 (pos-ans (aref ans 1))
794 (ignored (aref ans 2))) 821 (ignored (aref ans 2)))
@@ -805,14 +832,14 @@ lists of annotations like `format-annotate-location' does.
805 ;; To close anno. N, need to first close ans 1 to N-1, 832 ;; To close anno. N, need to first close ans 1 to N-1,
806 ;; remembering to re-open them later. 833 ;; remembering to re-open them later.
807 (setq pos-ans (cons (car open-ans) pos-ans)) 834 (setq pos-ans (cons (car open-ans) pos-ans))
808 (setq all-ans 835 (setq all-ans
809 (cons (cons loc (funcall format-fn (car open-ans) nil)) 836 (cons (cons loc (funcall format-fn (car open-ans) nil))
810 all-ans)) 837 all-ans))
811 (setq open-ans (cdr open-ans))) 838 (setq open-ans (cdr open-ans)))
812 ;; Now remove the one we're really interested in from open list. 839 ;; Now remove the one we're really interested in from open list.
813 (setq open-ans (cdr open-ans)) 840 (setq open-ans (cdr open-ans))
814 ;; And put the closing annotation here. 841 ;; And put the closing annotation here.
815 (setq all-ans 842 (setq all-ans
816 (cons (cons loc (funcall format-fn (car neg-ans) nil)) 843 (cons (cons loc (funcall format-fn (car neg-ans) nil))
817 all-ans))) 844 all-ans)))
818 (setq neg-ans (cdr neg-ans))) 845 (setq neg-ans (cdr neg-ans)))
@@ -820,14 +847,14 @@ lists of annotations like `format-annotate-location' does.
820 (let ((p pos-ans)) 847 (let ((p pos-ans))
821 (while pos-ans 848 (while pos-ans
822 (setq open-ans (cons (car pos-ans) open-ans)) 849 (setq open-ans (cons (car pos-ans) open-ans))
823 (setq all-ans 850 (setq all-ans
824 (cons (cons loc (funcall format-fn (car pos-ans) t)) 851 (cons (cons loc (funcall format-fn (car pos-ans) t))
825 all-ans)) 852 all-ans))
826 (setq pos-ans (cdr pos-ans)))))) 853 (setq pos-ans (cdr pos-ans))))))
827 854
828 ;; Close any annotations still open 855 ;; Close any annotations still open
829 (while open-ans 856 (while open-ans
830 (setq all-ans 857 (setq all-ans
831 (cons (cons to (funcall format-fn (car open-ans) nil)) 858 (cons (cons to (funcall format-fn (car open-ans) nil))
832 all-ans)) 859 all-ans))
833 (setq open-ans (cdr open-ans))) 860 (setq open-ans (cdr open-ans)))
@@ -838,12 +865,13 @@ lists of annotations like `format-annotate-location' does.
838 865
839;;; Internal functions for format-annotate-region. 866;;; Internal functions for format-annotate-region.
840 867
841(defun format-annotate-location (loc all ignore trans) 868(defun format-annotate-location (loc all ignore translations)
842 "Return annotation(s) needed at LOCATION. 869 "Return annotation(s) needed at location LOC.
843This includes any properties that change between LOC-1 and LOC. 870This includes any properties that change between LOC-1 and LOC.
844If ALL is true, don't look at previous location, but generate annotations for 871If ALL is true, don't look at previous location, but generate annotations for
845all non-nil properties. 872all non-nil properties.
846Third argument IGNORE is a list of text-properties not to consider. 873Third argument IGNORE is a list of text-properties not to consider.
874Use the TRANSLATIONS alist.
847 875
848Return value is a vector of 3 elements: 876Return value is a vector of 3 elements:
8491. List of names of the annotations to close 8771. List of names of the annotations to close
@@ -875,7 +903,7 @@ Return value is a vector of 3 elements:
875 (if (equal before after) 903 (if (equal before after)
876 nil ; no change; ignore 904 nil ; no change; ignore
877 (let ((result (format-annotate-single-property-change 905 (let ((result (format-annotate-single-property-change
878 prop before after trans))) 906 prop before after translations)))
879 (if (not result) 907 (if (not result)
880 (setq not-found (cons prop not-found)) 908 (setq not-found (cons prop not-found))
881 (setq negatives (nconc negatives (car result)) 909 (setq negatives (nconc negatives (car result))
@@ -883,8 +911,8 @@ Return value is a vector of 3 elements:
883 (vector negatives positives not-found))) 911 (vector negatives positives not-found)))
884 912
885(defun format-annotate-single-property-change (prop old new trans) 913(defun format-annotate-single-property-change (prop old new trans)
886 "Return annotations for PROPERTY changing from OLD to NEW. 914 "Return annotations for property PROP changing from OLD to NEW.
887These are searched for in the TRANSLATIONS alist. 915These are searched for in the translations alist TRANS.
888If NEW does not appear in the list, but there is a default function, then that 916If NEW does not appear in the list, but there is a default function, then that
889function is called. 917function is called.
890Annotations to open and to close are returned as a dotted pair." 918Annotations to open and to close are returned as a dotted pair."
@@ -899,13 +927,13 @@ Annotations to open and to close are returned as a dotted pair."
899 (tail (format-common-tail old new)) 927 (tail (format-common-tail old new))
900 close open) 928 close open)
901 (while old 929 (while old
902 (setq close 930 (setq close
903 (append (car (format-annotate-atomic-property-change 931 (append (car (format-annotate-atomic-property-change
904 prop-alist (car old) nil)) 932 prop-alist (car old) nil))
905 close) 933 close)
906 old (cdr old))) 934 old (cdr old)))
907 (while new 935 (while new
908 (setq open 936 (setq open
909 (append (cdr (format-annotate-atomic-property-change 937 (append (cdr (format-annotate-atomic-property-change
910 prop-alist nil (car new))) 938 prop-alist nil (car new)))
911 open) 939 open)
@@ -954,4 +982,5 @@ OLD and NEW are the values."
954 (funcall (car (cdr default)) old new)))))))) 982 (funcall (car (cdr default)) old new))))))))
955 983
956(provide 'format) 984(provide 'format)
957;; format.el ends here 985
986;;; format.el ends here