-;;; 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
(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.
(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))
(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.
(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