comparison lisp/format.el @ 90573:858cb33ae39d

Merge from emacs--devo--0 Patches applied: * emacs--devo--0 (patch 357-381) - Merge from gnus--rel--5.10 - Update from CVS - Merge from erc--emacs--21 * gnus--rel--5.10 (patch 116-122) - Update from CVS - Merge from emacs--devo--0 Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-98
author Miles Bader <miles@gnu.org>
date Thu, 03 Aug 2006 11:45:23 +0000
parents c5406394f567 2d16125405b4
children f1d13e615070
comparison
equal deleted inserted replaced
90572:ab9b8d043c39 90573:858cb33ae39d
106 format. It is currently unused, but in the future will be shown to 106 format. It is currently unused, but in the future will be shown to
107 the user if they ask for more information. 107 the user if they ask for more information.
108 108
109 REGEXP is a regular expression to match against the beginning of the file; 109 REGEXP is a regular expression to match against the beginning of the file;
110 it should match only files in that format. Use nil to avoid 110 it should match only files in that format. Use nil to avoid
111 matching at all for formats for which this isn't appropriate to 111 matching at all for formats for which it isn't appropriate to
112 require explicit encoding/decoding. 112 require explicit encoding/decoding.
113 113
114 FROM-FN is called to decode files in that format; it gets two args, BEGIN 114 FROM-FN is called to decode files in that format; it takes two args, BEGIN
115 and END, and can make any modifications it likes, returning the new 115 and END, and can make any modifications it likes, returning the new
116 end. It must make sure that the beginning of the file no longer 116 end. It must make sure that the beginning of the file no longer
117 matches REGEXP, or else it will get called again. 117 matches REGEXP, or else it will get called again.
118 Alternatively, FROM-FN can be a string, which specifies a shell command 118 Alternatively, FROM-FN can be a string, which specifies a shell command
119 (including options) to be used as a filter to perform the conversion. 119 (including options) to be used as a filter to perform the conversion.
120 120
121 TO-FN is called to encode a region into that format; it is passed three 121 TO-FN is called to encode a region into that format; it takes three
122 arguments: BEGIN, END, and BUFFER. BUFFER is the original buffer that 122 arguments: BEGIN, END, and BUFFER. BUFFER is the original buffer that
123 the data being written came from, which the function could use, for 123 the data being written came from, which the function could use, for
124 example, to find the values of local variables. TO-FN should either 124 example, to find the values of local variables. TO-FN should either
125 return a list of annotations like `write-region-annotate-functions', 125 return a list of annotations like `write-region-annotate-functions',
126 or modify the region and return the new end. 126 or modify the region and return the new end.
131 TO-FN will not make any changes but will instead return a list of 131 TO-FN will not make any changes but will instead return a list of
132 annotations. 132 annotations.
133 133
134 MODE-FN, if specified, is called when visiting a file with that format. 134 MODE-FN, if specified, is called when visiting a file with that format.
135 It is called with a single positive argument, on the assumption 135 It is called with a single positive argument, on the assumption
136 that it turns on some Emacs mode. 136 that this would turn on some minor mode.
137 137
138 PRESERVE, if non-nil, means that `format-write-file' should not remove 138 PRESERVE, if non-nil, means that `format-write-file' should not remove
139 this format from `buffer-file-formats'.") 139 this format from `buffer-file-formats'.")
140 140
141 ;;; Basic Functions (called from Lisp) 141 ;;; Basic Functions (called from Lisp)
142 142
143 (defun format-encode-run-method (method from to &optional buffer) 143 (defun format-encode-run-method (method from to &optional buffer)
144 "Translate using function or shell script METHOD the text from FROM to TO. 144 "Translate using METHOD the text from FROM to TO.
145 If METHOD is a string, it is a shell command; 145 If METHOD is a string, it is a shell command (including options);
146 otherwise, it should be a Lisp function. 146 otherwise, it should be a Lisp function.
147 BUFFER should be the buffer that the output originally came from." 147 BUFFER should be the buffer that the output originally came from."
148 (if (stringp method) 148 (if (stringp method)
149 (let ((error-buff (get-buffer-create "*Format Errors*")) 149 (let ((error-buff (get-buffer-create "*Format Errors*"))
150 (coding-system-for-read 'no-conversion) 150 (coding-system-for-read 'no-conversion)
162 (switch-to-buffer-other-window error-buff) 162 (switch-to-buffer-other-window error-buff)
163 (error "Format encoding failed"))) 163 (error "Format encoding failed")))
164 (funcall method from to buffer))) 164 (funcall method from to buffer)))
165 165
166 (defun format-decode-run-method (method from to &optional buffer) 166 (defun format-decode-run-method (method from to &optional buffer)
167 "Decode using function or shell script METHOD the text from FROM to TO. 167 "Decode using METHOD the text from FROM to TO.
168 If METHOD is a string, it is a shell command; otherwise, it should be 168 If METHOD is a string, it is a shell command (including options); otherwise,
169 a Lisp function. Decoding is done for the given BUFFER." 169 it should be a Lisp function. Decoding is done for the given BUFFER."
170 (if (stringp method) 170 (if (stringp method)
171 (let ((error-buff (get-buffer-create "*Format Errors*")) 171 (let ((error-buff (get-buffer-create "*Format Errors*"))
172 (coding-system-for-write 'no-conversion) 172 (coding-system-for-write 'no-conversion)
173 format-alist) 173 format-alist)
174 (with-current-buffer error-buff 174 (with-current-buffer error-buff
189 (point)) 189 (point))
190 (funcall method from to))) 190 (funcall method from to)))
191 191
192 (defun format-annotate-function (format from to orig-buf format-count) 192 (defun format-annotate-function (format from to orig-buf format-count)
193 "Return annotations for writing region as FORMAT. 193 "Return annotations for writing region as FORMAT.
194 FORMAT is a symbol naming one of the formats defined in `format-alist', 194 FORMAT is a symbol naming one of the formats defined in `format-alist'.
195 it must be a single symbol, not a list like `buffer-file-format'. 195 It must be a single symbol, not a list like `buffer-file-format'.
196 FROM and TO delimit the region to be operated on in the current buffer. 196 FROM and TO delimit the region to be operated on in the current buffer.
197 ORIG-BUF is the original buffer that the data came from. 197 ORIG-BUF is the original buffer that the data came from.
198 198
199 FORMAT-COUNT is an integer specifying how many times this function has 199 FORMAT-COUNT is an integer specifying how many times this function has
200 been called in the process of decoding ORIG-BUF. 200 been called in the process of decoding ORIG-BUF.
201 201
202 This function works like a function on `write-region-annotate-functions': 202 This function works like a function in `write-region-annotate-functions':
203 it either returns a list of annotations, or returns with a different buffer 203 it either returns a list of annotations, or returns with a different buffer
204 current, which contains the modified text to write. In the latter case, 204 current, which contains the modified text to write. In the latter case,
205 this function's value is nil. 205 this function's value is nil.
206 206
207 For most purposes, consider using `format-encode-region' instead." 207 For most purposes, consider using `format-encode-region' instead."
242 Second arg LENGTH is the number of characters following point to operate on. 242 Second arg LENGTH is the number of characters following point to operate on.
243 If optional third arg VISIT-FLAG is true, set `buffer-file-format' 243 If optional third arg VISIT-FLAG is true, set `buffer-file-format'
244 to the reverted list of formats used, and call any mode functions defined 244 to the reverted list of formats used, and call any mode functions defined
245 for those formats. 245 for those formats.
246 246
247 Returns the new length of the decoded region. 247 Return the new length of the decoded region.
248 248
249 For most purposes, consider using `format-decode-region' instead." 249 For most purposes, consider using `format-decode-region' instead."
250 (let ((mod (buffer-modified-p)) 250 (let ((mod (buffer-modified-p))
251 (begin (point)) 251 (begin (point))
252 (end (+ (point) length))) 252 (end (+ (point) length)))
301 ;;; Interactive functions & entry points 301 ;;; Interactive functions & entry points
302 ;;; 302 ;;;
303 303
304 (defun format-decode-buffer (&optional format) 304 (defun format-decode-buffer (&optional format)
305 "Translate the buffer from some FORMAT. 305 "Translate the buffer from some FORMAT.
306 If the format is not specified, this function attempts to guess. 306 If the format is not specified, attempt a regexp-based guess.
307 `buffer-file-format' is set to the format used, and any mode-functions 307 Set `buffer-file-format' to the format used, and call any
308 for the format are called." 308 format-specific mode functions."
309 (interactive 309 (interactive
310 (list (format-read "Translate buffer from format (default guess): "))) 310 (list (format-read "Translate buffer from format (default guess): ")))
311 (save-excursion 311 (save-excursion
312 (goto-char (point-min)) 312 (goto-char (point-min))
313 (format-decode format (buffer-size) t))) 313 (format-decode format (buffer-size) t)))
332 buffer-file-format)))) 332 buffer-file-format))))
333 (format-encode-region (point-min) (point-max) format)) 333 (format-encode-region (point-min) (point-max) format))
334 334
335 (defun format-encode-region (beg end &optional format) 335 (defun format-encode-region (beg end &optional format)
336 "Translate the region into some FORMAT. 336 "Translate the region into some FORMAT.
337 FORMAT defaults to `buffer-file-format', it is a symbol naming 337 FORMAT defaults to `buffer-file-format'. It is a symbol naming
338 one of the formats defined in `format-alist', or a list of such symbols." 338 one of the formats defined in `format-alist', or a list of such symbols."
339 (interactive 339 (interactive
340 (list (region-beginning) (region-end) 340 (list (region-beginning) (region-end)
341 (format-read (format "Translate region to format (default %s): " 341 (format-read (format "Translate region to format (default %s): "
342 buffer-file-format)))) 342 buffer-file-format))))
363 "Write current buffer into file FILENAME using some FORMAT. 363 "Write current buffer into file FILENAME using some FORMAT.
364 Make buffer visit that file and set the format as the default for future 364 Make buffer visit that file and set the format as the default for future
365 saves. If the buffer is already visiting a file, you can specify a directory 365 saves. If the buffer is already visiting a file, you can specify a directory
366 name as FILENAME, to write a file of the same old name in that directory. 366 name as FILENAME, to write a file of the same old name in that directory.
367 367
368 If optional third arg CONFIRM is non-nil, this function asks for 368 If optional third arg CONFIRM is non-nil, ask for confirmation before
369 confirmation before overwriting an existing file. Interactively, 369 overwriting an existing file. Interactively, confirmation is required
370 confirmation is required unless you supply a prefix argument." 370 unless you supply a prefix argument."
371 (interactive 371 (interactive
372 ;; Same interactive spec as write-file, plus format question. 372 ;; Same interactive spec as write-file, plus format question.
373 (let* ((file (if buffer-file-name 373 (let* ((file (if buffer-file-name
374 (read-file-name "Write file: " 374 (read-file-name "Write file: "
375 nil nil nil nil) 375 nil nil nil nil)
408 408
409 (defun format-insert-file (filename format &optional beg end) 409 (defun format-insert-file (filename format &optional beg end)
410 "Insert the contents of file FILENAME using data format FORMAT. 410 "Insert the contents of file FILENAME using data format FORMAT.
411 If FORMAT is nil then do not do any format conversion. 411 If FORMAT is nil then do not do any format conversion.
412 The optional third and fourth arguments BEG and END specify 412 The optional third and fourth arguments BEG and END specify
413 the part of the file to read. 413 the part (in bytes) of the file to read.
414 414
415 The return value is like the value of `insert-file-contents': 415 The return value is like the value of `insert-file-contents':
416 a list (ABSOLUTE-FILE-NAME SIZE)." 416 a list (ABSOLUTE-FILE-NAME SIZE)."
417 (interactive 417 (interactive
418 ;; Same interactive spec as write-file, plus format question. 418 ;; Same interactive spec as write-file, plus format question.
445 ;;; 445 ;;;
446 446
447 (defun format-replace-strings (alist &optional reverse beg end) 447 (defun format-replace-strings (alist &optional reverse beg end)
448 "Do multiple replacements on the buffer. 448 "Do multiple replacements on the buffer.
449 ALIST is a list of (FROM . TO) pairs, which should be proper arguments to 449 ALIST is a list of (FROM . TO) pairs, which should be proper arguments to
450 `search-forward' and `replace-match' respectively. 450 `search-forward' and `replace-match', respectively.
451 Optional 2nd arg REVERSE, if non-nil, means the pairs are (TO . FROM), so that 451 Optional second arg REVERSE, if non-nil, means the pairs are (TO . FROM),
452 you can use the same list in both directions if it contains only literal 452 so that you can use the same list in both directions if it contains only
453 strings. 453 literal strings.
454 Optional args BEG and END specify a region of the buffer on which to operate." 454 Optional args BEG and END specify a region of the buffer on which to operate."
455 (save-excursion 455 (save-excursion
456 (save-restriction 456 (save-restriction
457 (or beg (setq beg (point-min))) 457 (or beg (setq beg (point-min)))
458 (if end (narrow-to-region (point-min) end)) 458 (if end (narrow-to-region (point-min) end))
486 (setcdr p (cdr cons)) 486 (setcdr p (cdr cons))
487 list))) 487 list)))
488 488
489 (defun format-make-relatively-unique (a b) 489 (defun format-make-relatively-unique (a b)
490 "Delete common elements of lists A and B, return as pair. 490 "Delete common elements of lists A and B, return as pair.
491 Compares using `equal'." 491 Compare using `equal'."
492 (let* ((acopy (copy-sequence a)) 492 (let* ((acopy (copy-sequence a))
493 (bcopy (copy-sequence b)) 493 (bcopy (copy-sequence b))
494 (tail acopy)) 494 (tail acopy))
495 (while tail 495 (while tail
496 (let ((dup (member (car tail) bcopy)) 496 (let ((dup (member (car tail) bcopy))
500 (setq tail next))) 500 (setq tail next)))
501 (cons acopy bcopy))) 501 (cons acopy bcopy)))
502 502
503 (defun format-common-tail (a b) 503 (defun format-common-tail (a b)
504 "Given two lists that have a common tail, return it. 504 "Given two lists that have a common tail, return it.
505 Compares with `equal', and returns the part of A that is equal to the 505 Compare with `equal', and return the part of A that is equal to the
506 equivalent part of B. If even the last items of the two are not equal, 506 equivalent part of B. If even the last items of the two are not equal,
507 returns nil." 507 return nil."
508 (let ((la (length a)) 508 (let ((la (length a))
509 (lb (length b))) 509 (lb (length b)))
510 ;; Make sure they are the same length 510 ;; Make sure they are the same length
511 (if (> la lb) 511 (if (> la lb)
512 (setq a (nthcdr (- la lb) a)) 512 (setq a (nthcdr (- la lb) a))
523 (while (consp list) 523 (while (consp list)
524 (setq list (cdr list))) 524 (setq list (cdr list)))
525 (null list))) 525 (null list)))
526 526
527 (defun format-reorder (items order) 527 (defun format-reorder (items order)
528 "Arrange ITEMS to following partial ORDER. 528 "Arrange ITEMS to follow partial ORDER.
529 Elements of ITEMS equal to elements of ORDER will be rearranged to follow the 529 Elements of ITEMS equal to elements of ORDER will be rearranged
530 ORDER. Unmatched items will go last." 530 to follow the ORDER. Unmatched items will go last."
531 (if order 531 (if order
532 (let ((item (member (car order) items))) 532 (let ((item (member (car order) items)))
533 (if item 533 (if item
534 (cons (car item) 534 (cons (car item)
535 (format-reorder (format-delq-cons item items) 535 (format-reorder (format-delq-cons item items)
782 ;; This should probably go somewhere other than format.el. Then again, 782 ;; This should probably go somewhere other than format.el. Then again,
783 ;; indent.el has alter-text-property. NOTE: We can also use 783 ;; indent.el has alter-text-property. NOTE: We can also use
784 ;; next-single-property-change instead of text-property-not-all, but then 784 ;; next-single-property-change instead of text-property-not-all, but then
785 ;; we have to see if we passed TO. 785 ;; we have to see if we passed TO.
786 (defun format-property-increment-region (from to prop delta default) 786 (defun format-property-increment-region (from to prop delta default)
787 "Over the region between FROM and TO increment property PROP by amount DELTA. 787 "In the region from FROM to TO increment property PROP by amount DELTA.
788 DELTA may be negative. If property PROP is nil anywhere 788 DELTA may be negative. If property PROP is nil anywhere
789 in the region, it is treated as though it were DEFAULT." 789 in the region, it is treated as though it were DEFAULT."
790 (let ((cur from) val newval next) 790 (let ((cur from) val newval next)
791 (while cur 791 (while cur
792 (setq val (get-text-property cur prop) 792 (setq val (get-text-property cur prop)
799 ;;; Encoding 799 ;;; Encoding
800 ;;; 800 ;;;
801 801
802 (defun format-insert-annotations (list &optional offset) 802 (defun format-insert-annotations (list &optional offset)
803 "Apply list of annotations to buffer as `write-region' would. 803 "Apply list of annotations to buffer as `write-region' would.
804 Inserts each element of the given LIST of buffer annotations at its 804 Insert each element of the given LIST of buffer annotations at its
805 appropriate place. Use second arg OFFSET if the annotations' locations are 805 appropriate place. Use second arg OFFSET if the annotations' locations are
806 not relative to the beginning of the buffer: annotations will be inserted 806 not relative to the beginning of the buffer: annotations will be inserted
807 at their location-OFFSET+1 \(ie, the offset is treated as the position of 807 at their location-OFFSET+1 \(ie, the offset is treated as the position of
808 the first character in the buffer)." 808 the first character in the buffer)."
809 (if (not offset) 809 (if (not offset)
823 (cons (if old (list old)) 823 (cons (if old (list old))
824 (if new (list new)))) 824 (if new (list new))))
825 825
826 (defun format-annotate-region (from to translations format-fn ignore) 826 (defun format-annotate-region (from to translations format-fn ignore)
827 "Generate annotations for text properties in the region. 827 "Generate annotations for text properties in the region.
828 Searches for changes between FROM and TO, and describes them with a list of 828 Search for changes between FROM and TO, and describe them with a list of
829 annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text 829 annotations as defined by alist TRANSLATIONS and FORMAT-FN. IGNORE lists text
830 properties not to consider; any text properties that are neither ignored nor 830 properties not to consider; any text properties that are neither ignored nor
831 listed in TRANSLATIONS are warned about. 831 listed in TRANSLATIONS are warned about.
832 If you actually want to modify the region, give the return value of this 832 If you actually want to modify the region, give the return value of this
833 function to `format-insert-annotations'. 833 function to `format-insert-annotations'.
964 964
965 (defun format-annotate-single-property-change (prop old new translations) 965 (defun format-annotate-single-property-change (prop old new translations)
966 "Return annotations for property PROP changing from OLD to NEW. 966 "Return annotations for property PROP changing from OLD to NEW.
967 These are searched for in the translations alist TRANSLATIONS 967 These are searched for in the translations alist TRANSLATIONS
968 (see `format-annotate-region' for the format). 968 (see `format-annotate-region' for the format).
969 If NEW does not appear in the list, but there is a default function, then that 969 If NEW does not appear in the list, but there is a default function,
970 function is called. 970 then call that function.
971 Returns a cons of the form (CLOSE . OPEN) 971 Return a cons of the form (CLOSE . OPEN)
972 where CLOSE is a list of annotations to close 972 where CLOSE is a list of annotations to close
973 and OPEN is a list of annotations to open. 973 and OPEN is a list of annotations to open.
974 974
975 The annotations in CLOSE and OPEN need not be strings. 975 The annotations in CLOSE and OPEN need not be strings.
976 They can be whatever the FORMAT-FN in `format-annotate-region' 976 They can be whatever the FORMAT-FN in `format-annotate-region'
1005 new (cdr new))) 1005 new (cdr new)))
1006 (format-make-relatively-unique close open))) 1006 (format-make-relatively-unique close open)))
1007 (format-annotate-atomic-property-change prop-alist old new))))) 1007 (format-annotate-atomic-property-change prop-alist old new)))))
1008 1008
1009 (defun format-annotate-atomic-property-change (prop-alist old new) 1009 (defun format-annotate-atomic-property-change (prop-alist old new)
1010 "Internal function annotate a single property change. 1010 "Internal function to annotate a single property change.
1011 PROP-ALIST is the relevant element of a TRANSLATIONS list. 1011 PROP-ALIST is the relevant element of a TRANSLATIONS list.
1012 OLD and NEW are the values." 1012 OLD and NEW are the values."
1013 (let (num-ann) 1013 (let (num-ann)
1014 ;; If old and new values are numbers, 1014 ;; If old and new values are numbers,
1015 ;; look for a number in PROP-ALIST. 1015 ;; look for a number in PROP-ALIST.