diff --git a/lisp/ielm.el b/lisp/ielm.el index fb285e80f6..13bb4693cd 100644 --- a/lisp/ielm.el +++ b/lisp/ielm.el @@ -353,113 +353,117 @@ nonempty, then flushes the buffer." (output "") ; result to display (wbuf ielm-working-buffer) ; current buffer after evaluation (pmark (ielm-pm))) - (unless (ielm-is-whitespace-or-comment string) - (condition-case err - (let ((rout (read-from-string string))) - (setq form (car rout) - pos (cdr rout))) - (error (setq result (error-message-string err)) - (setq error-type "Read error"))) - (unless error-type - ;; Make sure working buffer has not been killed - (if (not (buffer-name ielm-working-buffer)) - (setq result "Working buffer has been killed" - error-type "IELM Error" - wbuf (current-buffer)) - (if (ielm-is-whitespace-or-comment (substring string pos)) - ;; To correctly handle the ielm-local variables *, - ;; ** and ***, we need a temporary buffer to be - ;; current at entry to the inner of the next two let - ;; forms. We need another temporary buffer to exit - ;; that same let. To avoid problems, neither of - ;; these buffers should be alive during the - ;; evaluation of form. - (let* ((*1 *) - (*2 **) - (*3 ***) - (active-process (ielm-process)) - (old-standard-output standard-output) - new-standard-output - ielm-temp-buffer) - (set-match-data ielm-match-data) - (save-excursion - (with-temp-buffer - (condition-case err - (unwind-protect - ;; The next let form creates default - ;; bindings for *, ** and ***. But - ;; these default bindings are - ;; identical to the ielm-local - ;; bindings. Hence, during the - ;; evaluation of form, the - ;; ielm-local values are going to be - ;; used in all buffers except for - ;; other ielm buffers, which override - ;; them. Normally, the variables *1, - ;; *2 and *3 also have default - ;; bindings, which are not overridden. - (let ((* *1) - (** *2) - (*** *3)) - (when (eq standard-output t) - (setf new-standard-output - (ielm-standard-output-impl - active-process)) - (setf standard-output new-standard-output)) - (kill-buffer (current-buffer)) - (set-buffer wbuf) - (setq result - (eval form lexical-binding)) - (setq wbuf (current-buffer)) - (setq - ielm-temp-buffer - (generate-new-buffer " *ielm-temp*")) - (set-buffer ielm-temp-buffer)) - (when ielm-temp-buffer - (kill-buffer ielm-temp-buffer)) - (when (eq new-standard-output standard-output) - (ignore-errors - (funcall standard-output t)) - (setf standard-output old-standard-output))) - (error (setq result (error-message-string err)) - (setq error-type "Eval error")) - (quit (setq result "Quit during evaluation") - (setq error-type "Eval error"))))) - (setq ielm-match-data (match-data))) - (setq error-type "IELM error") - (setq result "More than one sexp in input")))) - - ;; If the eval changed the current buffer, mention it here - (unless (eq wbuf ielm-working-buffer) - (message "current buffer is now: %s" wbuf) - (setq ielm-working-buffer wbuf)) - - (goto-char pmark) - (unless error-type - (condition-case nil - ;; Self-referential objects cause loops in the printer, so - ;; trap quits here. May as well do errors, too - (unless for-effect - (setq output (concat output (pp-to-string result) - (let ((str (eval-expression-print-format result))) - (if str (propertize str 'font-lock-face 'shadow)))))) - (error (setq error-type "IELM Error") - (setq result "Error during pretty-printing (bug in pp)")) - (quit (setq error-type "IELM Error") - (setq result "Quit during pretty-printing")))) - (if error-type + (unwind-protect + (progn + (unless (ielm-is-whitespace-or-comment string) + (condition-case err + (let ((rout (read-from-string string))) + (setq form (car rout) + pos (cdr rout))) + (error (setq result (error-message-string err)) + (setq error-type "Read error"))) + (unless error-type + ;; Make sure working buffer has not been killed + (if (not (buffer-name ielm-working-buffer)) + (setq result "Working buffer has been killed" + error-type "IELM Error" + wbuf (current-buffer)) + (if (ielm-is-whitespace-or-comment (substring string pos)) + ;; To correctly handle the ielm-local variables *, + ;; ** and ***, we need a temporary buffer to be + ;; current at entry to the inner of the next two let + ;; forms. We need another temporary buffer to exit + ;; that same let. To avoid problems, neither of + ;; these buffers should be alive during the + ;; evaluation of form. + (let* ((*1 *) + (*2 **) + (*3 ***) + (active-process (ielm-process)) + (old-standard-output standard-output) + new-standard-output + ielm-temp-buffer) + (set-match-data ielm-match-data) + (save-excursion + (with-temp-buffer + (unwind-protect + ;; The next let form creates default + ;; bindings for *, ** and ***. But + ;; these default bindings are + ;; identical to the ielm-local + ;; bindings. Hence, during the + ;; evaluation of form, the + ;; ielm-local values are going to be + ;; used in all buffers except for + ;; other ielm buffers, which override + ;; them. Normally, the variables *1, + ;; *2 and *3 also have default + ;; bindings, which are not overridden. + (let ((* *1) + (** *2) + (*** *3)) + (setq result nil) + (when (eq standard-output t) + (setf new-standard-output + (ielm-standard-output-impl + active-process)) + (setf standard-output new-standard-output)) + (kill-buffer (current-buffer)) + (set-buffer wbuf) + ;; Will immediately get + ;; overwritten, but only if eval + ;; does not throw an error + (setq error-type "Eval error") + (setq result + (eval form lexical-binding)) + (setq error-type nil) + (setq wbuf (current-buffer)) + (setq + ielm-temp-buffer + (generate-new-buffer " *ielm-temp*")) + (set-buffer ielm-temp-buffer)) + (when ielm-temp-buffer + (kill-buffer ielm-temp-buffer)) + (when (eq new-standard-output standard-output) + (ignore-errors + (funcall standard-output t)) + (setf standard-output old-standard-output))))) + (setq ielm-match-data (match-data))) + (setq error-type "IELM error") + (setq result "More than one sexp in input")))) + + ;; If the eval changed the current buffer, mention it here + (unless (eq wbuf ielm-working-buffer) + (message "current buffer is now: %s" wbuf) + (setq ielm-working-buffer wbuf)) + + (goto-char pmark) + (unless error-type + (condition-case nil + ;; Self-referential objects cause loops in the printer, so + ;; trap quits here. May as well do errors, too + (unless for-effect + (setq output (concat output (pp-to-string result) + (let ((str (eval-expression-print-format result))) + (if str (propertize str 'font-lock-face 'shadow)))))) + (error (setq error-type "IELM Error") + (setq result "Error during pretty-printing (bug in pp)")) + (quit (setq error-type "IELM Error") + (setq result "Quit during pretty-printing")))))) (progn - (when ielm-noisy (ding)) - (setq output (concat output "*** " error-type " *** ")) - (setq output (concat output result))) - ;; There was no error, so shift the *** values - (setq *** **) - (setq ** *) - (setq * result)) - (when (or (not for-effect) (not (equal output ""))) - (setq output (concat output "\n")))) - (setq output (concat output ielm-prompt-internal)) - (comint-output-filter (ielm-process) output))) + (if error-type + (progn + (when ielm-noisy (ding)) + (setq output (concat output "*** " error-type " *** ")) + (setq output (concat output result))) + ;; There was no error, so shift the *** values + (setq *** **) + (setq ** *) + (setq * result)) + (when (or (not for-effect) (not (equal output ""))) + (setq output (concat output "\n")))) + (setq output (concat output ielm-prompt-internal)) + (comint-output-filter (ielm-process) output)))) ;;; Process and marker utilities @@ -517,9 +521,6 @@ causes output to be directed to the ielm buffer. set to a different value during evaluation. You can use (princ VALUE) or (pp VALUE) to write to the ielm buffer. -Expressions evaluated by IELM are not subject to `debug-on-quit' or -`debug-on-error'. - The behavior of IELM may be customized with the following variables: * To stop beeping on error, set `ielm-noisy' to nil. * If you don't like the prompt, you can change it by setting `ielm-prompt'.