]> code.delx.au - gnu-emacs/blobdiff - lisp/format.el
(format-deannotate-region): Fixed bug that created
[gnu-emacs] / lisp / format.el
index 75aa5ec88316b02a104e0a84036196c4a98abbbc..929be66cdef005d35d62c93e2284968e8a1d3893 100644 (file)
@@ -1,7 +1,8 @@
-;;; format.el -- read and save files in multiple formats
+;;; format.el --- read and save files in multiple formats
+
 ;; Copyright (c) 1994, 1995 Free Software Foundation
 
-;; Author: Boris Goldowsky <boris@cs.rochester.edu>
+;; Author: Boris Goldowsky <boris@gnu.ai.mit.edu>
 
 ;; This file is part of GNU Emacs.
 
 ;; it under the terms of the GNU General Public License as published by
 ;; the Free Software Foundation; either version 2, or (at your option)
 ;; any later version.
-;;
+
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 ;; GNU General Public License for more details.
-;;
+
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+;; along with GNU Emacs; see the file COPYING.  If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
 
 ;;; Commentary:
-;; This file defines a unified mechanism for saving & loading files stored in
-;; different formats.  `format-alist' contains information that directs
+
+;; This file defines a unified mechanism for saving & loading files stored
+;; in different formats.  `format-alist' contains information that directs
 ;; Emacs to call an encoding or decoding function when reading or writing
 ;; files that match certain conditions.  
 ;;
-;; When a file is visited, its format is determined by matching the beginning
-;; of the file against regular expressions stored in `format-alist'.  If this
-;; fails, you can manually translate the buffer using `format-decode-buffer'.
-;; In either case, the formats used are listed in the variable
-;; `buffer-file-format', and become the default format for saving the buffer.
-;; To save a buffer in a different format, change this variable, or use
-;; `format-write-file'.
+;; When a file is visited, its format is determined by matching the
+;; beginning of the file against regular expressions stored in
+;; `format-alist'.  If this fails, you can manually translate the buffer
+;; using `format-decode-buffer'.  In either case, the formats used are
+;; listed in the variable `buffer-file-format', and become the default
+;; format for saving the buffer.  To save a buffer in a different format,
+;; change this variable, or use `format-write-file'.
 ;;
 ;; Auto-save files are normally created in the same format as the visited
-;; file, but the variable `auto-save-file-format' can be set to a particularly
-;; fast or otherwise preferred format to be used for auto-saving (or nil to do
-;; no encoding on auto-save files, but then you risk losing any
-;; text-properties in the buffer).
+;; file, but the variable `auto-save-file-format' can be set to a
+;; particularly fast or otherwise preferred format to be used for
+;; auto-saving (or nil to do no encoding on auto-save files, but then you
+;; risk losing any text-properties in the buffer).
 ;;
-;; You can manually translate a buffer into or out of a particular format with
-;; the functions `format-encode-buffer' and `format-decode-buffer'.
-;; To translate just the region use the functions `format-encode-region' and
-;; `format-decode-region'.  
+;; You can manually translate a buffer into or out of a particular format
+;; with the functions `format-encode-buffer' and `format-decode-buffer'.
+;; To translate just the region use the functions `format-encode-region'
+;; and `format-decode-region'.  
 ;;
