diff options
author | Charles A. Roelli <charles@aurox.ch> | 2020-08-10 15:16:11 +0200 |
---|---|---|
committer | Lars Ingebrigtsen <larsi@gnus.org> | 2020-08-10 15:18:19 +0200 |
commit | 4a6dd13fa42c87175ac72e1980f31cac56582db3 (patch) | |
tree | 074739d26dc3421cbf2c1f2cbcc2b8a42711341e | |
parent | 70825a4d313fddd6f80a1840d775384e848daf9f (diff) | |
download | emacs-4a6dd13fa42c87175ac72e1980f31cac56582db3.tar.gz |
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).
-rw-r--r-- | etc/NEWS | 7 | ||||
-rw-r--r-- | lisp/simple.el | 45 |
2 files changed, 52 insertions, 0 deletions
@@ -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 4a774bc9b4d..4d59108a34f 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) |