diff options
| author | Noam Postavsky | 2017-04-23 22:21:42 -0400 |
|---|---|---|
| committer | Noam Postavsky | 2017-05-19 18:16:15 -0400 |
| commit | 267be4bdc28564a99f45da29e84eb98838117b50 (patch) | |
| tree | 3816b74e945cb1a17a1f4c8ad5e25e4abb0e8206 | |
| parent | c1c8b67246c4314b302cca2ac43f13a0baba4c16 (diff) | |
| download | emacs-267be4bdc28564a99f45da29e84eb98838117b50.tar.gz emacs-267be4bdc28564a99f45da29e84eb98838117b50.zip | |
Refactor lisp eval result printing
* lisp/simple.el (eval-expression-print-format): Don't check
`standard-output' or `current-prefix-arg'.
(eval-expression-get-print-arguments): New function, centralizes
decision about how to print results of `eval-expression' and
`eval-last-sexp'.
(eval-expression):
* lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp-print-value):
Use it.
| -rw-r--r-- | lisp/progmodes/elisp-mode.el | 35 | ||||
| -rw-r--r-- | lisp/simple.el | 58 | ||||
| -rw-r--r-- | test/lisp/progmodes/elisp-mode-tests.el | 18 | ||||
| -rw-r--r-- | test/lisp/simple-tests.el | 42 |
4 files changed, 97 insertions, 56 deletions
diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 53a0f66439b..c2fdba47a09 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el | |||
| @@ -1119,29 +1119,28 @@ current buffer. If EVAL-LAST-SEXP-ARG-INTERNAL is `0', print | |||
| 1119 | output with no limit on the length and level of lists, and | 1119 | output with no limit on the length and level of lists, and |
| 1120 | include additional formats for integers \(octal, hexadecimal, and | 1120 | include additional formats for integers \(octal, hexadecimal, and |
| 1121 | character)." | 1121 | character)." |
| 1122 | (let ((standard-output (if eval-last-sexp-arg-internal (current-buffer) t))) | 1122 | (pcase-let* |
| 1123 | ((`(,insert-value ,no-truncate ,char-print) | ||
| 1124 | (eval-expression-get-print-arguments eval-last-sexp-arg-internal))) | ||
| 1123 | ;; Setup the lexical environment if lexical-binding is enabled. | 1125 | ;; Setup the lexical environment if lexical-binding is enabled. |
| 1124 | (elisp--eval-last-sexp-print-value | 1126 | (elisp--eval-last-sexp-print-value |
| 1125 | (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding) | 1127 | (eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding) |
| 1126 | eval-last-sexp-arg-internal))) | 1128 | (if insert-value (current-buffer) t) no-truncate char-print))) |
| 1127 | 1129 | ||
| 1128 | (defun elisp--eval-last-sexp-print-value (value &optional eval-last-sexp-arg-internal) | 1130 | (defun elisp--eval-last-sexp-print-value |
| 1129 | (let ((unabbreviated (let ((print-length nil) (print-level nil)) | 1131 | (value output &optional no-truncate char-print) |
| 1130 | (prin1-to-string value))) | 1132 | (let* ((unabbreviated (let ((print-length nil) (print-level nil)) |
| 1131 | (print-length (and (not (zerop (prefix-numeric-value | 1133 | (prin1-to-string value))) |
| 1132 | eval-last-sexp-arg-internal))) | 1134 | (print-length (unless no-truncate eval-expression-print-length)) |
| 1133 | eval-expression-print-length)) | 1135 | (print-level (unless no-truncate eval-expression-print-level)) |
| 1134 | (print-level (and (not (zerop (prefix-numeric-value | 1136 | (beg (point)) |
| 1135 | eval-last-sexp-arg-internal))) | 1137 | end) |
| 1136 | eval-expression-print-level)) | ||
| 1137 | (beg (point)) | ||
| 1138 | end) | ||
| 1139 | (prog1 | 1138 | (prog1 |
| 1140 | (prin1 value) | 1139 | (prin1 value output) |
| 1141 | (let ((str (eval-expression-print-format value))) | 1140 | (let ((str (and char-print (eval-expression-print-format value)))) |
| 1142 | (if str (princ str))) | 1141 | (if str (princ str output))) |
| 1143 | (setq end (point)) | 1142 | (setq end (point)) |
| 1144 | (when (and (bufferp standard-output) | 1143 | (when (and (bufferp output) |
| 1145 | (or (not (null print-length)) | 1144 | (or (not (null print-length)) |
| 1146 | (not (null print-level))) | 1145 | (not (null print-level))) |
| 1147 | (not (string= unabbreviated | 1146 | (not (string= unabbreviated |
diff --git a/lisp/simple.el b/lisp/simple.el index 7f13df5006d..3af62657dbf 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -1456,16 +1456,14 @@ This string will typically look like \" (#o1, #x1, ?\\C-a)\". | |||
| 1456 | If VALUE is not an integer, nil is returned. | 1456 | If VALUE is not an integer, nil is returned. |
| 1457 | This function is used by functions like `prin1' that display the | 1457 | This function is used by functions like `prin1' that display the |
| 1458 | result of expression evaluation." | 1458 | result of expression evaluation." |
| 1459 | (if (and (integerp value) | 1459 | (when (integerp value) |
| 1460 | (or (eq standard-output t) | 1460 | (let ((char-string |
| 1461 | (zerop (prefix-numeric-value current-prefix-arg)))) | 1461 | (and (characterp value) |
| 1462 | (let ((char-string | 1462 | (char-displayable-p value) |
| 1463 | (if (and (characterp value) | 1463 | (prin1-char value)))) |
| 1464 | (char-displayable-p value)) | 1464 | (if char-string |
| 1465 | (prin1-char value)))) | 1465 | (format " (#o%o, #x%x, %s)" value value char-string) |
| 1466 | (if char-string | 1466 | (format " (#o%o, #x%x)" value value))))) |
| 1467 | (format " (#o%o, #x%x, %s)" value value char-string) | ||
| 1468 | (format " (#o%o, #x%x)" value value))))) | ||
| 1469 | 1467 | ||
| 1470 | (defvar eval-expression-minibuffer-setup-hook nil | 1468 | (defvar eval-expression-minibuffer-setup-hook nil |
| 1471 | "Hook run by `eval-expression' when entering the minibuffer.") | 1469 | "Hook run by `eval-expression' when entering the minibuffer.") |
| @@ -1484,9 +1482,21 @@ result of expression evaluation." | |||
| 1484 | read-expression-map t | 1482 | read-expression-map t |
| 1485 | 'read-expression-history)))) | 1483 | 'read-expression-history)))) |
| 1486 | 1484 | ||
| 1485 | (defun eval-expression-get-print-arguments (prefix-argument) | ||
| 1486 | "Get arguments for commands that print an expression result. | ||
| 1487 | Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT) | ||
| 1488 | based on PREFIX-ARG. This function determines the interpretation | ||
| 1489 | of the prefix argument for `eval-expression' and | ||
| 1490 | `eval-last-sexp'." | ||
| 1491 | (let ((num (prefix-numeric-value prefix-argument))) | ||
| 1492 | (list (not (memq prefix-argument '(nil))) | ||
| 1493 | (= num 0) | ||
| 1494 | (cond ((not (memq prefix-argument '(0 nil))) nil) | ||
| 1495 | (t t))))) | ||
| 1496 | |||
| 1487 | ;; We define this, rather than making `eval' interactive, | 1497 | ;; We define this, rather than making `eval' interactive, |
| 1488 | ;; for the sake of completion of names like eval-region, eval-buffer. | 1498 | ;; for the sake of completion of names like eval-region, eval-buffer. |
| 1489 | (defun eval-expression (exp &optional insert-value) | 1499 | (defun eval-expression (exp &optional insert-value no-truncate char-print) |
| 1490 | "Evaluate EXP and print value in the echo area. | 1500 | "Evaluate EXP and print value in the echo area. |
| 1491 | When called interactively, read an Emacs Lisp expression and evaluate it. | 1501 | When called interactively, read an Emacs Lisp expression and evaluate it. |
| 1492 | Value is also consed on to front of the variable `values'. | 1502 | Value is also consed on to front of the variable `values'. |
| @@ -1507,8 +1517,8 @@ minibuffer. | |||
| 1507 | If `eval-expression-debug-on-error' is non-nil, which is the default, | 1517 | If `eval-expression-debug-on-error' is non-nil, which is the default, |
| 1508 | this command arranges for all errors to enter the debugger." | 1518 | this command arranges for all errors to enter the debugger." |
| 1509 | (interactive | 1519 | (interactive |
| 1510 | (list (read--expression "Eval: ") | 1520 | (cons (read--expression "Eval: ") |
| 1511 | current-prefix-arg)) | 1521 | (eval-expression-get-print-arguments current-prefix-arg))) |
| 1512 | 1522 | ||
| 1513 | (if (null eval-expression-debug-on-error) | 1523 | (if (null eval-expression-debug-on-error) |
| 1514 | (push (eval exp lexical-binding) values) | 1524 | (push (eval exp lexical-binding) values) |
| @@ -1523,23 +1533,15 @@ this command arranges for all errors to enter the debugger." | |||
| 1523 | (unless (eq old-value new-value) | 1533 | (unless (eq old-value new-value) |
| 1524 | (setq debug-on-error new-value)))) | 1534 | (setq debug-on-error new-value)))) |
| 1525 | 1535 | ||
| 1526 | (let ((print-length (and (not (zerop (prefix-numeric-value insert-value))) | 1536 | (let ((print-length (unless no-truncate eval-expression-print-length)) |
| 1527 | eval-expression-print-length)) | 1537 | (print-level (unless no-truncate eval-expression-print-level)) |
| 1528 | (print-level (and (not (zerop (prefix-numeric-value insert-value))) | ||
| 1529 | eval-expression-print-level)) | ||
| 1530 | (deactivate-mark)) | 1538 | (deactivate-mark)) |
| 1531 | (if insert-value | 1539 | (let ((out (if insert-value (current-buffer) t))) |
| 1532 | (with-no-warnings | ||
| 1533 | (let ((standard-output (current-buffer))) | ||
| 1534 | (prog1 | ||
| 1535 | (prin1 (car values)) | ||
| 1536 | (when (zerop (prefix-numeric-value insert-value)) | ||
| 1537 | (let ((str (eval-expression-print-format (car values)))) | ||
| 1538 | (if str (princ str))))))) | ||
| 1539 | (prog1 | 1540 | (prog1 |
| 1540 | (prin1 (car values) t) | 1541 | (prin1 (car values) out) |
| 1541 | (let ((str (eval-expression-print-format (car values)))) | 1542 | (let ((str (and char-print |
| 1542 | (if str (princ str t))))))) | 1543 | (eval-expression-print-format (car values))))) |
| 1544 | (when str (princ str out))))))) | ||
| 1543 | 1545 | ||
| 1544 | (defun edit-and-eval-command (prompt command) | 1546 | (defun edit-and-eval-command (prompt command) |
| 1545 | "Prompting with PROMPT, let user edit COMMAND and eval result. | 1547 | "Prompting with PROMPT, let user edit COMMAND and eval result. |
diff --git a/test/lisp/progmodes/elisp-mode-tests.el b/test/lisp/progmodes/elisp-mode-tests.el index 93c428b2d2b..5edb590b1e5 100644 --- a/test/lisp/progmodes/elisp-mode-tests.el +++ b/test/lisp/progmodes/elisp-mode-tests.el | |||
| @@ -114,6 +114,24 @@ | |||
| 114 | (should (member "backup-buffer" comps)) | 114 | (should (member "backup-buffer" comps)) |
| 115 | (should-not (member "backup-inhibited" comps))))) | 115 | (should-not (member "backup-inhibited" comps))))) |
| 116 | 116 | ||
| 117 | ;;; eval-last-sexp | ||
| 118 | |||
| 119 | (ert-deftest eval-last-sexp-print-format-sym () | ||
| 120 | (with-temp-buffer | ||
| 121 | (let ((current-prefix-arg '(4))) | ||
| 122 | (erase-buffer) (insert "t") | ||
| 123 | (call-interactively #'eval-last-sexp) | ||
| 124 | (should (equal (buffer-string) "tt"))))) | ||
| 125 | |||
| 126 | (ert-deftest eval-last-sexp-print-format-sym-echo () | ||
| 127 | ;; We can only check the echo area when running interactive. | ||
| 128 | (skip-unless (not noninteractive)) | ||
| 129 | (with-temp-buffer | ||
| 130 | (let ((current-prefix-arg nil)) | ||
| 131 | (erase-buffer) (insert "t") (message nil) | ||
| 132 | (call-interactively #'eval-last-sexp) | ||
| 133 | (should (equal (current-message) "t"))))) | ||
| 134 | |||
| 117 | ;;; xref | 135 | ;;; xref |
| 118 | 136 | ||
| 119 | (defun xref-elisp-test-descr-to-target (xref) | 137 | (defun xref-elisp-test-descr-to-target (xref) |
diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index f4849c4b21d..b74e28ccaf1 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | ;;; Code: | 20 | ;;; Code: |
| 21 | 21 | ||
| 22 | (require 'ert) | 22 | (require 'ert) |
| 23 | (eval-when-compile (require 'cl-lib)) | ||
| 23 | 24 | ||
| 24 | (defmacro simple-test--dummy-buffer (&rest body) | 25 | (defmacro simple-test--dummy-buffer (&rest body) |
| 25 | (declare (indent 0) | 26 | (declare (indent 0) |
| @@ -35,6 +36,8 @@ | |||
| 35 | (buffer-substring (point) (point-max)))))) | 36 | (buffer-substring (point) (point-max)))))) |
| 36 | 37 | ||
| 37 | 38 | ||
| 39 | |||
| 40 | ;;; `transpose-sexps' | ||
| 38 | (defmacro simple-test--transpositions (&rest body) | 41 | (defmacro simple-test--transpositions (&rest body) |
| 39 | (declare (indent 0) | 42 | (declare (indent 0) |
| 40 | (debug t)) | 43 | (debug t)) |
| @@ -46,6 +49,13 @@ | |||
| 46 | (cons (buffer-substring (point-min) (point)) | 49 | (cons (buffer-substring (point-min) (point)) |
| 47 | (buffer-substring (point) (point-max))))) | 50 | (buffer-substring (point) (point-max))))) |
| 48 | 51 | ||
| 52 | ;;; Transposition with negative args (bug#20698, bug#21885) | ||
| 53 | (ert-deftest simple-transpose-subr () | ||
| 54 | (should (equal (simple-test--transpositions (transpose-sexps -1)) | ||
| 55 | '("(s1) (s2) (s4)" . " (s3) (s5)"))) | ||
| 56 | (should (equal (simple-test--transpositions (transpose-sexps -2)) | ||
| 57 | '("(s1) (s4)" . " (s2) (s3) (s5)")))) | ||
| 58 | |||
| 49 | 59 | ||
| 50 | ;;; `newline' | 60 | ;;; `newline' |
| 51 | (ert-deftest newline () | 61 | (ert-deftest newline () |
| @@ -239,8 +249,8 @@ | |||
| 239 | (should (equal ?\s (char-syntax ?\f))) | 249 | (should (equal ?\s (char-syntax ?\f))) |
| 240 | (should (equal ?\s (char-syntax ?\n)))))) | 250 | (should (equal ?\s (char-syntax ?\n)))))) |
| 241 | 251 | ||
| 242 | 252 | ||
| 243 | ;;; auto-boundary tests | 253 | ;;; undo auto-boundary tests |
| 244 | (ert-deftest undo-auto-boundary-timer () | 254 | (ert-deftest undo-auto-boundary-timer () |
| 245 | (should | 255 | (should |
| 246 | undo-auto-current-boundary-timer)) | 256 | undo-auto-current-boundary-timer)) |
| @@ -269,14 +279,6 @@ | |||
| 269 | (insert "hello") | 279 | (insert "hello") |
| 270 | (undo-auto--boundaries 'test)))) | 280 | (undo-auto--boundaries 'test)))) |
| 271 | 281 | ||
| 272 | ;;; Transposition with negative args (bug#20698, bug#21885) | ||
| 273 | (ert-deftest simple-transpose-subr () | ||
| 274 | (should (equal (simple-test--transpositions (transpose-sexps -1)) | ||
| 275 | '("(s1) (s2) (s4)" . " (s3) (s5)"))) | ||
| 276 | (should (equal (simple-test--transpositions (transpose-sexps -2)) | ||
| 277 | '("(s1) (s4)" . " (s2) (s3) (s5)")))) | ||
| 278 | |||
| 279 | |||
| 280 | ;; Test for a regression introduced by undo-auto--boundaries changes. | 282 | ;; Test for a regression introduced by undo-auto--boundaries changes. |
| 281 | ;; https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg01652.html | 283 | ;; https://lists.gnu.org/archive/html/emacs-devel/2015-11/msg01652.html |
| 282 | (defun undo-test-kill-c-a-then-undo () | 284 | (defun undo-test-kill-c-a-then-undo () |
| @@ -374,5 +376,25 @@ See Bug#21722." | |||
| 374 | (undo) | 376 | (undo) |
| 375 | (point))))) | 377 | (point))))) |
| 376 | 378 | ||
| 379 | |||
| 380 | ;;; `eval-expression' | ||
| 381 | |||
| 382 | (ert-deftest eval-expression-print-format-sym () | ||
| 383 | (with-temp-buffer | ||
| 384 | (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) t))) | ||
| 385 | (let ((current-prefix-arg '(4))) | ||
| 386 | (call-interactively #'eval-expression) | ||
| 387 | (should (equal (buffer-string) "t")))))) | ||
| 388 | |||
| 389 | (ert-deftest eval-expression-print-format-sym-echo () | ||
| 390 | ;; We can only check the echo area when running interactive. | ||
| 391 | (skip-unless (not noninteractive)) | ||
| 392 | (with-temp-buffer | ||
| 393 | (cl-letf (((symbol-function 'read--expression) (lambda (&rest _) t))) | ||
| 394 | (let ((current-prefix-arg nil)) | ||
| 395 | (message nil) | ||
| 396 | (call-interactively #'eval-expression) | ||
| 397 | (should (equal (current-message) "t")))))) | ||
| 398 | |||
| 377 | (provide 'simple-test) | 399 | (provide 'simple-test) |
| 378 | ;;; simple-test.el ends here | 400 | ;;; simple-test.el ends here |