aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lisp/emacs-lisp/cl-print.el102
-rw-r--r--test/lisp/emacs-lisp/cl-print-tests.el53
2 files changed, 152 insertions, 3 deletions
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el
index e638e58275a..337efa465a0 100644
--- a/lisp/emacs-lisp/cl-print.el
+++ b/lisp/emacs-lisp/cl-print.el
@@ -285,6 +285,95 @@ into a button whose action shows the function's disassembly.")
285 (princ " " stream) 285 (princ " " stream)
286 (cl-print-insert-ellipsis object limit stream)))) 286 (cl-print-insert-ellipsis object limit stream))))
287 287
288(cl-defmethod cl-print-object ((object string) stream)
289 (unless stream (setq stream standard-output))
290 (let* ((has-properties (or (text-properties-at 0 object)
291 (next-property-change 0 object)))
292 (len (length object))
293 (limit (if (natnump print-length) (min print-length len) len)))
294 (if (and has-properties
295 cl-print--depth
296 (natnump print-level)
297 (> cl-print--depth print-level))
298 (cl-print-insert-ellipsis object 0 stream)
299 ;; Print all or part of the string
300 (when has-properties
301 (princ "#(" stream))
302 (if (= limit len)
303 (prin1 (if has-properties (substring-no-properties object) object)
304 stream)
305 (let ((part (concat (substring-no-properties object 0 limit) "...")))
306 (prin1 part stream)
307 (when (bufferp stream)
308 (with-current-buffer stream
309 (cl-print-propertize-ellipsis object limit
310 (- (point) 4)
311 (- (point) 1) stream)))))
312 ;; Print the property list.
313 (when has-properties
314 (let* ((interval-limit (and (natnump print-length)
315 (max 1 (/ print-length 3))))
316 (interval-count 0)
317 (start-pos (if (text-properties-at 0 object)
318 0 (next-property-change 0 object)))
319 (end-pos (next-property-change start-pos object len)))
320 (while (and (or (null interval-limit)
321 (< interval-count interval-limit))
322 (< start-pos len))
323 (let ((props (text-properties-at start-pos object)))
324 (when props
325 (princ " " stream) (princ start-pos stream)
326 (princ " " stream) (princ end-pos stream)
327 (princ " " stream) (cl-print-object props stream)
328 (cl-incf interval-count))
329 (setq start-pos end-pos
330 end-pos (next-property-change start-pos object len))))
331 (when (< start-pos len)
332 (princ " " stream)
333 (cl-print-insert-ellipsis object (list start-pos) stream)))
334 (princ ")" stream)))))
335
336(cl-defmethod cl-print-object-contents ((object string) start stream)
337 ;; If START is an integer, it is an index into the string, and the
338 ;; ellipsis that needs to be expanded is part of the string. If
339 ;; START is a cons, its car is an index into the string, and the
340 ;; ellipsis that needs to be expanded is in the property list.
341 (let* ((len (length object)))
342 (if (atom start)
343 ;; Print part of the string.
344 (let* ((limit (if (natnump print-length)
345 (min (+ start print-length) len) len))
346 (substr (substring-no-properties object start limit))
347 (printed (prin1-to-string substr))
348 (trimmed (substring printed 1 (1- (length printed)))))
349 (princ trimmed)
350 (when (< limit len)
351 (cl-print-insert-ellipsis object limit stream)))
352
353 ;; Print part of the property list.
354 (let* ((first t)
355 (interval-limit (and (natnump print-length)
356 (max 1 (/ print-length 3))))
357 (interval-count 0)
358 (start-pos (car start))
359 (end-pos (next-property-change start-pos object len)))
360 (while (and (or (null interval-limit)
361 (< interval-count interval-limit))
362 (< start-pos len))
363 (let ((props (text-properties-at start-pos object)))
364 (when props
365 (if first
366 (setq first nil)
367 (princ " " stream))
368 (princ start-pos stream)
369 (princ " " stream) (princ end-pos stream)
370 (princ " " stream) (cl-print-object props stream)
371 (cl-incf interval-count))
372 (setq start-pos end-pos
373 end-pos (next-property-change start-pos object len))))
374 (when (< start-pos len)
375 (princ " " stream)
376 (cl-print-insert-ellipsis object (list start-pos) stream))))))
288 377
289;;; Circularity and sharing. 378;;; Circularity and sharing.
290 379
@@ -346,8 +435,17 @@ into a button whose action shows the function's disassembly.")
346 (push cdr stack) 435 (push cdr stack)
347 (push car stack)) 436 (push car stack))
348 ((pred stringp) 437 ((pred stringp)
349 ;; We presumably won't print its text-properties. 438 (let* ((len (length object))
350 nil) 439 (start (if (text-properties-at 0 object)
440 0 (next-property-change 0 object)))
441 (end (and start
442 (next-property-change start object len))))
443 (while (and start (< start len))
444 (let ((props (text-properties-at start object)))
445 (when props
446 (push props stack))
447 (setq start end
448 end (next-property-change start object len))))))
351 ((or (pred arrayp) (pred byte-code-function-p)) 449 ((or (pred arrayp) (pred byte-code-function-p))
352 ;; FIXME: Inefficient for char-tables! 450 ;; FIXME: Inefficient for char-tables!
353 (dotimes (i (length object)) 451 (dotimes (i (length object))
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el
index 2b5eb3402bf..7594d2466b5 100644
--- a/test/lisp/emacs-lisp/cl-print-tests.el
+++ b/test/lisp/emacs-lisp/cl-print-tests.el
@@ -56,11 +56,13 @@
56 (let ((long-list (make-list 5 'a)) 56 (let ((long-list (make-list 5 'a))
57 (long-vec (make-vector 5 'b)) 57 (long-vec (make-vector 5 'b))
58 (long-struct (cl-print-tests-con)) 58 (long-struct (cl-print-tests-con))
59 (long-string (make-string 5 ?a))
59 (print-length 4)) 60 (print-length 4))
60 (should (equal "(a a a a ...)" (cl-prin1-to-string long-list))) 61 (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 "[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 (should (equal "#s(cl-print-tests-struct :a nil :b nil :c nil :d nil ...)"
63 (cl-prin1-to-string long-struct))))) 64 (cl-prin1-to-string long-struct)))
65 (should (equal "\"aaaa...\"" (cl-prin1-to-string long-string)))))
64 66
65(ert-deftest cl-print-tests-4 () 67(ert-deftest cl-print-tests-4 ()
66 "CL printing observes `print-level'." 68 "CL printing observes `print-level'."
@@ -68,11 +70,16 @@
68 (buried-vector '(a (b (c (d [e]))))) 70 (buried-vector '(a (b (c (d [e])))))
69 (deep-struct (cl-print-tests-con)) 71 (deep-struct (cl-print-tests-con))
70 (buried-struct `(a (b (c (d ,deep-struct))))) 72 (buried-struct `(a (b (c (d ,deep-struct)))))
73 (buried-string '(a (b (c (d #("hello" 0 5 (cl-print-test t)))))))
74 (buried-simple-string '(a (b (c (d "hello")))))
71 (print-level 4)) 75 (print-level 4))
72 (setf (cl-print-tests-struct-a deep-struct) deep-list) 76 (setf (cl-print-tests-struct-a deep-struct) deep-list)
73 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string deep-list))) 77 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string deep-list)))
74 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-vector))) 78 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-vector)))
75 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-struct))) 79 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-struct)))
80 (should (equal "(a (b (c (d ...))))" (cl-prin1-to-string buried-string)))
81 (should (equal "(a (b (c (d \"hello\"))))"
82 (cl-prin1-to-string buried-simple-string)))
76 (should (equal "#s(cl-print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)" 83 (should (equal "#s(cl-print-tests-struct :a (a (b (c ...))) :b nil :c nil :d nil :e nil)"
77 (cl-prin1-to-string deep-struct))))) 84 (cl-prin1-to-string deep-struct)))))
78 85
@@ -86,6 +93,35 @@
86 (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))" 93 (should (equal "((quote a) (function b) (\\` ((\\, c) (\\,@ d))))"
87 (cl-prin1-to-string quoted-stuff)))))) 94 (cl-prin1-to-string quoted-stuff))))))
88 95
96(ert-deftest cl-print-tests-strings ()
97 "CL printing prints strings and propertized strings."
98 (let* ((str1 "abcdefghij")
99 (str2 #("abcdefghij" 3 6 (bold t) 7 9 (italic t)))
100 (str3 #("abcdefghij" 0 10 (test t)))
101 (obj '(a b))
102 ;; Since the byte compiler reuses string literals,
103 ;; and the put-text-property call is destructive, use
104 ;; copy-sequence to make a new string.
105 (str4 (copy-sequence "abcdefghij")))
106 (put-text-property 0 5 'test obj str4)
107 (put-text-property 7 10 'test obj str4)
108
109 (should (equal "\"abcdefghij\"" (cl-prin1-to-string str1)))
110 (should (equal "#(\"abcdefghij\" 3 6 (bold t) 7 9 (italic t))"
111 (cl-prin1-to-string str2)))
112 (should (equal "#(\"abcdefghij\" 0 10 (test t))"
113 (cl-prin1-to-string str3)))
114 (let ((print-circle nil))
115 (should
116 (equal
117 "#(\"abcdefghij\" 0 5 (test (a b)) 7 10 (test (a b)))"
118 (cl-prin1-to-string str4))))
119 (let ((print-circle t))
120 (should
121 (equal
122 "#(\"abcdefghij\" 0 5 (test #1=(a b)) 7 10 (test #1#))"
123 (cl-prin1-to-string str4))))))
124
89(ert-deftest cl-print-tests-ellipsis-cons () 125(ert-deftest cl-print-tests-ellipsis-cons ()
90 "Ellipsis expansion works in conses." 126 "Ellipsis expansion works in conses."
91 (let ((print-length 4) 127 (let ((print-length 4)
@@ -113,6 +149,21 @@
113 (cl-print-tests-check-ellipsis-expansion 149 (cl-print-tests-check-ellipsis-expansion
114 [a [b [c [d [e]]]]] "[a [b [c ...]]]" "[d [e]]"))) 150 [a [b [c [d [e]]]]] "[a [b [c ...]]]" "[d [e]]")))
115 151
152(ert-deftest cl-print-tests-ellipsis-string ()
153 "Ellipsis expansion works in strings."
154 (let ((print-length 4)
155 (print-level 3))
156 (cl-print-tests-check-ellipsis-expansion
157 "abcdefg" "\"abcd...\"" "efg")
158 (cl-print-tests-check-ellipsis-expansion
159 "abcdefghijk" "\"abcd...\"" "efgh...")
160 (cl-print-tests-check-ellipsis-expansion
161 '(1 (2 (3 #("abcde" 0 5 (test t)))))
162 "(1 (2 (3 ...)))" "#(\"abcd...\" 0 5 (test t))")
163 (cl-print-tests-check-ellipsis-expansion
164 #("abcd" 0 1 (bold t) 1 2 (invisible t) 3 4 (italic t))
165 "#(\"abcd\" 0 1 (bold t) ...)" "1 2 (invisible t) ...")))
166
116(ert-deftest cl-print-tests-ellipsis-struct () 167(ert-deftest cl-print-tests-ellipsis-struct ()
117 "Ellipsis expansion works in structures." 168 "Ellipsis expansion works in structures."
118 (let ((print-length 4) 169 (let ((print-length 4)