Limit integers printed as characters (Bug#16828)
* lisp/simple.el (eval-expression-print-maximum-character): New variable. (eval-expression-print-format): Only display value as character if it's less than or equal to `eval-expression-print-maximum-character'. (eval-expression-get-print-arguments): Check eval-expression-print-maximum-character, allow negative arg to override it. (eval-expression): * lisp/progmodes/elisp-mode.el (elisp--eval-last-sexp): (elisp--eval-last-sexp-print-value): Handle new variable. * doc/emacs/building.texi (Lisp Eval): Document new variable and behavior. * etc/NEWS: Announce it. * test/lisp/progmodes/elisp-mode-tests.el (eval-last-sexp-print-format-small-int) (eval-last-sexp-print-format-small-int-echo) (eval-last-sexp-print-format-large-int) (eval-last-sexp-print-format-large-int-echo): * test/lisp/simple-tests.el (eval-expression-print-format-small-int) (eval-expression-print-format-small-int-echo) (eval-expression-print-format-large-int) (eval-expression-print-format-large-int-echo): New tests.
This commit is contained in:
parent
267be4bdc2
commit
acd58c9198
6 changed files with 163 additions and 30 deletions
|
@ -1485,7 +1485,9 @@ expression.)
|
|||
Emacs Lisp expression preceding point in the buffer, and displays the
|
||||
value in the echo area. When the result of an evaluation is an
|
||||
integer, it is displayed together with the value in other formats
|
||||
(octal, hexadecimal, and character).
|
||||
(octal, hexadecimal, and character if
|
||||
@code{eval-expression-print-maximum-character}, described below,
|
||||
allows it).
|
||||
|
||||
If @kbd{M-:} or @kbd{C-x C-e} is given a prefix argument, it inserts
|
||||
the value into the current buffer at point, rather than displaying it
|
||||
|
@ -1493,8 +1495,10 @@ in the echo area. If the prefix argument is zero, any integer output
|
|||
is inserted together with its value in other formats (octal,
|
||||
hexadecimal, and character). Such a prefix argument also prevents
|
||||
abbreviation of the output according to the variables
|
||||
@code{eval-expression-print-level} and @code{eval-expression-print-length}
|
||||
(see below).
|
||||
@code{eval-expression-print-level} and
|
||||
@code{eval-expression-print-length} (see below). Similarly, a prefix
|
||||
argument of @code{-1} overrides the effect of
|
||||
@code{eval-expression-print-length}.
|
||||
|
||||
@kindex C-M-x @r{(Emacs Lisp mode)}
|
||||
@findex eval-defun
|
||||
|
@ -1524,6 +1528,7 @@ eval-buffer} is similar but evaluates the entire buffer.
|
|||
|
||||
@vindex eval-expression-print-level
|
||||
@vindex eval-expression-print-length
|
||||
@vindex eval-expression-print-maximum-character
|
||||
@vindex eval-expression-debug-on-error
|
||||
The options @code{eval-expression-print-level} and
|
||||
@code{eval-expression-print-length} control the maximum depth and
|
||||
|
@ -1533,6 +1538,8 @@ before abbreviating them. Supplying a zero prefix argument to
|
|||
printed in full. @code{eval-expression-debug-on-error} controls
|
||||
whether evaluation errors invoke the debugger when these commands are
|
||||
used; its default is @code{t}.
|
||||
@code{eval-expression-print-maximum-character} prevents integers which
|
||||
are larger than it from being displayed as characters.
|
||||
|
||||
@node Lisp Interaction
|
||||
@section Lisp Interaction Buffers
|
||||
|
|
4
etc/NEWS
4
etc/NEWS
|
@ -352,6 +352,10 @@ environment variable on a remote machine to emacsclient, and
|
|||
use the local Emacs to edit remote files via Tramp. See the node
|
||||
"emacsclient Options" in the user manual for the details.
|
||||
|
||||
+++
|
||||
** The new variable 'eval-expression-print-maximum-character' prevents
|
||||
large integers from being displayed as characters.
|
||||
|
||||
|
||||
* Editing Changes in Emacs 26.1
|
||||
|
||||
|
|
|
@ -1120,24 +1120,25 @@ output with no limit on the length and level of lists, and
|
|||
include additional formats for integers \(octal, hexadecimal, and
|
||||
character)."
|
||||
(pcase-let*
|
||||
((`(,insert-value ,no-truncate ,char-print)
|
||||
((`(,insert-value ,no-truncate ,char-print-limit)
|
||||
(eval-expression-get-print-arguments eval-last-sexp-arg-internal)))
|
||||
;; Setup the lexical environment if lexical-binding is enabled.
|
||||
(elisp--eval-last-sexp-print-value
|
||||
(eval (eval-sexp-add-defvars (elisp--preceding-sexp)) lexical-binding)
|
||||
(if insert-value (current-buffer) t) no-truncate char-print)))
|
||||
(if insert-value (current-buffer) t) no-truncate char-print-limit)))
|
||||
|
||||
(defun elisp--eval-last-sexp-print-value
|
||||
(value output &optional no-truncate char-print)
|
||||
(value output &optional no-truncate char-print-limit)
|
||||
(let* ((unabbreviated (let ((print-length nil) (print-level nil))
|
||||
(prin1-to-string value)))
|
||||
(eval-expression-print-maximum-character char-print-limit)
|
||||
(print-length (unless no-truncate eval-expression-print-length))
|
||||
(print-level (unless no-truncate eval-expression-print-level))
|
||||
(beg (point))
|
||||
end)
|
||||
(prog1
|
||||
(prin1 value output)
|
||||
(let ((str (and char-print (eval-expression-print-format value))))
|
||||
(let ((str (and char-print-limit (eval-expression-print-format value))))
|
||||
(if str (princ str output)))
|
||||
(setq end (point))
|
||||
(when (and (bufferp output)
|
||||
|
@ -1175,14 +1176,17 @@ POS specifies the starting position where EXP was found and defaults to point."
|
|||
|
||||
(defun eval-last-sexp (eval-last-sexp-arg-internal)
|
||||
"Evaluate sexp before point; print value in the echo area.
|
||||
Interactively, with prefix argument, print output into current buffer.
|
||||
Interactively, with a non `-' prefix argument, print output into
|
||||
current buffer.
|
||||
|
||||
Normally, this function truncates long output according to the value
|
||||
of the variables `eval-expression-print-length' and
|
||||
Normally, this function truncates long output according to the
|
||||
value of the variables `eval-expression-print-length' and
|
||||
`eval-expression-print-level'. With a prefix argument of zero,
|
||||
however, there is no such truncation. Such a prefix argument
|
||||
also causes integers to be printed in several additional formats
|
||||
\(octal, hexadecimal, and character).
|
||||
\(octal, hexadecimal, and character when the prefix argument is
|
||||
-1 or the integer is `eval-expression-print-maximum-character' or
|
||||
less).
|
||||
|
||||
If `eval-expression-debug-on-error' is non-nil, which is the default,
|
||||
this command arranges for all errors to enter the debugger."
|
||||
|
|
|
@ -1450,15 +1450,24 @@ If nil, don't change the value of `debug-on-error'."
|
|||
:type 'boolean
|
||||
:version "21.1")
|
||||
|
||||
(defcustom eval-expression-print-maximum-character 127
|
||||
"The largest integer that will be displayed as a character.
|
||||
This affects printing by `eval-expression' (via
|
||||
`eval-expression-print-format')."
|
||||
:group 'lisp
|
||||
:type 'integer
|
||||
:version "26.1")
|
||||
|
||||
(defun eval-expression-print-format (value)
|
||||
"If VALUE in an integer, return a specially formatted string.
|
||||
This string will typically look like \" (#o1, #x1, ?\\C-a)\".
|
||||
If VALUE is not an integer, nil is returned.
|
||||
This function is used by functions like `prin1' that display the
|
||||
result of expression evaluation."
|
||||
This function is used by commands like `eval-expression' that
|
||||
display the result of expression evaluation."
|
||||
(when (integerp value)
|
||||
(let ((char-string
|
||||
(and (characterp value)
|
||||
(<= value eval-expression-print-maximum-character)
|
||||
(char-displayable-p value)
|
||||
(prin1-char value))))
|
||||
(if char-string
|
||||
|
@ -1484,32 +1493,40 @@ result of expression evaluation."
|
|||
|
||||
(defun eval-expression-get-print-arguments (prefix-argument)
|
||||
"Get arguments for commands that print an expression result.
|
||||
Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT)
|
||||
Returns a list (INSERT-VALUE NO-TRUNCATE CHAR-PRINT-LIMIT)
|
||||
based on PREFIX-ARG. This function determines the interpretation
|
||||
of the prefix argument for `eval-expression' and
|
||||
`eval-last-sexp'."
|
||||
(let ((num (prefix-numeric-value prefix-argument)))
|
||||
(list (not (memq prefix-argument '(nil)))
|
||||
(list (not (memq prefix-argument '(- nil)))
|
||||
(= num 0)
|
||||
(cond ((not (memq prefix-argument '(0 nil))) nil)
|
||||
(t t)))))
|
||||
(cond ((not (memq prefix-argument '(0 -1 - nil))) nil)
|
||||
((= num -1) most-positive-fixnum)
|
||||
(t eval-expression-print-maximum-character)))))
|
||||
|
||||
;; We define this, rather than making `eval' interactive,
|
||||
;; for the sake of completion of names like eval-region, eval-buffer.
|
||||
(defun eval-expression (exp &optional insert-value no-truncate char-print)
|
||||
(defun eval-expression (exp &optional insert-value no-truncate char-print-limit)
|
||||
"Evaluate EXP and print value in the echo area.
|
||||
When called interactively, read an Emacs Lisp expression and evaluate it.
|
||||
Value is also consed on to front of the variable `values'.
|
||||
If the resulting value is an integer, it will be printed in
|
||||
several additional formats (octal, hexadecimal, and character).
|
||||
Optional argument INSERT-VALUE non-nil (interactively, with
|
||||
prefix argument) means insert the result into the current buffer
|
||||
instead of printing it in the echo area.
|
||||
When called interactively, read an Emacs Lisp expression and
|
||||
evaluate it. Value is also consed on to front of the variable
|
||||
`values'. Optional argument INSERT-VALUE non-nil (interactively,
|
||||
with a non `-' prefix argument) means insert the result into the
|
||||
current buffer instead of printing it in the echo area.
|
||||
|
||||
Normally, this function truncates long output according to the value
|
||||
of the variables `eval-expression-print-length' and
|
||||
`eval-expression-print-level'. With a prefix argument of zero,
|
||||
however, there is no such truncation.
|
||||
Normally, this function truncates long output according to the
|
||||
value of the variables `eval-expression-print-length' and
|
||||
`eval-expression-print-level'. When NO-TRUNCATE is
|
||||
non-nil (interactively, with a prefix argument of zero), however,
|
||||
there is no such truncation.
|
||||
|
||||
If the resulting value is an integer, and CHAR-PRINT-LIMIT is
|
||||
non-nil (interactively, unless given a positive prefix argument)
|
||||
it will be printed in several additional formats (octal,
|
||||
hexadecimal, and character). The character format is only used
|
||||
if the value is below CHAR-PRINT-LIMIT (interactively, if the
|
||||
prefix argument is -1 or the value is below
|
||||
`eval-expression-print-maximum-character').
|
||||
|
||||
Runs the hook `eval-expression-minibuffer-setup-hook' on entering the
|
||||
minibuffer.
|
||||
|
@ -1535,11 +1552,12 @@ this command arranges for all errors to enter the debugger."
|
|||
|
||||
(let ((print-length (unless no-truncate eval-expression-print-length))
|
||||
(print-level (unless no-truncate eval-expression-print-level))
|
||||
(eval-expression-print-maximum-character char-print-limit)
|
||||
(deactivate-mark))
|
||||
(let ((out (if insert-value (current-buffer) t)))
|
||||
(prog1
|
||||
(prin1 (car values) out)
|
||||
(let ((str (and char-print
|
||||
(let ((str (and char-print-limit
|
||||
(eval-expression-print-format (car values)))))
|
||||
(when str (princ str out)))))))
|
||||
|
||||
|
|
|
@ -132,6 +132,54 @@
|
|||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (current-message) "t")))))
|
||||
|
||||
(ert-deftest eval-last-sexp-print-format-small-int ()
|
||||
(with-temp-buffer
|
||||
(let ((current-prefix-arg '(4)))
|
||||
(erase-buffer) (insert "?A")
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (buffer-string) "?A65")))
|
||||
(let ((current-prefix-arg 0))
|
||||
(erase-buffer) (insert "?A")
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (buffer-string) "?A65 (#o101, #x41, ?A)")))))
|
||||
|
||||
(ert-deftest eval-last-sexp-print-format-small-int-echo ()
|
||||
(skip-unless (not noninteractive))
|
||||
(with-temp-buffer
|
||||
(let ((current-prefix-arg nil))
|
||||
(erase-buffer) (insert "?A") (message nil)
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (current-message) "65 (#o101, #x41, ?A)")))))
|
||||
|
||||
(ert-deftest eval-last-sexp-print-format-large-int ()
|
||||
(with-temp-buffer
|
||||
(let ((eval-expression-print-maximum-character ?A))
|
||||
(let ((current-prefix-arg '(4)))
|
||||
(erase-buffer) (insert "?B")
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (buffer-string) "?B66")))
|
||||
(let ((current-prefix-arg 0))
|
||||
(erase-buffer) (insert "?B")
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (buffer-string) "?B66 (#o102, #x42)")))
|
||||
(let ((current-prefix-arg -1))
|
||||
(erase-buffer) (insert "?B")
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (buffer-string) "?B66 (#o102, #x42, ?B)"))))))
|
||||
|
||||
(ert-deftest eval-last-sexp-print-format-large-int-echo ()
|
||||
(skip-unless (not noninteractive))
|
||||
(with-temp-buffer
|
||||
(let ((eval-expression-print-maximum-character ?A))
|
||||
(let ((current-prefix-arg nil))
|
||||
(erase-buffer) (insert "?B") (message nil)
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (current-message) "66 (#o102, #x42)")))
|
||||
(let ((current-prefix-arg '-))
|
||||
(erase-buffer) (insert "?B") (message nil)
|
||||
(call-interactively #'eval-last-sexp)
|
||||
(should (equal (current-message) "66 (#o102, #x42, ?B)"))))))
|
||||
|
||||
;;; xref
|
||||
|
||||
(defun xref-elisp-test-descr-to-target (xref)
|
||||
|
|
|
@ -396,5 +396,57 @@ See Bug#21722."
|
|||
(call-interactively #'eval-expression)
|
||||
(should (equal (current-message) "t"))))))
|
||||
|
||||
(ert-deftest eval-expression-print-format-small-int ()
|
||||
(with-temp-buffer
|
||||
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?A)))
|
||||
(let ((current-prefix-arg '(4)))
|
||||
(erase-buffer)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (buffer-string) "65")))
|
||||
(let ((current-prefix-arg 0))
|
||||
(erase-buffer)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (buffer-string) "65 (#o101, #x41, ?A)"))))))
|
||||
|
||||
(ert-deftest eval-expression-print-format-small-int-echo ()
|
||||
(skip-unless (not noninteractive))
|
||||
(with-temp-buffer
|
||||
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?A)))
|
||||
(let ((current-prefix-arg nil))
|
||||
(message nil)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (current-message) "65 (#o101, #x41, ?A)"))))))
|
||||
|
||||
(ert-deftest eval-expression-print-format-large-int ()
|
||||
(with-temp-buffer
|
||||
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?B))
|
||||
(eval-expression-print-maximum-character ?A))
|
||||
(let ((current-prefix-arg '(4)))
|
||||
(erase-buffer)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (buffer-string) "66")))
|
||||
(let ((current-prefix-arg 0))
|
||||
(erase-buffer)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (buffer-string) "66 (#o102, #x42)")))
|
||||
(let ((current-prefix-arg -1))
|
||||
(erase-buffer)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (buffer-string) "66 (#o102, #x42, ?B)"))))))
|
||||
|
||||
(ert-deftest eval-expression-print-format-large-int-echo ()
|
||||
(skip-unless (not noninteractive))
|
||||
(with-temp-buffer
|
||||
(cl-letf (((symbol-function 'read--expression) (lambda (&rest _) ?B))
|
||||
(eval-expression-print-maximum-character ?A))
|
||||
(let ((current-prefix-arg nil))
|
||||
(message nil)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (current-message) "66 (#o102, #x42)")))
|
||||
(let ((current-prefix-arg '-))
|
||||
(message nil)
|
||||
(call-interactively #'eval-expression)
|
||||
(should (equal (current-message) "66 (#o102, #x42, ?B)"))))))
|
||||
|
||||
(provide 'simple-test)
|
||||
;;; simple-test.el ends here
|
||||
|
|
Loading…
Add table
Reference in a new issue