aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGemini Lasswell2018-05-27 11:38:00 -0700
committerGemini Lasswell2018-06-04 08:57:10 -0700
commit5d448ca98cd59287b2c20175e2e6638f1922db57 (patch)
treec7db77439fede92045ab369392acd046d6824b96
parent03697e648c080f6b007b6ef8443fd4448bc52364 (diff)
downloademacs-5d448ca98cd59287b2c20175e2e6638f1922db57.tar.gz
emacs-5d448ca98cd59287b2c20175e2e6638f1922db57.zip
Make cl-print respect print-level and print-length (bug#31559)
* lisp/emacs-lisp/cl-print.el (cl-print--depth): New variable. (cl-print-object) <cons>: Print ellipsis if printing depth greater than 'print-level' or length of list greater than 'print-length'. (cl-print-object) <vector>: Truncate printing with ellipsis if vector is longer than 'print-length'. (cl-print-object) <cl-structure-object>: Truncate printing with ellipsis if structure has more slots than 'print-length'. (cl-print-object) <:around>: Bind 'cl-print--depth'. * test/lisp/emacs-lisp/cl-print-tests.el (cl-print-tests-3, cl-print-tests-4): New tests. (cherry picked from commit 0f48d18fd2a30f29cc3592a835d2a2254c9b0afb)
-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))