diff options
| author | Gemini Lasswell | 2018-07-14 08:05:51 -0700 |
|---|---|---|
| committer | Gemini Lasswell | 2018-08-03 08:53:02 -0700 |
| commit | a3ba34aeac1b41ca5d12bfe5644d3fdfa894ddda (patch) | |
| tree | 3a04c22cc9f55cc2c8b629f9b4df9f316c8d2117 | |
| parent | 2ede75c49b62439e15be3ab8be2c14594f846da6 (diff) | |
| download | emacs-a3ba34aeac1b41ca5d12bfe5644d3fdfa894ddda.tar.gz emacs-a3ba34aeac1b41ca5d12bfe5644d3fdfa894ddda.zip | |
Add new command to expand all "..."s in a backtrace frame
* doc/lispref/debugging.texi (Backtraces): Document new keybinding.
* lisp/emacs-lisp/backtrace.el (backtrace-line-length): Add the
option of unlimited line length.
(backtrace--match-ellipsis-in-string): Add a comment to explain
why this function is necessary.
(backtrace-mode-map): Add keybinding for 'backtrace-expand-ellipses'.
(backtrace-expand-ellipsis): Use 'cl-print-to-string-with-limit'.
(backtrace-expand-ellipses): New command.
(backtrace-print-to-string): Use 'cl-print-to-string-with-limit'.
Tag the printed forms with a gensym instead of the values of
print-length and print-level.
(backtrace--print): Add 'stream' argument.
* test/lisp/emacs-lisp/backtrace-tests.el
(backtrace-tests--expand-ellipsis): Make the test less dependent
on the implementation.
(backtrace-tests--expand-ellipses): New test.
Move the fitting of a printed representation into a limited number of
characters using appropriate values of print-level and print-length
from 'backtrace-print-to-string' to cl-print.el for future use by
other parts of Emacs.
* lisp/emacs-lisp/cl-print.el (cl-print-to-string-with-limit): New
function.
* test/lisp/emacs-lisp/cl-print-tests.el
(cl-print-tests-print-to-string-with-limit): New test.
| -rw-r--r-- | doc/lispref/debugging.texi | 3 | ||||
| -rw-r--r-- | lisp/emacs-lisp/backtrace.el | 124 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cl-print.el | 40 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/backtrace-tests.el | 60 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/cl-print-tests.el | 36 |
5 files changed, 192 insertions, 71 deletions
diff --git a/doc/lispref/debugging.texi b/doc/lispref/debugging.texi index 5230854cc7a..87429a67ba9 100644 --- a/doc/lispref/debugging.texi +++ b/doc/lispref/debugging.texi | |||
| @@ -457,6 +457,9 @@ Collapse the top-level Lisp form at point back to a single line. | |||
| 457 | @item # | 457 | @item # |
| 458 | Toggle @code{print-circle} for the frame at point. | 458 | Toggle @code{print-circle} for the frame at point. |
| 459 | 459 | ||
| 460 | @item . | ||
| 461 | Expand all the forms abbreviated with ``...'' in the frame at point. | ||
| 462 | |||
| 460 | @end table | 463 | @end table |
| 461 | 464 | ||
| 462 | @node Debugger Commands | 465 | @node Debugger Commands |
diff --git a/lisp/emacs-lisp/backtrace.el b/lisp/emacs-lisp/backtrace.el index 779feb43075..da5a777177d 100644 --- a/lisp/emacs-lisp/backtrace.el +++ b/lisp/emacs-lisp/backtrace.el | |||
| @@ -55,7 +55,8 @@ order to debug the code that does fontification." | |||
| 55 | "Target length for lines in Backtrace buffers. | 55 | "Target length for lines in Backtrace buffers. |
| 56 | Backtrace mode will attempt to abbreviate printing of backtrace | 56 | Backtrace mode will attempt to abbreviate printing of backtrace |
| 57 | frames to make them shorter than this, but success is not | 57 | frames to make them shorter than this, but success is not |
| 58 | guaranteed." | 58 | guaranteed. If set to nil or zero, Backtrace mode will not |
| 59 | abbreviate the forms it prints." | ||
| 59 | :type 'integer | 60 | :type 'integer |
| 60 | :group 'backtrace | 61 | :group 'backtrace |
| 61 | :version "27.1") | 62 | :version "27.1") |
| @@ -146,6 +147,9 @@ fontifies.") | |||
| 146 | 147 | ||
| 147 | (defun backtrace--match-ellipsis-in-string (bound) | 148 | (defun backtrace--match-ellipsis-in-string (bound) |
| 148 | ;; Fontify ellipses within strings as buttons. | 149 | ;; Fontify ellipses within strings as buttons. |
| 150 | ;; This is necessary because ellipses are text property buttons | ||
| 151 | ;; instead of overlay buttons, which is done because there could | ||
| 152 | ;; be a large number of them. | ||
| 149 | (when (re-search-forward "\\(\\.\\.\\.\\)\"" bound t) | 153 | (when (re-search-forward "\\(\\.\\.\\.\\)\"" bound t) |
| 150 | (and (get-text-property (- (point) 2) 'cl-print-ellipsis) | 154 | (and (get-text-property (- (point) 2) 'cl-print-ellipsis) |
| 151 | (get-text-property (- (point) 3) 'cl-print-ellipsis) | 155 | (get-text-property (- (point) 3) 'cl-print-ellipsis) |
| @@ -187,6 +191,7 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 187 | (define-key map "\C-m" 'backtrace-help-follow-symbol) | 191 | (define-key map "\C-m" 'backtrace-help-follow-symbol) |
| 188 | (define-key map "+" 'backtrace-pretty-print) | 192 | (define-key map "+" 'backtrace-pretty-print) |
| 189 | (define-key map "-" 'backtrace-collapse) | 193 | (define-key map "-" 'backtrace-collapse) |
| 194 | (define-key map "." 'backtrace-expand-ellipses) | ||
| 190 | (define-key map [follow-link] 'mouse-face) | 195 | (define-key map [follow-link] 'mouse-face) |
| 191 | (define-key map [mouse-2] 'mouse-select-window) | 196 | (define-key map [mouse-2] 'mouse-select-window) |
| 192 | map) | 197 | map) |
| @@ -207,9 +212,7 @@ This is commonly used to recompute `backtrace-frames'.") | |||
| 207 | ;; backtrace-form: A value applied to each printed representation of a | 212 | ;; backtrace-form: A value applied to each printed representation of a |
| 208 | ;; top-level s-expression, which needs to be different for sexps | 213 | ;; top-level s-expression, which needs to be different for sexps |
| 209 | ;; printed adjacent to each other, so the limits can be quickly | 214 | ;; printed adjacent to each other, so the limits can be quickly |
| 210 | ;; found for pretty-printing. The value chosen is a list contining | 215 | ;; found for pretty-printing. |
| 211 | ;; the values of print-level and print-length used to print the | ||
| 212 | ;; sexp, and those values are used when expanding ellipses. | ||
| 213 | 216 | ||
| 214 | (defsubst backtrace-get-index (&optional pos) | 217 | (defsubst backtrace-get-index (&optional pos) |
| 215 | "Return the index of the backtrace frame at POS. | 218 | "Return the index of the backtrace frame at POS. |
| @@ -423,9 +426,6 @@ Reprint the frame with the new view plist." | |||
| 423 | 426 | ||
| 424 | (defun backtrace-expand-ellipsis (button) | 427 | (defun backtrace-expand-ellipsis (button) |
| 425 | "Expand display of the elided form at BUTTON." | 428 | "Expand display of the elided form at BUTTON." |
| 426 | ;; TODO a command to expand all ... in form at point | ||
| 427 | ;; with argument, don't bind print-level, length?? | ||
| 428 | ;; Enable undo so there's a way to go back? | ||
| 429 | (interactive) | 429 | (interactive) |
| 430 | (goto-char (button-start button)) | 430 | (goto-char (button-start button)) |
| 431 | (unless (get-text-property (point) 'cl-print-ellipsis) | 431 | (unless (get-text-property (point) 'cl-print-ellipsis) |
| @@ -437,25 +437,44 @@ Reprint the frame with the new view plist." | |||
| 437 | (begin (previous-single-property-change end 'cl-print-ellipsis)) | 437 | (begin (previous-single-property-change end 'cl-print-ellipsis)) |
| 438 | (value (get-text-property begin 'cl-print-ellipsis)) | 438 | (value (get-text-property begin 'cl-print-ellipsis)) |
| 439 | (props (backtrace-get-text-properties begin)) | 439 | (props (backtrace-get-text-properties begin)) |
| 440 | (tag (backtrace-get-form begin)) | ||
| 441 | (length (nth 0 tag)) ; TODO should this work with a target char count | ||
| 442 | (level (nth 1 tag)) ; like backtrace-print-to-string? | ||
| 443 | (inhibit-read-only t)) | 440 | (inhibit-read-only t)) |
| 444 | (backtrace--with-output-variables (backtrace-get-view) | 441 | (backtrace--with-output-variables (backtrace-get-view) |
| 445 | (let ((print-level level) | 442 | (delete-region begin end) |
| 446 | (print-length length)) | 443 | (insert (cl-print-to-string-with-limit #'cl-print-expand-ellipsis value |
| 447 | (delete-region begin end) | 444 | backtrace-line-length)) |
| 448 | (cl-print-expand-ellipsis value (current-buffer)) | 445 | (setq end (point)) |
| 449 | (setq end (point)) | 446 | (goto-char begin) |
| 450 | (goto-char begin) | 447 | (while (< (point) end) |
| 451 | (while (< (point) end) | 448 | (let ((next (next-single-property-change (point) 'cl-print-ellipsis |
| 452 | (let ((next (next-single-property-change (point) 'cl-print-ellipsis | 449 | nil end))) |
| 453 | nil end))) | 450 | (when (get-text-property (point) 'cl-print-ellipsis) |
| 454 | (when (get-text-property (point) 'cl-print-ellipsis) | 451 | (make-text-button (point) next :type 'backtrace-ellipsis)) |
| 455 | (make-text-button (point) next :type 'backtrace-ellipsis)) | 452 | (goto-char next))) |
| 456 | (goto-char next))) | 453 | (goto-char begin) |
| 457 | (goto-char begin) | 454 | (add-text-properties begin end props)))) |
| 458 | (add-text-properties begin end props))))) | 455 | |
| 456 | (defun backtrace-expand-ellipses (&optional no-limit) | ||
| 457 | "Expand display of all \"...\"s in the backtrace frame at point. | ||
| 458 | \\<backtrace-mode-map> | ||
| 459 | Each ellipsis will be limited to `backtrace-line-length' | ||
| 460 | characters in its expansion. With optional prefix argument | ||
| 461 | NO-LIMIT, do not limit the number of characters. Note that with | ||
| 462 | or without the argument, using this command can result in very | ||
| 463 | long lines and very poor display performance. If this happens | ||
| 464 | and is a problem, use `\\[revert-buffer]' to return to the | ||
| 465 | initial state of the Backtrace buffer." | ||
| 466 | (interactive "P") | ||
| 467 | (save-excursion | ||
| 468 | (let ((start (backtrace-get-frame-start)) | ||
| 469 | (end (backtrace-get-frame-end)) | ||
| 470 | (backtrace-line-length (unless no-limit backtrace-line-length))) | ||
| 471 | (goto-char end) | ||
| 472 | (while (> (point) start) | ||
| 473 | (let ((next (previous-single-property-change (point) 'cl-print-ellipsis | ||
| 474 | nil start))) | ||
| 475 | (when (get-text-property (point) 'cl-print-ellipsis) | ||
| 476 | (push-button (point))) | ||
| 477 | (goto-char next)))))) | ||
| 459 | 478 | ||
| 460 | (defun backtrace-pretty-print () | 479 | (defun backtrace-pretty-print () |
| 461 | "Pretty-print the top level s-expression at point." | 480 | "Pretty-print the top level s-expression at point." |
| @@ -605,8 +624,7 @@ line and recenter window line accordingly." | |||
| 605 | "Return a printed representation of OBJ formatted for backtraces. | 624 | "Return a printed representation of OBJ formatted for backtraces. |
| 606 | Attempt to get the length of the returned string under LIMIT | 625 | Attempt to get the length of the returned string under LIMIT |
| 607 | charcters with appropriate settings of `print-level' and | 626 | charcters with appropriate settings of `print-level' and |
| 608 | `print-length.' Attach the settings used with the text property | 627 | `print-length.' LIMIT defaults to `backtrace-line-length'." |
| 609 | `backtrace-form'. LIMIT defaults to `backtrace-line-length'." | ||
| 610 | (backtrace--with-output-variables backtrace-view | 628 | (backtrace--with-output-variables backtrace-view |
| 611 | (backtrace--print-to-string obj limit))) | 629 | (backtrace--print-to-string obj limit))) |
| 612 | 630 | ||
| @@ -614,36 +632,20 @@ charcters with appropriate settings of `print-level' and | |||
| 614 | ;; This is for use by callers who wrap the call with | 632 | ;; This is for use by callers who wrap the call with |
| 615 | ;; backtrace--with-output-variables. | 633 | ;; backtrace--with-output-variables. |
| 616 | (setq limit (or limit backtrace-line-length)) | 634 | (setq limit (or limit backtrace-line-length)) |
| 617 | (let* ((length 50) ; (/ backtrace-line-length 100) ?? | 635 | (with-temp-buffer |
| 618 | (level (truncate (log limit))) | 636 | (insert (cl-print-to-string-with-limit #'backtrace--print sexp limit)) |
| 619 | (delta (truncate (/ length level)))) | 637 | ;; Add a unique backtrace-form property. |
| 620 | (with-temp-buffer | 638 | (put-text-property (point-min) (point) 'backtrace-form (gensym)) |
| 621 | (catch 'done | 639 | ;; Make buttons from all the "..."s. Since there might be many of |
| 622 | (while t | 640 | ;; them, use text property buttons. |
| 623 | (erase-buffer) | 641 | (goto-char (point-min)) |
| 624 | (let ((standard-output (current-buffer)) | 642 | (while (< (point) (point-max)) |
| 625 | (print-length length) | 643 | (let ((end (next-single-property-change (point) 'cl-print-ellipsis |
| 626 | (print-level level)) | 644 | nil (point-max)))) |
| 627 | (backtrace--print sexp)) | 645 | (when (get-text-property (point) 'cl-print-ellipsis) |
| 628 | ;; Stop when either the level is too low or the sexp is | 646 | (make-text-button (point) end :type 'backtrace-ellipsis)) |
| 629 | ;; successfully printed in the space allowed. | 647 | (goto-char end))) |
| 630 | (when (or (< (- (point-max) (point-min)) limit) (= level 2)) | 648 | (buffer-string))) |
| 631 | (throw 'done nil)) | ||
| 632 | (cl-decf level) | ||
| 633 | (cl-decf length delta))) | ||
| 634 | (put-text-property (point-min) (point) | ||
| 635 | 'backtrace-form (list length level)) | ||
| 636 | ;; Make buttons from all the "..."s. | ||
| 637 | ;; TODO should this be under control of :do-ellipses in the view | ||
| 638 | ;; plist? | ||
| 639 | (goto-char (point-min)) | ||
| 640 | (while (< (point) (point-max)) | ||
| 641 | (let ((end (next-single-property-change (point) 'cl-print-ellipsis | ||
| 642 | nil (point-max)))) | ||
| 643 | (when (get-text-property (point) 'cl-print-ellipsis) | ||
| 644 | (make-text-button (point) end :type 'backtrace-ellipsis)) | ||
| 645 | (goto-char end))) | ||
| 646 | (buffer-string)))) | ||
| 647 | 649 | ||
| 648 | (defun backtrace-print-frame (frame view) | 650 | (defun backtrace-print-frame (frame view) |
| 649 | "Insert a backtrace FRAME at point formatted according to VIEW. | 651 | "Insert a backtrace FRAME at point formatted according to VIEW. |
| @@ -727,14 +729,14 @@ Print them only if :show-locals is non-nil in the VIEW plist." | |||
| 727 | (insert "\n"))) | 729 | (insert "\n"))) |
| 728 | (put-text-property beg (point) 'backtrace-section 'locals)))) | 730 | (put-text-property beg (point) 'backtrace-section 'locals)))) |
| 729 | 731 | ||
| 730 | (defun backtrace--print (obj) | 732 | (defun backtrace--print (obj &optional stream) |
| 731 | "Attempt to print OBJ using `backtrace-print-function'. | 733 | "Attempt to print OBJ to STREAM using `backtrace-print-function'. |
| 732 | Fall back to `prin1' if there is an error." | 734 | Fall back to `prin1' if there is an error." |
| 733 | (condition-case err | 735 | (condition-case err |
| 734 | (funcall backtrace-print-function obj) | 736 | (funcall backtrace-print-function obj stream) |
| 735 | (error | 737 | (error |
| 736 | (message "Error in backtrace printer: %S" err) | 738 | (message "Error in backtrace printer: %S" err) |
| 737 | (prin1 obj)))) | 739 | (prin1 obj stream)))) |
| 738 | 740 | ||
| 739 | (defun backtrace-update-flags () | 741 | (defun backtrace-update-flags () |
| 740 | "Update the display of the flags in the backtrace frame at point." | 742 | "Update the display of the flags in the backtrace frame at point." |
| @@ -805,8 +807,6 @@ followed by `backtrace-print-frame', once for each stack frame." | |||
| 805 | backtrace-font-lock-keywords-1 | 807 | backtrace-font-lock-keywords-1 |
| 806 | backtrace-font-lock-keywords-2) | 808 | backtrace-font-lock-keywords-2) |
| 807 | nil nil nil nil | 809 | nil nil nil nil |
| 808 | ;; TODO This one doesn't look necessary: | ||
| 809 | ;; (font-lock-mark-block-function . mark-defun) | ||
| 810 | (font-lock-syntactic-face-function | 810 | (font-lock-syntactic-face-function |
| 811 | . lisp-font-lock-syntactic-face-function)))) | 811 | . lisp-font-lock-syntactic-face-function)))) |
| 812 | (setq truncate-lines t) | 812 | (setq truncate-lines t) |
diff --git a/lisp/emacs-lisp/cl-print.el b/lisp/emacs-lisp/cl-print.el index 337efa465a0..c63f5ac005c 100644 --- a/lisp/emacs-lisp/cl-print.el +++ b/lisp/emacs-lisp/cl-print.el | |||
| @@ -524,5 +524,45 @@ node `(elisp)Output Variables'." | |||
| 524 | (cl-prin1 object (current-buffer)) | 524 | (cl-prin1 object (current-buffer)) |
| 525 | (buffer-string))) | 525 | (buffer-string))) |
| 526 | 526 | ||
| 527 | ;;;###autoload | ||
| 528 | (defun cl-print-to-string-with-limit (print-function value limit) | ||
| 529 | "Return a string containing a printed representation of VALUE. | ||
| 530 | Attempt to get the length of the returned string under LIMIT | ||
| 531 | characters with appropriate settings of `print-level' and | ||
| 532 | `print-length.' Use PRINT-FUNCTION to print, which should take | ||
| 533 | the arguments VALUE and STREAM and which should respect | ||
| 534 | `print-length' and `print-level'. LIMIT may be nil or zero in | ||
| 535 | which case PRINT-FUNCTION will be called with `print-level' and | ||
| 536 | `print-length' bound to nil. | ||
| 537 | |||
| 538 | Use this function with `cl-prin1' to print an object, | ||
| 539 | abbreviating it with ellipses to fit within a size limit. Use | ||
| 540 | this function with `cl-prin1-expand-ellipsis' to expand an | ||
| 541 | ellipsis, abbreviating the expansion to stay within a size | ||
| 542 | limit." | ||
| 543 | (setq limit (and (natnump limit) | ||
| 544 | (not (zerop limit)) | ||
| 545 | limit)) | ||
| 546 | ;; Since this is used by the debugger when stack space may be | ||
| 547 | ;; limited, if you increase print-level here, add more depth in | ||
| 548 | ;; call_debugger (bug#31919). | ||
| 549 | (let* ((print-length (when limit (min limit 50))) | ||
| 550 | (print-level (when limit (min 8 (truncate (log limit))))) | ||
| 551 | (delta (when limit | ||
| 552 | (max 1 (truncate (/ print-length print-level)))))) | ||
| 553 | (with-temp-buffer | ||
| 554 | (catch 'done | ||
| 555 | (while t | ||
| 556 | (erase-buffer) | ||
| 557 | (funcall print-function value (current-buffer)) | ||
| 558 | ;; Stop when either print-level is too low or the value is | ||
| 559 | ;; successfully printed in the space allowed. | ||
| 560 | (when (or (not limit) | ||
| 561 | (< (- (point-max) (point-min)) limit) | ||
| 562 | (= print-level 2)) | ||
| 563 | (throw 'done (buffer-string))) | ||
| 564 | (cl-decf print-level) | ||
| 565 | (cl-decf print-length delta)))))) | ||
| 566 | |||
| 527 | (provide 'cl-print) | 567 | (provide 'cl-print) |
| 528 | ;;; cl-print.el ends here | 568 | ;;; cl-print.el ends here |
diff --git a/test/lisp/emacs-lisp/backtrace-tests.el b/test/lisp/emacs-lisp/backtrace-tests.el index ba2d33a9d5c..ff26112ab9a 100644 --- a/test/lisp/emacs-lisp/backtrace-tests.el +++ b/test/lisp/emacs-lisp/backtrace-tests.el | |||
| @@ -349,32 +349,74 @@ digit and replace with #[0-9]." | |||
| 349 | (buffer-string))) | 349 | (buffer-string))) |
| 350 | 350 | ||
| 351 | (ert-deftest backtrace-tests--expand-ellipsis () | 351 | (ert-deftest backtrace-tests--expand-ellipsis () |
| 352 | "Backtrace buffers ellipsify large forms and can expand the ellipses." | 352 | "Backtrace buffers ellipsify large forms as buttons which expand the ellipses." |
| 353 | ;; make a backtrace with an ellipsis | 353 | ;; make a backtrace with an ellipsis |
| 354 | ;; expand the ellipsis | 354 | ;; expand the ellipsis |
| 355 | (ert-with-test-buffer (:name "variables") | 355 | (ert-with-test-buffer (:name "variables") |
| 356 | (let* ((print-level nil) | 356 | (let* ((print-level nil) |
| 357 | (print-length nil) | 357 | (print-length nil) |
| 358 | (arg (let ((long (make-list 100 'a)) | 358 | (backtrace-line-length 300) |
| 359 | (deep '(0 (1 (2 (3 (4 (5 (6 (7 (8 (9)))))))))))) | 359 | (arg (make-list 40 (make-string 10 ?a))) |
| 360 | (setf (nth 1 long) deep) | ||
| 361 | long)) | ||
| 362 | (results (backtrace-tests--result arg))) | 360 | (results (backtrace-tests--result arg))) |
| 363 | (backtrace-tests--make-backtrace arg) | 361 | (backtrace-tests--make-backtrace arg) |
| 364 | (backtrace-print) | 362 | (backtrace-print) |
| 365 | 363 | ||
| 366 | ;; There should be two ellipses. Find and expand them. | 364 | ;; There should be an ellipsis. Find and expand it. |
| 367 | (goto-char (point-min)) | 365 | (goto-char (point-min)) |
| 368 | (search-forward "...") | 366 | (search-forward "...") |
| 369 | (backward-char) | 367 | (backward-char) |
| 370 | (push-button) | 368 | (push-button) |
| 371 | (search-forward "...") | ||
| 372 | (backward-char) | ||
| 373 | (push-button) | ||
| 374 | 369 | ||
| 375 | (should (string= (backtrace-tests--get-substring (point-min) (point-max)) | 370 | (should (string= (backtrace-tests--get-substring (point-min) (point-max)) |
| 376 | results))))) | 371 | results))))) |
| 377 | 372 | ||
| 373 | (ert-deftest backtrace-tests--expand-ellipses () | ||
| 374 | "Backtrace buffers ellipsify large forms and can expand the ellipses." | ||
| 375 | (ert-with-test-buffer (:name "variables") | ||
| 376 | (let* ((print-level nil) | ||
| 377 | (print-length nil) | ||
| 378 | (backtrace-line-length 300) | ||
| 379 | (arg (let ((outer (make-list 40 (make-string 10 ?a))) | ||
| 380 | (nested (make-list 40 (make-string 10 ?b)))) | ||
| 381 | (setf (nth 39 nested) (make-list 40 (make-string 10 ?c))) | ||
| 382 | (setf (nth 39 outer) nested) | ||
| 383 | outer)) | ||
| 384 | (results (backtrace-tests--result-with-locals arg))) | ||
| 385 | |||
| 386 | ;; Make a backtrace with local variables visible. | ||
| 387 | (backtrace-tests--make-backtrace arg) | ||
| 388 | (backtrace-print) | ||
| 389 | (backtrace-toggle-locals '(4)) | ||
| 390 | |||
| 391 | ;; There should be two ellipses. | ||
| 392 | (goto-char (point-min)) | ||
| 393 | (should (search-forward "...")) | ||
| 394 | (should (search-forward "...")) | ||
| 395 | (should-error (search-forward "...")) | ||
| 396 | |||
| 397 | ;; Expanding the last frame without argument should expand both | ||
| 398 | ;; ellipses, but the expansions will contain one ellipsis each. | ||
| 399 | (let ((buffer-len (- (point-max) (point-min)))) | ||
| 400 | (goto-char (point-max)) | ||
| 401 | (backtrace-backward-frame) | ||
| 402 | (backtrace-expand-ellipses) | ||
| 403 | (should (> (- (point-max) (point-min)) buffer-len)) | ||
| 404 | (goto-char (point-min)) | ||
| 405 | (should (search-forward "...")) | ||
| 406 | (should (search-forward "...")) | ||
| 407 | (should-error (search-forward "..."))) | ||
| 408 | |||
| 409 | ;; Expanding with argument should remove all ellipses. | ||
| 410 | (goto-char (point-max)) | ||
| 411 | (backtrace-backward-frame) | ||
| 412 | (backtrace-expand-ellipses '(4)) | ||
| 413 | (goto-char (point-min)) | ||
| 414 | |||
| 415 | (should-error (search-forward "...")) | ||
| 416 | (should (string= (backtrace-tests--get-substring (point-min) (point-max)) | ||
| 417 | results))))) | ||
| 418 | |||
| 419 | |||
| 378 | (ert-deftest backtrace-tests--to-string () | 420 | (ert-deftest backtrace-tests--to-string () |
| 379 | "Backtraces can be produced as strings." | 421 | "Backtraces can be produced as strings." |
| 380 | (let ((frames (ert-with-test-buffer (:name nil) | 422 | (let ((frames (ert-with-test-buffer (:name nil) |
diff --git a/test/lisp/emacs-lisp/cl-print-tests.el b/test/lisp/emacs-lisp/cl-print-tests.el index 7594d2466b5..a469b5526c0 100644 --- a/test/lisp/emacs-lisp/cl-print-tests.el +++ b/test/lisp/emacs-lisp/cl-print-tests.el | |||
| @@ -233,5 +233,41 @@ | |||
| 233 | (let ((print-circle t)) | 233 | (let ((print-circle t)) |
| 234 | (should (equal "(0 . #1=(0 . #1#))" (cl-prin1-to-string x)))))) | 234 | (should (equal "(0 . #1=(0 . #1#))" (cl-prin1-to-string x)))))) |
| 235 | 235 | ||
| 236 | (ert-deftest cl-print-tests-print-to-string-with-limit () | ||
| 237 | (let* ((thing10 (make-list 10 'a)) | ||
| 238 | (thing100 (make-list 100 'a)) | ||
| 239 | (thing10x10 (make-list 10 thing10)) | ||
| 240 | (nested-thing (let ((val 'a)) | ||
| 241 | (dotimes (_i 20) | ||
| 242 | (setq val (list val))) | ||
| 243 | val)) | ||
| 244 | ;; Make a consistent environment for this test. | ||
| 245 | (print-circle nil) | ||
| 246 | (print-level nil) | ||
| 247 | (print-length nil)) | ||
| 248 | |||
| 249 | ;; Print something that fits in the space given. | ||
| 250 | (should (string= (cl-prin1-to-string thing10) | ||
| 251 | (cl-print-to-string-with-limit #'cl-prin1 thing10 100))) | ||
| 252 | |||
| 253 | ;; Print something which needs to be abbreviated and which can be. | ||
| 254 | (should (< (length (cl-print-to-string-with-limit #'cl-prin1 thing100 100)) | ||
| 255 | 100 | ||
| 256 | (length (cl-prin1-to-string thing100)))) | ||
| 257 | |||
| 258 | ;; Print something resistant to easy abbreviation. | ||
| 259 | (should (string= (cl-prin1-to-string thing10x10) | ||
| 260 | (cl-print-to-string-with-limit #'cl-prin1 thing10x10 100))) | ||
| 261 | |||
| 262 | ;; Print something which should be abbreviated even if the limit is large. | ||
| 263 | (should (< (length (cl-print-to-string-with-limit #'cl-prin1 nested-thing 1000)) | ||
| 264 | (length (cl-prin1-to-string nested-thing)))) | ||
| 265 | |||
| 266 | ;; Print with no limits. | ||
| 267 | (dolist (thing (list thing10 thing100 thing10x10 nested-thing)) | ||
| 268 | (let ((rep (cl-prin1-to-string thing))) | ||
| 269 | (should (string= rep (cl-print-to-string-with-limit #'cl-prin1 thing 0))) | ||
| 270 | (should (string= rep (cl-print-to-string-with-limit #'cl-prin1 thing nil))))))) | ||
| 271 | |||
| 236 | 272 | ||
| 237 | ;;; cl-print-tests.el ends here. | 273 | ;;; cl-print-tests.el ends here. |