emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 4a6dd13 2/2: Change 'M-:' to not error out on incomplete expressi


From: Lars Ingebrigtsen
Subject: master 4a6dd13 2/2: Change 'M-:' to not error out on incomplete expressions
Date: Mon, 10 Aug 2020 09:18:26 -0400 (EDT)

branch: master
commit 4a6dd13fa42c87175ac72e1980f31cac56582db3
Author: Charles A. Roelli <charles@aurox.ch>
Commit: Lars Ingebrigtsen <larsi@gnus.org>

    Change 'M-:' to not error out on incomplete expressions
    
    * lisp/simple.el (read--expression-try-read): New function to read
    a Lisp expression from the minibuffer (bug#30697).  This will not
    (as before) signal an error on incomplete expressions, but allow
    users to continue editing it.
    (read--expression): Use it (and add a doc string).
---
 etc/NEWS       |  7 +++++++
 lisp/simple.el | 45 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/etc/NEWS b/etc/NEWS
index e3d7ff0..7a38b4d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -101,6 +101,13 @@ deprecated.  Errors in the Inscript method were corrected.
 
 * Editing Changes in Emacs 28.1
 
+---
+** 'eval-expression' now no longer signals an error on incomplete expressions.
+Previously, typing 'M-: ( RET' would result in Emacs saying "End of
+file during parsing" and dropping out of the minibuffer.  The user
+would have to type 'M-: M-p' to edit and redo the expression.  Now
+Emacs will echo the message and allow the user to continue editing.
+
 +++
 ** New command 'undo-redo'.
 It undoes previous undo commands, but doesn't record itself as an
diff --git a/lisp/simple.el b/lisp/simple.el
index 4a774bc..4d59108 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -1619,6 +1619,10 @@ display the result of expression evaluation."
   "Hook run by `eval-expression' when entering the minibuffer.")
 
 (defun read--expression (prompt &optional initial-contents)
+  "Read an Emacs Lisp expression from the minibuffer.
+
+PROMPT and optional argument INITIAL-CONTENTS do the same as in
+function `read-from-minibuffer'."
   (let ((minibuffer-completing-symbol t))
     (minibuffer-with-setup-hook
         (lambda ()
@@ -1629,11 +1633,52 @@ display the result of expression evaluation."
           (set-syntax-table emacs-lisp-mode-syntax-table)
           (add-hook 'completion-at-point-functions
                     #'elisp-completion-at-point nil t)
+          (local-set-key "\r" 'read--expression-try-read)
+          (local-set-key "\n" 'read--expression-try-read)
           (run-hooks 'eval-expression-minibuffer-setup-hook))
       (read-from-minibuffer prompt initial-contents
                             read-expression-map t
                             'read-expression-history))))
 
+(defun read--expression-try-read ()
+  "Try to read an Emacs Lisp expression in the minibuffer.
+
+Exit the minibuffer if successful, else report the error to the
+user and move point to the location of the error.  If point is
+not already at the location of the error, push a mark before
+moving point."
+  (interactive)
+  (unless (> (minibuffer-depth) 0)
+    (error "Minibuffer must be active"))
+  (if (let* ((contents (minibuffer-contents))
+             (error-point nil))
+        (with-temp-buffer
+          (condition-case err
+              (progn
+                (insert contents)
+                (goto-char (point-min))
+                ;; `read' will signal errors like "End of file during
+                ;; parsing" and "Invalid read syntax".
+                (read (current-buffer))
+                ;; Since `read' does not signal the "Trailing garbage
+                ;; following expression" error, we check for trailing
+                ;; garbage ourselves.
+                (or (progn
+                      ;; This check is similar to what `string_to_object'
+                      ;; does in minibuf.c.
+                      (skip-chars-forward " \t\n")
+                      (= (point) (point-max)))
+                    (error "Trailing garbage following expression")))
+            (error
+             (setq error-point (+ (length (minibuffer-prompt)) (point)))
+             (with-current-buffer (window-buffer (minibuffer-window))
+               (unless (= (point) error-point)
+                 (push-mark))
+               (goto-char error-point)
+               (minibuffer-message (error-message-string err)))
+             nil))))
+      (exit-minibuffer)))
+
 (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-LIMIT)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]