Subject: bug#12985: eval-last-sexp looks broken when executed twice

From: Juri Linkov <[email-masked]>
Date: Mon, 06 May 2013 22:57:38 +0300

> Even then the design seems wrong. It's designed to avoid producing the
> string the first time eval-last-sexp or eval-print-last-sexp is
> called, regardless of whether the result will be displayed in the echo
> area (in which case I don't see any reason to avoid it) or printed
> into the buffer (in which case avoiding it is good since the user
> probably wants just the decimal representation).
>
> It seems a better design would be to always include the string, even
> the first time, when displaying in the echo area, and never include
> the string when printing into the buffer, regardless of the invoking
> command name. This is simpler, and it's how eval-expression already works.

Thank you for suggesting a new design.  I agree it is better
than the current design.  The patch below implements it and
removes the feature of behaving differently when called twice.

> And it makes one of my custom functions fail to work the same as
> eval-last-sexp when intended, which is what brought all this to my
> attention in the first place:
>
> (defun eval-region-or-last-sexp ()
>  (interactive)
>  (if mark-active
>   (call-interactively 'eval-region)
>   (call-interactively 'eval-last-sexp)))
>
> I can fix my function using (setq this-command 'eval-last-sexp), but
> that's a kludge.

The function `eval-expression-print-format' in this patch
doesn't compare the command name with `this-command' anymore,
so your function `eval-region-or-last-sexp' above should work now
as intended.

Additionally, it allows a new prefix arg `M-0' to be used as `M-0 C-x C-e'
to print more information with the octal and hex representations
into the current buffer.  It replaces the old feature of calling 'C-x C-e'
twice to do the same.

The documentation could be updated accordingly later.

=== modified file 'lisp/simple.el'
--- lisp/simple.el	2013-04-18 13:15:08 +0000
+++ lisp/simple.el	2013-05-06 19:57:05 +0000
@@ -1280,12 +1280,10 @@ (defun eval-expression-print-format (val
 in addition to the value printed by prin1 in functions which
 display the result of expression evaluation."
   (if (and (integerp value)
-           (or (not (memq this-command '(eval-last-sexp eval-print-last-sexp)))
-               (eq this-command last-command)
-               (if (boundp 'edebug-active) edebug-active)))
+	   (or (eq standard-output t)
+	       (zerop (prefix-numeric-value current-prefix-arg))))
       (let ((char-string
-             (if (or (if (boundp 'edebug-active) edebug-active)
-		     (memq this-command '(eval-last-sexp eval-print-last-sexp)))
+	     (if (char-displayable-p value)
                  (prin1-char value))))
         (if char-string
             (format " (#o%o, #x%x, %s)" value value char-string)