aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/emacs-lisp/cl-print.el115
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el25
2 files changed, 93 insertions, 47 deletions
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index 7c0e81c9349..780b9fb3fe9 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -40,6 +40,10 @@
40 40
41(defvar cl-print--number-table nil) 41(defvar cl-print--number-table nil)
42(defvar cl-print--currently-printing nil) 42(defvar cl-print--currently-printing nil)
43(defvar cl-print--depth nil
44 "Depth of recursion within cl-print functions.
45Compared to `print-level' to determine when to stop recursing.")
46
43 47
44;;;###autoload 48;;;###autoload
45(cl-defgeneric cl-print-object (object stream) 49(cl-defgeneric cl-print-object (object stream)
@@ -52,33 +56,45 @@ call other entry points instead, such as `cl-prin1'."
52 (prin1 object stream)) 56 (prin1 object stream))
53 57
54(cl-defmethod cl-print-object ((object cons) stream) 58(cl-defmethod cl-print-object ((object cons) stream)
55 (let ((car (pop object))) 59 (if (and cl-print--depth (natnump print-level)
56 (if (and (memq car '(\, quote \` \,@ \,.)) 60 (> cl-print--depth print-level))
57 (consp object) 61 (princ "..." stream)
58 (null (cdr object))) 62 (let ((car (pop object))
59 (progn 63 (count 1))
60 (princ (if (eq car 'quote) '\' car) stream) 64 (if (and (memq car '(\, quote \` \,@ \,.))
61 (cl-print-object (car object) stream)) 65 (consp object)
62 (princ "(" stream) 66 (null (cdr object)))
63 (cl-print-object car stream) 67 (progn
64 (while (and (consp object) 68 (princ (if (eq car 'quote) '\' car) stream)
65 (not (cond 69 (cl-print-object (car object) stream))
66 (cl-print--number-table 70 (princ "(" stream)
67 (numberp (gethash object cl-print--number-table))) 71 (cl-print-object car stream)
68 ((memq object cl-print--currently-printing)) 72 (while (and (consp object)
69 (t (push object cl-print--currently-printing) 73 (not (cond
70 nil)))) 74 (cl-print--number-table
71 (princ " " stream) 75 (numberp (gethash object cl-print--number-table)))
72 (cl-print-object (pop object) stream)) 76 ((memq object cl-print--currently-printing))
73 (when object 77 (t (push object cl-print--currently-printing)
74 (princ " . " stream) (cl-print-object object stream)) 78 nil))))
75 (princ ")" stream)))) 79 (princ " " stream)
80 (if (or (not (natnump print-length)) (> print-length count))
81 (cl-print-object (pop object) stream)
82 (princ "..." stream)
83 (setq object nil))
84 (cl-incf count))
85 (when object
86 (princ " . " stream) (cl-print-object object stream))
87 (princ ")" stream)))))
76 88
77(cl-defmethod cl-print-object ((object vector) stream) 89(cl-defmethod cl-print-object ((object vector) stream)
78 (princ "[" stream) 90 (princ "[" stream)
79 (dotimes (i (length object)) 91 (let ((count (length object)))
80 (unless (zerop i) (princ " " stream)) 92 (dotimes (i (if (natnump print-length)
81 (cl-print-object (aref object i) stream)) 93 (min print-length count) count))
94 (unless (zerop i) (princ " " stream))
95 (cl-print-object (aref object i) stream))
96 (when (and (natnump print-length) (< print-length count))
97 (princ " ..." stream)))
82 (princ "]" stream)) 98 (princ "]" stream))
83 99
84(cl-defmethod cl-print-object ((object hash-table) stream) 100(cl-defmethod cl-print-object ((object hash-table) stream)
@@ -180,14 +196,18 @@ into a button whose action shows the function's disassembly.")
180(cl-defmethod cl-print-object ((object cl-structure-object) stream) 196(cl-defmethod cl-print-object ((object cl-structure-object) stream)
181 (princ "#s(" stream) 197 (princ "#s(" stream)
182 (let* ((class (cl-find-class (type-of object))) 198 (let* ((class (cl-find-class (type-of object)))
183 (slots (cl--struct-class-slots class))) 199 (slots (cl--struct-class-slots class))
200 (count (length slots)))
184 (princ (cl--struct-class-name class) stream) 201 (princ (cl--struct-class-name class) stream)
185 (dotimes (i (length slots)) 202 (dotimes (i (if (natnump print-length)
203 (min print-length count) count))
186 (let ((slot (aref slots i))) 204 (let ((slot (aref slots i)))
187 (princ " :" stream) 205 (princ " :" stream)
188 (princ (cl--slot-descriptor-name slot) stream) 206 (princ (cl--slot-descriptor-name slot) stream)
189 (princ " " stream) 207 (princ " " stream)
190 (cl-print-object (aref object (1+ i)) stream)))) 208 (cl-print-object (aref object (1+ i)) stream)))
209 (when (and (natnump print-length) (< print-length count))
210 (princ " ..." stream)))
191 (princ ")" stream)) 211 (princ ")" stream))
192 212
193;;; Circularity and sharing. 213;;; Circularity and sharing.
@@ -198,26 +218,27 @@ into a button whose action shows the function's disassembly.")
198 218
199(cl-defmethod cl-print-object :around (object stream) 219(cl-defmethod cl-print-object :around (object stream)
200 ;; FIXME: Only put such an :around method on types where it's relevant. 220 ;; FIXME: Only put such an :around method on types where it's relevant.
201 (cond 221 (let ((cl-print--depth (if cl-print--depth (1+ cl-print--depth) 1)))
202 (print-circle 222 (cond
203 (let ((n (gethash object cl-print--number-table))) 223 (print-circle
204 (if (not (numberp n)) 224 (let ((n (gethash object cl-print--number-table)))
205 (cl-call-next-method) 225 (if (not (numberp n))
206 (if (> n 0) 226 (cl-call-next-method)
207 ;; Already printed. Just print a reference. 227 (if (> n 0)
208 (progn (princ "#" stream) (princ n stream) (princ "#" stream)) 228 ;; Already printed. Just print a reference.
209 (puthash object (- n) cl-print--number-table) 229 (progn (princ "#" stream) (princ n stream) (princ "#" stream))
210 (princ "#" stream) (princ (- n) stream) (princ "=" stream) 230 (puthash object (- n) cl-print--number-table)
211 (cl-call-next-method))))) 231 (princ "#" stream) (princ (- n) stream) (princ "=" stream)
212 ((let ((already-printing (memq object cl-print--currently-printing))) 232 (cl-call-next-method)))))
213 (when already-printing 233 ((let ((already-printing (memq object cl-print--currently-printing)))
214 ;; Currently printing, just print reference to avoid endless 234 (when already-printing
215 ;; recursion. 235 ;; Currently printing, just print reference to avoid endless
216 (princ "#" stream) 236 ;; recursion.
217 (princ (length (cdr already-printing)) stream)))) 237 (princ "#" stream)
218 (t (let ((cl-print--currently-printing 238 (princ (length (cdr already-printing)) stream))))
219 (cons object cl-print--currently-printing))) 239 (t (let ((cl-print--currently-printing
220 (cl-call-next-method))))) 240 (cons object cl-print--currently-printing)))
241 (cl-call-next-method))))))
221 242
222(defvar cl-print--number-index nil) 243(defvar cl-print--number-index nil)
223 244
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index d986c4015d7..bfce4a16cec 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -47,6 +47,31 @@
47 "\\`(#1=#s(foo 1 2 3) #1#)\\'" 47 "\\`(#1=#s(foo 1 2 3) #1#)\\'"
48 (cl-prin1-to-string (list x x))))))) 48 (cl-prin1-to-string (list x x)))))))
49 49
50(cl-defstruct (cl-print-tests-struct
51 (:constructor cl-print-tests-con))
52 a b c d e)
53
54(ert-deftest cl-print-tests-3 ()
55 "CL printing observes `print-length'."
56 (let ((long-list (make-list 5 'a))
57 (long-vec (make-vector 5 'b))
58 (long-struct (cl-print-tests-con))
59 (print-length 4))
60 (should (equal "(a a a a ...)" (cl-prin1-to-string long-list)))
61 (should (equal "[b b b b ...]" (cl-prin1-to-string long-vec)))
62 (should (equal "#s(cl-print-tests-struct :a nil :b nil :c nil :d nil ...)"
63 (cl-prin1-to-string long-struct)))))
64
65(ert-deftest cl-print-tests-4 ()
66 "CL printing observes `print-level'."
67 (let ((deep-list '(a (b (c (d (e))))))
68 (deep-struct (cl-print-tests-con))
69 (print-level 4))
70 (setf (cl-print-tests-struct-a deep-struct) deep-list)
71 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string deep-list)))
72 (should (equal "#s(cl-print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
73 (cl-prin1-to-string deep-struct)))))
74
50(ert-deftest cl-print-circle () 75(ert-deftest cl-print-circle ()
51 (let ((x '(#1=(a . #1#) #1#))) 76 (let ((x '(#1=(a . #1#) #1#)))
52 (let ((print-circle nil)) 77 (let ((print-circle nil))