-;; You can define a new format by writing the encoding and decoding functions,
-;; and adding an entry to `format-alist'.  See enriched.el for an example of
-;; how to implement a file format.  There are various functions defined
-;; in this file that may be useful for writing the encoding and decoding
-;; functions:
-;;  * `format-annotate-region' and `format-deannotate-region' allow a single
-;;     alist of information to be used for encoding and decoding.  The alist
-;;     defines a correspondence between strings in the file ("annotations")
-;;     and text-properties in the buffer.
+;; You can define a new format by writing the encoding and decoding
+;; functions, and adding an entry to `format-alist'.  See enriched.el for
+;; an example of how to implement a file format.  There are various
+;; functions defined in this file that may be useful for writing the
+;; encoding and decoding functions:
+;;  * `format-annotate-region' and `format-deannotate-region' allow a
+;;     single alist of information to be used for encoding and decoding.
+;;     The alist defines a correspondence between strings in the file
+;;     ("annotations") and text-properties in the buffer.
 ;;  * `format-replace-strings' is similarly useful for doing simple
 ;;     string->string translations in a reversible manner.
 
+;;; Code:
+
 (put 'buffer-file-format 'permanent-local t)
 
 (defconst format-alist 
@@ -251,6 +256,43 @@ name as FILE, to write a file of the same old name in that directory."
   (setq buffer-file-format format)
   (write-file filename))
 
+(defun format-find-file (filename format)
+  "Find the file FILE using data format FORMAT.
+If FORMAT is nil then do not do any format conversion."
+  (interactive
+   ;; Same interactive spec as write-file, plus format question.
+   (let* ((file (read-file-name "Find file: "))
+         (fmt (format-read (format "Read file `%s' in format: " 
+                                   (file-name-nondirectory file)))))
+     (list file fmt)))
+  (let ((format-alist nil))
+     (find-file filename))
+  (if format
+      (format-decode-buffer format)))
+
+(defun format-insert-file (filename format &optional beg end)
+  "Insert the contents of file FILE using data format FORMAT.
+If FORMAT is nil then do not do any format conversion.
+The optional third and fourth arguments BEG and END specify
+the part of the file to read.
+
+The return value is like the value of `insert-file-contents':
+a list (ABSOLUTE-FILE-NAME . SIZE)."
+  (interactive
+   ;; Same interactive spec as write-file, plus format question.
+   (let* ((file (read-file-name "Find file: "))
+         (fmt (format-read (format "Read file `%s' in format: " 
+                                   (file-name-nondirectory file)))))
+     (list file fmt)))
+  (let (value size)
+    (let ((format-alist nil))
+      (setq value (insert-file-contents filename nil beg end))
+      (setq size (nth 1 value)))
+    (if format
+       (setq size (format-decode size format)
+             value (cons (car value) size)))
+    value))
+
 (defun format-read (&optional prompt)
   "Read and return the name of a format.
 Return value is a list, like `buffer-file-format'; it may be nil.
@@ -431,7 +473,7 @@ to write these unknown annotations back into the file."
                  (message "Extra closing annotation (%s) in file" name)
              ;; If one is open, but not on the top of the stack, close
              ;; the things in between as well.  Set `found' when the real
-             ;; oneis closed.
+             ;; one is closed.
                (while (not found)
                  (let* ((top (car open-ans)) ; first on stack: should match.
                         (top-name (car top))
@@ -458,8 +500,21 @@ to write these unknown annotations back into the file."
                                                    (assoc r open-ans))
                                                  ans))
                                    nil ; multiple ans not satisfied
-                                 ;; Yes, use the current property name &
-                                 ;; value.  Set loop variables to nil so loop
+                                 ;; Yes, all set.
+                                 ;; If there are multiple annotations going
+                                 ;; into one text property, adjust the 
+                                 ;; begin points of the other annotations
+                                 ;; so that we don't get double marking.
+                                 (let ((to-reset ans)
+                                       this-one)
+                                   (while to-reset
+                                     (setq this-one
+                                           (assoc (car to-reset) 
+                                                  (cdr open-ans)))
+                                     (if this-one
+                                         (setcdr this-one (list loc)))
+                                     (setq to-reset (cdr to-reset))))
+                                 ;; Set loop variables to nil so loop
                                  ;; will exit.
                                  (setq alist nil aalist nil matched t
                                        ;; pop annotation off stack.
@@ -722,7 +777,7 @@ Annotations to open and to close are returned as a dotted pair."
 
 (defun format-annotate-atomic-property-change (prop-alist old new)
   "Internal function annotate a single property change.
-PROP-ALIST is the relevant segement of a TRANSLATIONS list.
+PROP-ALIST is the relevant segment of a TRANSLATIONS list.
 OLD and NEW are the values."
   (cond
    ;; Numerical annotation - use difference