aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel LaLiberte1994-03-24 20:26:05 +0000
committerDaniel LaLiberte1994-03-24 20:26:05 +0000
commit65c3c4ed1cd768020669a1f409787effd7110800 (patch)
tree8fc1ca5201dc8bc209bfb36da0fcc0869ff1328b
parente6512bcf1f9ef48cfcf96bb4d5f93e109a784c09 (diff)
downloademacs-65c3c4ed1cd768020669a1f409787effd7110800.tar.gz
emacs-65c3c4ed1cd768020669a1f409787effd7110800.zip
Change "internal" to "original" throughout.
(add-custom-printer, delete-custom-printer) replace old customizers. (with-custom-print) new (custom-prin1-to-string) Made it more robust.
-rw-r--r--lisp/emacs-lisp/cust-print.el667
1 files changed, 406 insertions, 261 deletions
diff --git a/lisp/emacs-lisp/cust-print.el b/lisp/emacs-lisp/cust-print.el
index 863c8daaf3b..28569f05985 100644
--- a/lisp/emacs-lisp/cust-print.el
+++ b/lisp/emacs-lisp/cust-print.el
@@ -3,10 +3,14 @@
3;; Copyright (C) 1992 Free Software Foundation, Inc. 3;; Copyright (C) 1992 Free Software Foundation, Inc.
4 4
5;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu> 5;; Author: Daniel LaLiberte <liberte@cs.uiuc.edu>
6;; Version: 1.0
7;; Adapted-By: ESR 6;; Adapted-By: ESR
8;; Keywords: extensions 7;; Keywords: extensions
9 8
9;; LCD Archive Entry:
10;; cust-print|Daniel LaLiberte|liberte@cs.uiuc.edu
11;; |Handle print-level, print-circle and more.
12;; |$Date: 1994/03/23 20:34:29 $|$Revision: 1.4 $|
13
10;; This file is part of GNU Emacs. 14;; This file is part of GNU Emacs.
11 15
12;; GNU Emacs is free software; you can redistribute it and/or modify 16;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -23,6 +27,42 @@
23;; along with GNU Emacs; see the file COPYING. If not, write to 27;; along with GNU Emacs; see the file COPYING. If not, write to
24;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 28;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
25 29
30;;; ===============================
31;;; $Header: /import/kaplan/kaplan/liberte/Edebug/RCS/cust-print.el,v 1.4 1994/03/23 20:34:29 liberte Exp liberte $
32;;; $Log: cust-print.el,v $
33;;; Revision 1.4 1994/03/23 20:34:29 liberte
34;;; * Change "emacs" to "original" - I just can't decide.
35;;;
36;;; Revision 1.3 1994/02/21 21:25:36 liberte
37;;; * Make custom-prin1-to-string more robust when errors occur.
38;;; * Change "internal" to "emacs".
39;;;
40;;; Revision 1.2 1993/11/22 22:36:36 liberte
41;;; * Simplified and generalized printer customization.
42;;; custom-printers is an alist of (PREDICATE . PRINTER) pairs
43;;; for any data types. The PRINTER function should print to
44;;; `standard-output' add-custom-printer and delete-custom-printer
45;;; change custom-printers.
46;;;
47;;; * Installation function now called install-custom-print. The
48;;; old name is still around for now.
49;;;
50;;; * New macro with-custom-print (added earlier) - executes like
51;;; progn but with custom-print activated temporarily.
52;;;
53;;; * Cleaned up comments for replacements of standardard printers.
54;;;
55;;; * Changed custom-prin1-to-string to use a temporary buffer.
56;;;
57;;; * Option custom-print-vectors (added earlier) - controls whether
58;;; vectors should be printed according to print-length and
59;;; print-length. Emacs doesnt do this, but cust-print would
60;;; otherwise do it only if custom printing is required.
61;;;
62;;; * Uninterned symbols are treated as non-read-equivalent.
63;;;
64
65
26;;; Commentary: 66;;; Commentary:
27 67
28;; This package provides a general print handler for prin1 and princ 68;; This package provides a general print handler for prin1 and princ
@@ -39,27 +79,35 @@
39;; circular lists (where cdrs of lists point back; what is the right 79;; circular lists (where cdrs of lists point back; what is the right
40;; term here?), you can limit the length of printing with 80;; term here?), you can limit the length of printing with
41;; print-length. But car circular lists and circular vectors generate 81;; print-length. But car circular lists and circular vectors generate
42;; the above mentioned untrappable error in Emacs version 18. Version 82;; the above mentioned error in Emacs version 18. Version
43;; 19 will support print-level, but it is often useful to get a better 83;; 19 supports print-level, but it is often useful to get a better
44;; print representation of circular structures; the print-circle 84;; print representation of circular and shared structures; the print-circle
45;; option may be used to print more concise representations. 85;; option may be used to print more concise representations.
46 86
47;; There are two main ways to use this package. First, you may 87;; There are three main ways to use this package. First, you may
48;; replace prin1, princ, and some subroutines that use them by calling 88;; replace prin1, princ, and some subroutines that use them by calling
49;; install-custom-print-funcs so that any use of these functions in 89;; install-custom-print so that any use of these functions in
50;; lisp code will be affected. Second, you could call the custom 90;; Lisp code will be affected; you can later reset with
51;; routines directly, thus only affecting the printing that requires 91;; uninstall-custom-print. Second, you may temporarily install
52;; them. 92;; these functions with the macro with-custom-print. Third, you
53 93;; could call the custom routines directly, thus only affecting the
54;; Note that subroutines which call print subroutines directly will not 94;; printing that requires them.
55;; use the custom print functions. In particular, the evaluation 95
96;; Note that subroutines which call print subroutines directly will
97;; not use the custom print functions. In particular, the evaluation
56;; functions like eval-region call the print subroutines directly. 98;; functions like eval-region call the print subroutines directly.
57;; Therefore, evaluating (aref circ-list 0), which calls error 99;; Therefore, if you evaluate (aref circ-list 0), where circ-list is a
58;; directly (because circ-list is not an array), will jump to the top 100;; circular list rather than an array, aref calls error directly which
59;; level instead of printing the circular list. 101;; will jump to the top level instead of printing the circular list.
102
103;; Uninterned symbols are recognized when print-circle is non-nil,
104;; but they are not printed specially here. Use the cl-packages package
105;; to print according to print-gensym.
60 106
61;; Obviously the right way to implement this custom-print facility 107;; Obviously the right way to implement this custom-print facility is
62;; is in C. Please volunteer since I don't have the time or need. 108;; in C or with hooks into the standard printer. Please volunteer
109;; since I don't have the time or need. More CL-like printing
110;; capabilities could be added in the future.
63 111
64;; Implementation design: we want to use the same list and vector 112;; Implementation design: we want to use the same list and vector
65;; processing algorithm for all versions of prin1 and princ, since how 113;; processing algorithm for all versions of prin1 and princ, since how
@@ -68,31 +116,49 @@
68;; required before the final printing. Thanks to Jamie Zawinski 116;; required before the final printing. Thanks to Jamie Zawinski
69;; for motivation and algorithms. 117;; for motivation and algorithms.
70 118
119
120;;; Code:
71;;========================================================= 121;;=========================================================
72;; export list:
73 122
74;; print-level 123;; If using cl-packages:
75;; print-circle 124
125'(defpackage "cust-print"
126 (:nicknames "CP" "custom-print")
127 (:use "el")
128 (:export
129 print-level
130 print-circle
131
132 install-custom-print
133 uninstall-custom-print
134 custom-print-installed-p
135 with-custom-print
136
137 custom-prin1
138 custom-princ
139 custom-prin1-to-string
140 custom-print
141 custom-format
142 custom-message
143 custom-error
144
145 custom-printers
146 add-custom-printer
147 ))
76 148
77;; custom-print-list 149'(in-package cust-print)
78;; custom-print-vector
79;; add-custom-print-list
80;; add-custom-print-vector
81 150
82;; install-custom-print-funcs 151(require 'backquote)
83;; uninstall-custom-print-funcs
84 152
85;; custom-prin1 153;; Emacs 18 doesnt have defalias.
86;; custom-princ 154;; Provide def for byte compiler.
87;; custom-prin1-to-string 155(defun defalias (symbol func) (fset symbol func))
88;; custom-print 156;; Better def when loaded.
89;; custom-format 157(or (fboundp 'defalias) (fset 'defalias 'fset))
90;; custom-message
91;; custom-error
92 158
93;;; Code: 159
94 160;; Variables:
95(provide 'custom-print) 161;;=========================================================
96 162
97;;(defvar print-length nil 163;;(defvar print-length nil
98;; "*Controls how many elements of a list, at each level, are printed. 164;; "*Controls how many elements of a list, at each level, are printed.
@@ -102,7 +168,7 @@
102 "*Controls how many levels deep a nested data object will print. 168 "*Controls how many levels deep a nested data object will print.
103 169
104If nil, printing proceeds recursively and may lead to 170If nil, printing proceeds recursively and may lead to
105max-lisp-eval-depth being exceeded or an untrappable error may occur: 171max-lisp-eval-depth being exceeded or an error may occur:
106`Apparently circular structure being printed.' 172`Apparently circular structure being printed.'
107Also see `print-length' and `print-circle'. 173Also see `print-length' and `print-circle'.
108 174
@@ -116,7 +182,7 @@ level 1.")
116 "*Controls the printing of recursive structures. 182 "*Controls the printing of recursive structures.
117 183
118If nil, printing proceeds recursively and may lead to 184If nil, printing proceeds recursively and may lead to
119`max-lisp-eval-depth' being exceeded or an untrappable error may occur: 185`max-lisp-eval-depth' being exceeded or an error may occur:
120\"Apparently circular structure being printed.\" Also see 186\"Apparently circular structure being printed.\" Also see
121`print-length' and `print-level'. 187`print-length' and `print-level'.
122 188
@@ -125,67 +191,101 @@ with `#N=' before the first occurrence (in the order of the print
125representation) and `#N#' in place of each subsequent occurrence, 191representation) and `#N#' in place of each subsequent occurrence,
126where N is a positive decimal integer. 192where N is a positive decimal integer.
127 193
128Currently, there is no way to read this representation in Emacs.") 194There is no way to read this representation in standard Emacs,
195but if you need to do so, try the cl-read.el package.")
129 196
130 197
131(defconst custom-print-list 198(defvar custom-print-vectors nil
132 nil 199 "*Non-nil if printing of vectors should obey print-level and print-length.
133 ;; e.g. '((floatp . float-to-string))
134 "An alist for custom printing of lists.
135Pairs are of the form (PRED . CONVERTER). If PREDICATE is true
136for an object, then CONVERTER is called with the object and should
137return a string to be printed with `princ'.
138Also see `custom-print-vector'.")
139 200
140(defconst custom-print-vector 201For Emacs 18, setting print-level, or adding custom print list or
141 nil 202vector handling will make this happen anyway. Emacs 19 obeys
142 "An alist for custom printing of vectors. 203print-level, but not for vectors.")
143Pairs are of the form (PRED . CONVERTER). If PREDICATE is true
144for an object, then CONVERTER is called with the object and should
145return a string to be printed with `princ'.
146Also see `custom-print-list'.")
147 204
205
206;; Custom printers
207;;==========================================================
148 208
149(defun add-custom-print-list (pred converter) 209(defconst custom-printers nil
150 "Add a pair of PREDICATE and CONVERTER to `custom-print-list'. 210 ;; e.g. '((symbolp . pkg::print-symbol))
151Any pair that has the same PREDICATE is first removed." 211 "An alist for custom printing of any type.
152 (setq custom-print-list (cons (cons pred converter) 212Pairs are of the form (PREDICATE . PRINTER). If PREDICATE is true
153 (delq (assq pred custom-print-list) 213for an object, then PRINTER is called with the object.
154 custom-print-list)))) 214PRINTER should print to `standard-output' using cust-print-original-princ
155;; e.g. (add-custom-print-list 'floatp 'float-to-string) 215if the standard printer is sufficient, or cust-print-prin for complex things.
216The PRINTER should return the object being printed.
156 217
218Don't modify this variable directly. Use `add-custom-printer' and
219`delete-custom-printer'")
220;; Should cust-print-original-princ and cust-print-prin be exported symbols?
221;; Or should the standard printers functions be replaced by
222;; CP ones in elisp so that CP internal functions need not be called?
157 223
158(defun add-custom-print-vector (pred converter) 224(defun add-custom-printer (pred printer)
159 "Add a pair of PREDICATE and CONVERTER to `custom-print-vector'. 225 "Add a pair of PREDICATE and PRINTER to `custom-printers'.
160Any pair that has the same PREDICATE is first removed." 226Any pair that has the same PREDICATE is first removed."
161 (setq custom-print-vector (cons (cons pred converter) 227 (setq custom-printers (cons (cons pred printer)
162 (delq (assq pred custom-print-vector) 228 (delq (assq pred custom-printers)
163 custom-print-vector)))) 229 custom-printers)))
164 230 ;; Rather than updating here, we could wait until cust-print-top-level is called.
165 231 (cust-print-update-custom-printers))
232
233(defun delete-custom-printer (pred)
234 "Delete the custom printer associated with PREDICATE."
235 (setq custom-printers (delq (assq pred custom-printers)
236 custom-printers))
237 (cust-print-update-custom-printers))
238
239
240(defun cust-print-use-custom-printer (object)
241 ;; Default function returns nil.
242 nil)
243
244(defun cust-print-update-custom-printers ()
245 ;; Modify the definition of cust-print-use-custom-printer
246 (defalias 'cust-print-use-custom-printer
247 ;; We dont really want to require the byte-compiler.
248 ;; (byte-compile
249 (` (lambda (object)
250 (cond
251 (,@ (mapcar (function
252 (lambda (pair)
253 (` (((, (car pair)) object)
254 ((, (cdr pair)) object)))))
255 custom-printers))
256 ;; Otherwise return nil.
257 (t nil)
258 )))
259 ;; )
260 ))
261
262
263;; Saving and restoring emacs printing routines.
166;;==================================================== 264;;====================================================
167;; Saving and restoring internal printing routines.
168 265
169(defun cust-print-set-function-cell (symbol-pair) 266(defun cust-print-set-function-cell (symbol-pair)
170 (defalias (car symbol-pair) 267 (defalias (car symbol-pair)
171 (symbol-function (car (cdr symbol-pair))))) 268 (symbol-function (car (cdr symbol-pair)))))
172 269
270(defun cust-print-original-princ (object &optional stream)) ; dummy def
173 271
174(if (not (fboundp 'cust-print-internal-prin1)) 272;; Save emacs routines.
273(if (not (fboundp 'cust-print-original-prin1))
175 (mapcar 'cust-print-set-function-cell 274 (mapcar 'cust-print-set-function-cell
176 '((cust-print-internal-prin1 prin1) 275 '((cust-print-original-prin1 prin1)
177 (cust-print-internal-princ princ) 276 (cust-print-original-princ princ)
178 (cust-print-internal-print print) 277 (cust-print-original-print print)
179 (cust-print-internal-prin1-to-string prin1-to-string) 278 (cust-print-original-prin1-to-string prin1-to-string)
180 (cust-print-internal-format format) 279 (cust-print-original-format format)
181 (cust-print-internal-message message) 280 (cust-print-original-message message)
182 (cust-print-internal-error error)))) 281 (cust-print-original-error error))))
183 282
184 283
185(defun install-custom-print-funcs () 284(defalias 'install-custom-print-funcs 'install-custom-print)
285(defun install-custom-print ()
186 "Replace print functions with general, customizable, Lisp versions. 286 "Replace print functions with general, customizable, Lisp versions.
187The internal subroutines are saved away, and you can reinstall them 287The emacs subroutines are saved away, and you can reinstall them
188by running `uninstall-custom-print-funcs'." 288by running `uninstall-custom-print'."
189 (interactive) 289 (interactive)
190 (mapcar 'cust-print-set-function-cell 290 (mapcar 'cust-print-set-function-cell
191 '((prin1 custom-prin1) 291 '((prin1 custom-prin1)
@@ -195,193 +295,227 @@ by running `uninstall-custom-print-funcs'."
195 (format custom-format) 295 (format custom-format)
196 (message custom-message) 296 (message custom-message)
197 (error custom-error) 297 (error custom-error)
198 ))) 298 ))
299 t)
199 300
200(defun uninstall-custom-print-funcs () 301(defalias 'uninstall-custom-print-funcs 'uninstall-custom-print)
201 "Reset print functions to their internal subroutines." 302(defun uninstall-custom-print ()
303 "Reset print functions to their emacs subroutines."
202 (interactive) 304 (interactive)
203 (mapcar 'cust-print-set-function-cell 305 (mapcar 'cust-print-set-function-cell
204 '((prin1 cust-print-internal-prin1) 306 '((prin1 cust-print-original-prin1)
205 (princ cust-print-internal-princ) 307 (princ cust-print-original-princ)
206 (print cust-print-internal-print) 308 (print cust-print-original-print)
207 (prin1-to-string cust-print-internal-prin1-to-string) 309 (prin1-to-string cust-print-original-prin1-to-string)
208 (format cust-print-internal-format) 310 (format cust-print-original-format)
209 (message cust-print-internal-message) 311 (message cust-print-original-message)
210 (error cust-print-internal-error) 312 (error cust-print-original-error)
211 ))) 313 ))
212 314 t)
213 315
316(defalias 'custom-print-funcs-installed-p 'custom-print-installed-p)
317(defun custom-print-installed-p ()
318 "Return t if custom-print is currently installed, nil otherwise."
319 (eq (symbol-function 'custom-prin1) (symbol-function 'prin1)))
320
321(put 'with-custom-print-funcs 'edebug-form-spec '(body))
322(put 'with-custom-print 'edebug-form-spec '(body))
323
324(defalias 'with-custom-print-funcs 'with-custom-print)
325(defmacro with-custom-print (&rest body)
326 "Temporarily install the custom print package while executing BODY."
327 (` (unwind-protect
328 (progn
329 (install-custom-print)
330 (,@ body))
331 (uninstall-custom-print))))
332
333
334;; Lisp replacements for prin1 and princ, and for some subrs that use them
214;;=============================================================== 335;;===============================================================
215;; Lisp replacements for prin1 and princ and for subrs that use prin1 336;; - so far only the printing and formatting subrs.
216;; (or princ) -- so far only the printing and formatting subrs.
217 337
218(defun custom-prin1 (object &optional stream) 338(defun custom-prin1 (object &optional stream)
219 "Replacement for standard `prin1'. 339 "Output the printed representation of OBJECT, any Lisp object.
220Uses the appropriate printer depending on the values of `print-level'
221and `print-circle' (which see).
222
223Output the printed representation of OBJECT, any Lisp object.
224Quoting characters are printed when needed to make output that `read' 340Quoting characters are printed when needed to make output that `read'
225can handle, whenever this is possible. 341can handle, whenever this is possible.
226Output stream is STREAM, or value of `standard-output' (which see)." 342Output stream is STREAM, or value of `standard-output' (which see).
227 (cust-print-top-level object stream 'cust-print-internal-prin1)) 343
344This is the custom-print replacement for the standard `prin1'. It
345uses the appropriate printer depending on the values of `print-level'
346and `print-circle' (which see)."
347 (cust-print-top-level object stream 'cust-print-original-prin1))
228 348
229 349
230(defun custom-princ (object &optional stream) 350(defun custom-princ (object &optional stream)
231 "Same as `custom-prin1' except no quoting." 351 "Output the printed representation of OBJECT, any Lisp object.
232 (cust-print-top-level object stream 'cust-print-internal-princ)) 352No quoting characters are used; no delimiters are printed around
353the contents of strings.
354Output stream is STREAM, or value of `standard-output' (which see).
233 355
234(defvar custom-prin1-chars) 356This is the custom-print replacement for the standard `princ'."
357 (cust-print-top-level object stream 'cust-print-original-princ))
235 358
236(defun custom-prin1-to-string-func (c)
237 "Stream function for `custom-prin1-to-string'."
238 (setq custom-prin1-chars (cons c custom-prin1-chars)))
239 359
240(defun custom-prin1-to-string (object) 360(defun custom-prin1-to-string (object)
241 "Replacement for standard `prin1-to-string'." 361 "Return a string containing the printed representation of OBJECT,
242 (let ((custom-prin1-chars nil)) 362any Lisp object. Quoting characters are used when needed to make output
243 (custom-prin1 object 'custom-prin1-to-string-func) 363that `read' can handle, whenever this is possible.
244 (concat (nreverse custom-prin1-chars)))) 364
365This is the custom-print replacement for the standard `prin1-to-string'."
366 (let ((buf (get-buffer-create " *custom-print-temp*")))
367 ;; We must erase the buffer before printing in case an error
368 ;; occured during the last prin1-to-string and we are in debugger.
369 (save-excursion
370 (set-buffer buf)
371 (erase-buffer))
372 ;; We must be in the current-buffer when the print occurs.
373 (custom-prin1 object buf)
374 (save-excursion
375 (set-buffer buf)
376 (buffer-string)
377 ;; We could erase the buffer again, but why bother?
378 )))
245 379
246 380
247(defun custom-print (object &optional stream) 381(defun custom-print (object &optional stream)
248 "Replacement for standard `print'." 382 "Output the printed representation of OBJECT, with newlines around it.
249 (cust-print-internal-princ "\n") 383Quoting characters are printed when needed to make output that `read'
384can handle, whenever this is possible.
385Output stream is STREAM, or value of `standard-output' (which see).
386
387This is the custom-print replacement for the standard `print'."
388 (cust-print-original-princ "\n" stream)
250 (custom-prin1 object stream) 389 (custom-prin1 object stream)
251 (cust-print-internal-princ "\n")) 390 (cust-print-original-princ "\n" stream))
252 391
253 392
254(defun custom-format (fmt &rest args) 393(defun custom-format (fmt &rest args)
255 "Replacement for standard `format'. 394 "Format a string out of a control-string and arguments.
256 395The first argument is a control string. It, and subsequent arguments
257Calls format after first making strings for list or vector args. 396substituted into it, become the value, which is a string.
258The format specification for such args should be `%s' in any case, so a 397It may contain %s or %d or %c to substitute successive following arguments.
259string argument will also work. The string is generated with 398%s means print an argument as a string, %d means print as number in decimal,
260`custom-prin1-to-string', which quotes quotable characters." 399%c means print a number as a single character.
261 (apply 'cust-print-internal-format fmt 400The argument used by %s must be a string or a symbol;
401the argument used by %d, %b, %o, %x or %c must be a number.
402
403This is the custom-print replacement for the standard `format'. It
404calls the emacs `format' after first making strings for list,
405vector, or symbol args. The format specification for such args should
406be `%s' in any case, so a string argument will also work. The string
407is generated with `custom-prin1-to-string', which quotes quotable
408characters."
409 (apply 'cust-print-original-format fmt
262 (mapcar (function (lambda (arg) 410 (mapcar (function (lambda (arg)
263 (if (or (listp arg) (vectorp arg)) 411 (if (or (listp arg) (vectorp arg) (symbolp arg))
264 (custom-prin1-to-string arg) 412 (custom-prin1-to-string arg)
265 arg))) 413 arg)))
266 args))) 414 args)))
267 415
268 416
269
270(defun custom-message (fmt &rest args) 417(defun custom-message (fmt &rest args)
271 "Replacement for standard `message' that works like `custom-format'." 418 "Print a one-line message at the bottom of the screen.
272 ;; It doesn't work to princ the result of custom-format 419The first argument is a control string.
420It may contain %s or %d or %c to print successive following arguments.
421%s means print an argument as a string, %d means print as number in decimal,
422%c means print a number as a single character.
423The argument used by %s must be a string or a symbol;
424the argument used by %d or %c must be a number.
425
426This is the custom-print replacement for the standard `message'.
427See `custom-format' for the details."
428 ;; It doesn't work to princ the result of custom-format as in:
429 ;; (cust-print-original-princ (apply 'custom-format fmt args))
273 ;; because the echo area requires special handling 430 ;; because the echo area requires special handling
274 ;; to avoid duplicating the output. cust-print-internal-message does it right. 431 ;; to avoid duplicating the output.
275 ;; (cust-print-internal-princ (apply 'custom-format fmt args)) 432 ;; cust-print-original-message does it right.
276 (apply 'cust-print-internal-message fmt 433 (apply 'cust-print-original-message fmt
277 (mapcar (function (lambda (arg) 434 (mapcar (function (lambda (arg)
278 (if (or (listp arg) (vectorp arg)) 435 (if (or (listp arg) (vectorp arg) (symbolp arg))
279 (custom-prin1-to-string arg) 436 (custom-prin1-to-string arg)
280 arg))) 437 arg)))
281 args))) 438 args)))
282 439
283 440
284(defun custom-error (fmt &rest args) 441(defun custom-error (fmt &rest args)
285 "Replacement for standard `error' that uses `custom-format'" 442 "Signal an error, making error message by passing all args to `format'.
443
444This is the custom-print replacement for the standard `error'.
445See `custom-format' for the details."
286 (signal 'error (list (apply 'custom-format fmt args)))) 446 (signal 'error (list (apply 'custom-format fmt args))))
287 447
288 448
289;;========================================= 449
290;; Support for custom prin1 and princ 450;; Support for custom prin1 and princ
451;;=========================================
291 452
453;; Defs to quiet byte-compiler.
292(defvar circle-table) 454(defvar circle-table)
293(defvar circle-tree) 455(defvar cust-print-current-level)
294(defvar circle-level) 456
457(defun cust-print-original-printer (object)) ; One of the standard printers.
458(defun cust-print-low-level-prin (object)) ; Used internally.
459(defun cust-print-prin (object)) ; Call this to print recursively.
295 460
296(defun cust-print-top-level (object stream internal-printer) 461(defun cust-print-top-level (object stream emacs-printer)
297 "Set up for printing." 462 ;; Set up for printing.
298 (let ((standard-output (or stream standard-output)) 463 (let ((standard-output (or stream standard-output))
299 (circle-table (and print-circle (cust-print-preprocess-circle-tree object))) 464 ;; circle-table will be non-nil if anything is circular.
300 (circle-level (or print-level -1)) 465 (circle-table (and print-circle
301 ) 466 (cust-print-preprocess-circle-tree object)))
467 (cust-print-current-level (or print-level -1)))
302 468
303 (defalias 'cust-print-internal-printer internal-printer) 469 (defalias 'cust-print-original-printer emacs-printer)
304 (defalias 'cust-print-low-level-prin 470 (defalias 'cust-print-low-level-prin
305 (cond 471 (cond
306 ((or custom-print-list 472 ((or custom-printers
307 custom-print-vector 473 circle-table
308 print-level ; comment out for version 19 474 print-level ; comment out for version 19
309 ) 475 ;; Emacs doesn't use print-level or print-length
310 'cust-print-custom-object) 476 ;; for vectors, but custom-print can.
311 (circle-table 477 (if custom-print-vectors
312 'cust-print-object) 478 (or print-level print-length)))
313 (t 'cust-print-internal-printer))) 479 'cust-print-print-object)
314 (defalias 'cust-print-prin (if circle-table 'cust-print-circular 'cust-print-low-level-prin)) 480 (t 'cust-print-original-printer)))
481 (defalias 'cust-print-prin
482 (if circle-table 'cust-print-print-circular 'cust-print-low-level-prin))
315 483
316 (cust-print-prin object) 484 (cust-print-prin object)
317 object)) 485 object))
318 486
319 487
320;; Test object type and print accordingly. 488(defun cust-print-print-object (object)
321(defun cust-print-object (object) 489 ;; Test object type and print accordingly.
322 ;; Could be called as either cust-print-low-level-prin or cust-print-prin. 490 ;; Could be called as either cust-print-low-level-prin or cust-print-prin.
323 (cond 491 (cond
324 ((null object) (cust-print-internal-printer object)) 492 ((null object) (cust-print-original-printer object))
493 ((cust-print-use-custom-printer object) object)
325 ((consp object) (cust-print-list object)) 494 ((consp object) (cust-print-list object))
326 ((vectorp object) (cust-print-vector object)) 495 ((vectorp object) (cust-print-vector object))
327 ;; All other types, just print. 496 ;; All other types, just print.
328 (t (cust-print-internal-printer object)))) 497 (t (cust-print-original-printer object))))
329
330 498
331;; Test object type and print accordingly.
332(defun cust-print-custom-object (object)
333 ;; Could be called as either cust-print-low-level-prin or cust-print-prin.
334 (cond
335 ((null object) (cust-print-internal-printer object))
336 499
337 ((consp object) 500(defun cust-print-print-circular (object)
338 (or (and custom-print-list 501 ;; Printer for `prin1' and `princ' that handles circular structures.
339 (cust-print-custom-object1 object custom-print-list)) 502 ;; If OBJECT appears multiply, and has not yet been printed,
340 (cust-print-list object))) 503 ;; prefix with label; if it has been printed, use `#N#' instead.
341 504 ;; Otherwise, print normally.
342 ((vectorp object)
343 (or (and custom-print-vector
344 (cust-print-custom-object1 object custom-print-vector))
345 (cust-print-vector object)))
346
347 ;; All other types, just print.
348 (t (cust-print-internal-printer object))))
349
350
351;; Helper for cust-print-custom-object.
352;; Print the custom OBJECT using the custom type ALIST.
353;; For the first predicate that matches the object, the corresponding
354;; converter is evaluated with the object and the string that results is
355;; printed with princ. Return nil if no predicate matches the object.
356(defun cust-print-custom-object1 (object alist)
357 (while (and alist (not (funcall (car (car alist)) object)))
358 (setq alist (cdr alist)))
359 ;; If alist is not null, then something matched.
360 (if alist
361 (cust-print-internal-princ
362 (funcall (cdr (car alist)) object) ; returns string
363 )))
364
365
366(defun cust-print-circular (object)
367 "Printer for `prin1' and `princ' that handles circular structures.
368If OBJECT appears multiply, and has not yet been printed,
369prefix with label; if it has been printed, use `#N#' instead.
370Otherwise, print normally."
371 (let ((tag (assq object circle-table))) 505 (let ((tag (assq object circle-table)))
372 (if tag 506 (if tag
373 (let ((id (cdr tag))) 507 (let ((id (cdr tag)))
374 (if (> id 0) 508 (if (> id 0)
375 (progn 509 (progn
376 ;; Already printed, so just print id. 510 ;; Already printed, so just print id.
377 (cust-print-internal-princ "#") 511 (cust-print-original-princ "#")
378 (cust-print-internal-princ id) 512 (cust-print-original-princ id)
379 (cust-print-internal-princ "#")) 513 (cust-print-original-princ "#"))
380 ;; Not printed yet, so label with id and print object. 514 ;; Not printed yet, so label with id and print object.
381 (setcdr tag (- id)) ; mark it as printed 515 (setcdr tag (- id)) ; mark it as printed
382 (cust-print-internal-princ "#") 516 (cust-print-original-princ "#")
383 (cust-print-internal-princ (- id)) 517 (cust-print-original-princ (- id))
384 (cust-print-internal-princ "=") 518 (cust-print-original-princ "=")
385 (cust-print-low-level-prin object) 519 (cust-print-low-level-prin object)
386 )) 520 ))
387 ;; Not repeated in structure. 521 ;; Not repeated in structure.
@@ -391,18 +525,18 @@ Otherwise, print normally."
391;;================================================ 525;;================================================
392;; List and vector processing for print functions. 526;; List and vector processing for print functions.
393 527
394;; Print a list using print-length, print-level, and print-circle.
395(defun cust-print-list (list) 528(defun cust-print-list (list)
396 (if (= circle-level 0) 529 ;; Print a list using print-length, print-level, and print-circle.
397 (cust-print-internal-princ "#") 530 (if (= cust-print-current-level 0)
398 (let ((circle-level (1- circle-level))) 531 (cust-print-original-princ "#")
399 (cust-print-internal-princ "(") 532 (let ((cust-print-current-level (1- cust-print-current-level)))
533 (cust-print-original-princ "(")
400 (let ((length (or print-length 0))) 534 (let ((length (or print-length 0)))
401 535
402 ;; Print the first element always (even if length = 0). 536 ;; Print the first element always (even if length = 0).
403 (cust-print-prin (car list)) 537 (cust-print-prin (car list))
404 (setq list (cdr list)) 538 (setq list (cdr list))
405 (if list (cust-print-internal-princ " ")) 539 (if list (cust-print-original-princ " "))
406 (setq length (1- length)) 540 (setq length (1- length))
407 541
408 ;; Print the rest of the elements. 542 ;; Print the rest of the elements.
@@ -414,26 +548,26 @@ Otherwise, print normally."
414 (setq list (cdr list))) 548 (setq list (cdr list)))
415 549
416 ;; cdr is not a list, or it is in circle-table. 550 ;; cdr is not a list, or it is in circle-table.
417 (cust-print-internal-princ ". ") 551 (cust-print-original-princ ". ")
418 (cust-print-prin list) 552 (cust-print-prin list)
419 (setq list nil)) 553 (setq list nil))
420 554
421 (setq length (1- length)) 555 (setq length (1- length))
422 (if list (cust-print-internal-princ " "))) 556 (if list (cust-print-original-princ " ")))
423 557
424 (if (and list (= length 0)) (cust-print-internal-princ "...")) 558 (if (and list (= length 0)) (cust-print-original-princ "..."))
425 (cust-print-internal-princ ")")))) 559 (cust-print-original-princ ")"))))
426 list) 560 list)
427 561
428 562
429;; Print a vector according to print-length, print-level, and print-circle.
430(defun cust-print-vector (vector) 563(defun cust-print-vector (vector)
431 (if (= circle-level 0) 564 ;; Print a vector according to print-length, print-level, and print-circle.
432 (cust-print-internal-princ "#") 565 (if (= cust-print-current-level 0)
433 (let ((circle-level (1- circle-level)) 566 (cust-print-original-princ "#")
567 (let ((cust-print-current-level (1- cust-print-current-level))
434 (i 0) 568 (i 0)
435 (len (length vector))) 569 (len (length vector)))
436 (cust-print-internal-princ "[") 570 (cust-print-original-princ "[")
437 571
438 (if print-length 572 (if print-length
439 (setq len (min print-length len))) 573 (setq len (min print-length len)))
@@ -441,16 +575,17 @@ Otherwise, print normally."
441 (while (< i len) 575 (while (< i len)
442 (cust-print-prin (aref vector i)) 576 (cust-print-prin (aref vector i))
443 (setq i (1+ i)) 577 (setq i (1+ i))
444 (if (< i (length vector)) (cust-print-internal-princ " "))) 578 (if (< i (length vector)) (cust-print-original-princ " ")))
445 579
446 (if (< i (length vector)) (cust-print-internal-princ "...")) 580 (if (< i (length vector)) (cust-print-original-princ "..."))
447 (cust-print-internal-princ "]") 581 (cust-print-original-princ "]")
448 )) 582 ))
449 vector) 583 vector)
450 584
451 585
452;;================================== 586
453;; Circular structure preprocessing 587;; Circular structure preprocessing
588;;==================================
454 589
455(defun cust-print-preprocess-circle-tree (object) 590(defun cust-print-preprocess-circle-tree (object)
456 ;; Fill up the table. 591 ;; Fill up the table.
@@ -492,7 +627,11 @@ Otherwise, print normally."
492(defun cust-print-walk-circle-tree (object) 627(defun cust-print-walk-circle-tree (object)
493 (let (read-equivalent-p tag) 628 (let (read-equivalent-p tag)
494 (while object 629 (while object
495 (setq read-equivalent-p (or (numberp object) (symbolp object)) 630 (setq read-equivalent-p
631 (or (numberp object)
632 (and (symbolp object)
633 ;; Check if it is uninterned.
634 (eq object (intern-soft (symbol-name object)))))
496 tag (and (not read-equivalent-p) 635 tag (and (not read-equivalent-p)
497 (assq object (cdr circle-table)))) 636 (assq object (cdr circle-table))))
498 (cond (tag 637 (cond (tag
@@ -525,49 +664,55 @@ Otherwise, print normally."
525 (cust-print-walk-circle-tree (aref object j)) 664 (cust-print-walk-circle-tree (aref object j))
526 (setq j (1+ j)))))))))) 665 (setq j (1+ j))))))))))
527 666
667
668;; Example.
669;;=======================================
528 670
671'(progn
672 (progn
673 ;; Create some circular structures.
674 (setq circ-sym (let ((x (make-symbol "FOO"))) (list x x)))
675 (setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f))
676 (setcar (nthcdr 3 circ-list) circ-list)
677 (aset (nth 2 circ-list) 2 circ-list)
678 (setq dotted-circ-list (list 'a 'b 'c))
679 (setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list)
680 (setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7))
681 (aset circ-vector 5 (make-symbol "-gensym-"))
682 (setcar (cdr (aref circ-vector 4)) (aref circ-vector 5))
683 nil)
684
685 (install-custom-print)
686 ;; (setq print-circle t)
687
688 (let ((print-circle t))
689 (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)")
690 (error "circular object with array printing")))
691
692 (let ((print-circle t))
693 (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)")
694 (error "circular object with array printing")))
695
696 (let* ((print-circle t)
697 (x (list 'p 'q))
698 (y (list (list 'a 'b) x 'foo x)))
699 (setcdr (cdr (cdr (cdr y))) (cdr y))
700 (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))"
701 )
702 (error "circular list example from CL manual")))
529 703
530;;======================================= 704 (let ((print-circle nil))
705 ;; cl-packages.el is required to print uninterned symbols like #:FOO.
706 ;; (require 'cl-packages)
707 (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)")
708 (error "uninterned symbols in list")))
709 (let ((print-circle t))
710 (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)")
711 (error "circular uninterned symbols in list")))
531 712
532;; Example. 713 (uninstall-custom-print)
714 )
533 715
534;;;; Create some circular structures. 716(provide 'cust-print)
535;;(setq circ-sym (let ((x (make-symbol "FOO"))) (list x x)))
536;;(setq circ-list (list 'a 'b (vector 1 2 3 4) 'd 'e 'f))
537;;(setcar (nthcdr 3 circ-list) circ-list)
538;;(aset (nth 2 circ-list) 2 circ-list)
539;;(setq dotted-circ-list (list 'a 'b 'c))
540;;(setcdr (cdr (cdr dotted-circ-list)) dotted-circ-list)
541;;(setq circ-vector (vector 1 2 3 4 (list 'a 'b 'c 'd) 6 7))
542;;(aset circ-vector 5 (make-symbol "-gensym-"))
543;;(setcar (cdr (aref circ-vector 4)) (aref circ-vector 5))
544
545;;(install-custom-print-funcs)
546;;;; (setq print-circle t)
547
548;;(let ((print-circle t))
549;; (or (equal (prin1-to-string circ-list) "#1=(a b [1 2 #1# 4] #1# e f)")
550;; (error "circular object with array printing")))
551
552;;(let ((print-circle t))
553;; (or (equal (prin1-to-string dotted-circ-list) "#1=(a b c . #1#)")
554;; (error "circular object with array printing")))
555
556;;(let* ((print-circle t)
557;; (x (list 'p 'q))
558;; (y (list (list 'a 'b) x 'foo x)))
559;; (setcdr (cdr (cdr (cdr y))) (cdr y))
560;; (or (equal (prin1-to-string y) "((a b) . #1=(#2=(p q) foo #2# . #1#))"
561;; )
562;; (error "circular list example from CL manual")))
563
564;;;; There's no special handling of uninterned symbols in custom-print.
565;;(let ((print-circle nil))
566;; (or (equal (prin1-to-string circ-sym) "(#:FOO #:FOO)")
567;; (error "uninterned symbols in list")))
568;;(let ((print-circle t))
569;; (or (equal (prin1-to-string circ-sym) "(#1=FOO #1#)")
570;; (error "circular uninterned symbols in list")))
571;;(uninstall-custom-print-funcs)
572 717
573;;; cust-print.el ends here 718;;; cust-print.el ends here