commit f24aa0f46af1f808aa051fdbb44876a1141c928c (HEAD, refs/remotes/origin/master) Merge: 2002ac376c9 3965c65d5e2 Author: Stefan Kangas Date: Wed Mar 29 06:30:09 2023 +0200 Merge from origin/emacs-29 3965c65d5e2 ; * lisp/subr.el (read-char-choice): Fix last change. c1eac5b6586 Improve documentation of 'read-choice' and related symbols a8c9283e170 Revert "Comp fix calls to redefined primtives with op-byt... 8b66d8abd01 Revert "* lisp/emacs-lisp/comp.el (comp-emit-set-call-sub... 4ec4f614c71 ; Fix incompatibility in 'display-buffer-assq-regexp' ba3ade58f3b Skip ruby-ts-imenu-index test if needed 9133446db87 Fix Eglot Tramp tests on EMBA 5b351bc7fa9 * test/infra/Dockerfile.emba (emacs-gnustep): Instrument ... commit 2002ac376c97382cace161ef0832a6faf6f376e8 Author: Dmitry Gutov Date: Wed Mar 29 01:08:55 2023 +0300 ruby-ts-mode: Rehash which nodes should be treated as sexps * lisp/progmodes/ruby-ts-mode.el (ruby-ts-mode): Recognize smaller syntactic elements as sexps too (bug#62416). Also do that for heredocs, regexps and symbol arrays. But drop binary expressions (including assignments) since they led to non-intuitive behavior. diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el index 97c7cf6480c..1a085b669ee 100644 --- a/lisp/progmodes/ruby-ts-mode.el +++ b/lisp/progmodes/ruby-ts-mode.el @@ -1114,21 +1114,32 @@ ruby-ts-mode (setq-local treesit-defun-type-regexp ruby-ts--method-regex) (setq-local treesit-sexp-type-regexp - (regexp-opt '("class" - "module" - "method" - "argument_list" - "array" - "hash" - "parenthesized_statements" - "if" - "case" - "when" - "block" - "do_block" - "begin" - "binary" - "assignment"))) + (rx bol + (or "class" + "module" + "method" + "array" + "hash" + "parenthesized_statements" + "if" + "case" + "when" + "block" + "do_block" + "begin" + "integer" + "identifier" + "constant" + "simple_symbol" + "symbol_array" + "hash_key_symbol" + "string" + "string_array" + "heredoc_body" + "regex" + "argument_list" + ) + eol)) ;; AFAIK, Ruby can not nest methods (setq-local treesit-defun-prefer-top-level nil) commit cde38f0df3fa3540ce411a48d95da1c2f1be1b60 Author: Jim Porter Date: Mon Mar 20 17:25:54 2023 -0700 Avoid parsing some Eshell forms when performing completion During completion, we want to evaluate most Eshell forms (e.g. variable references), but skip others (e.g. globbing, subcommands). For globbing, we want to pass the literal glob to Pcomplete so it can use the glob for selecting completion candidates. For subcommands (including Lisp forms), we especially want to avoid evaluation, since they can produce arbitary side effects! (Bug#50470) * lisp/eshell/esh-cmd.el (eshell-allow-commands): New variable... (eshell-commands-forbidden): New error... (eshell-named-command, eshell-lisp-command): ... use them. * lisp/eshell/em-cmpl.el (eshell-complete--eval-argument-form): Disallow command forms and handle errors ourselves. (eshell-complete-parse-arguments): Don't parse glob characters. * test/lisp/eshell/em-cmpl-tests.el (em-cmpl-test/parse-arguments/unevaluated-subcommand) (em-cmpl-test/parse-arguments/unevaluated-lisp-form) (em-cmpl-test/parse-arguments/unevaluated-inner-subcommand) (em-cmpl-test/file-completion/glob, em-cmpl-test/command-completion) (em-cmpl-test/subcommand-completion): New tests. (em-cmpl-test/parse-arguments/pipeline): Remove superfluous let-binding. (em-cmpl-test/file-completion/after-list): Use a list variable rather than a subexpression; the latter is no longer evaluated during completion. (em-cmpl-test/lisp-function-completion): Check "$(func)" syntax. diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el index b65652019d4..732bbb3f1fa 100644 --- a/lisp/eshell/em-cmpl.el +++ b/lisp/eshell/em-cmpl.el @@ -306,9 +306,24 @@ eshell--pcomplete-insert-tab (defun eshell-complete--eval-argument-form (arg) "Evaluate a single Eshell argument form ARG for the purposes of completion." - (let ((result (eshell-do-eval `(eshell-commands ,arg) t))) - (cl-assert (eq (car result) 'quote)) - (cadr result))) + (condition-case err + (let* (;; Don't allow running commands; they could have + ;; arbitrary side effects, which we don't want when we're + ;; just performing completions! + (eshell-allow-commands) + ;; Handle errors ourselves so that we can properly catch + ;; `eshell-commands-forbidden'. + (eshell-handle-errors) + (result (eshell-do-eval `(eshell-commands ,arg) t))) + (cl-assert (eq (car result) 'quote)) + (cadr result)) + (eshell-commands-forbidden + (propertize "\0" 'eshell-argument-stub + (intern (format "%s-command" (cadr err))))) + (error + (lwarn 'eshell :error + "Failed to evaluate argument form during completion: %S" arg) + (propertize "\0" 'eshell-argument-stub 'error)))) (defun eshell-complete-parse-arguments () "Parse the command line arguments for `pcomplete-argument'." @@ -325,23 +340,28 @@ eshell-complete-parse-arguments (if (= begin end) (end-of-line)) (setq end (point-marker))) - (if (setq delim - (catch 'eshell-incomplete - (ignore - (setq args (eshell-parse-arguments begin end))))) - (cond ((member (car delim) '("{" "${" "$<")) - (setq begin (1+ (cadr delim)) - args (eshell-parse-arguments begin end))) - ((member (car delim) '("$'" "$\"" "#<")) - ;; Add the (incomplete) argument to our arguments, and - ;; note its position. - (setq args (append (nth 2 delim) (list (car delim))) - incomplete-arg t) - (push (- (nth 1 delim) 2) posns)) - ((member (car delim) '("(" "$(")) - (throw 'pcompleted (elisp-completion-at-point))) - (t - (eshell--pcomplete-insert-tab)))) + ;; Don't expand globs when parsing arguments; we want to pass any + ;; globs to Pcomplete unaltered. + (declare-function eshell-parse-glob-chars "em-glob" ()) + (let ((eshell-parse-argument-hook (remq #'eshell-parse-glob-chars + eshell-parse-argument-hook))) + (if (setq delim + (catch 'eshell-incomplete + (ignore + (setq args (eshell-parse-arguments begin end))))) + (cond ((member (car delim) '("{" "${" "$<")) + (setq begin (1+ (cadr delim)) + args (eshell-parse-arguments begin end))) + ((member (car delim) '("$'" "$\"" "#<")) + ;; Add the (incomplete) argument to our arguments, and + ;; note its position. + (setq args (append (nth 2 delim) (list (car delim))) + incomplete-arg t) + (push (- (nth 1 delim) 2) posns)) + ((member (car delim) '("(" "$(")) + (throw 'pcompleted (elisp-completion-at-point))) + (t + (eshell--pcomplete-insert-tab))))) (when (get-text-property (1- end) 'comment) (eshell--pcomplete-insert-tab)) (let ((pos (1- end))) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 1a458290dfe..d5237ee1f04 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -293,6 +293,17 @@ eshell-last-async-procs When the process in the CDR completes, resume command evaluation.") +(defvar eshell-allow-commands t + "If non-nil, allow evaluating command forms (including Lisp forms). +If you want to forbid command forms, you can let-bind this to a +non-nil value before calling `eshell-do-eval'. Then, any command +forms will signal `eshell-commands-forbidden'. This is useful +if, for example, you want to evaluate simple expressions like +variable expansions, but not fully-evaluate the command. See +also `eshell-complete-parse-arguments'.") + +(define-error 'eshell-commands-forbidden "Commands forbidden") + ;;; Functions: (defsubst eshell-interactive-process-p () @@ -1328,6 +1339,8 @@ eshell/which (defun eshell-named-command (command &optional args) "Insert output from a plain COMMAND, using ARGS. COMMAND may result in an alias being executed, or a plain command." + (unless eshell-allow-commands + (signal 'eshell-commands-forbidden '(named))) (setq eshell-last-arguments args eshell-last-command-name (eshell-stringify command)) (run-hook-with-args 'eshell-prepare-command-hook) @@ -1465,6 +1478,8 @@ eshell-last-output-end (defun eshell-lisp-command (object &optional args) "Insert Lisp OBJECT, using ARGS if a function." + (unless eshell-allow-commands + (signal 'eshell-commands-forbidden '(lisp))) (catch 'eshell-external ; deferred to an external command (setq eshell-last-command-status 0 eshell-last-arguments args) diff --git a/test/lisp/eshell/em-cmpl-tests.el b/test/lisp/eshell/em-cmpl-tests.el index ea907f1945d..29a41625d5e 100644 --- a/test/lisp/eshell/em-cmpl-tests.el +++ b/test/lisp/eshell/em-cmpl-tests.el @@ -69,11 +69,10 @@ eshell-arguments-equal--equal-explainer (ert-deftest em-cmpl-test/parse-arguments/pipeline () "Test that parsing arguments for completion discards earlier commands." (with-temp-eshell - (let ((eshell-test-value '("foo" "bar"))) - (insert "echo hi | cat") - (should (eshell-arguments-equal - (car (eshell-complete-parse-arguments)) - '("cat")))))) + (insert "echo hi | cat") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + '("cat"))))) (ert-deftest em-cmpl-test/parse-arguments/multiple-dots () "Test parsing arguments with multiple dots like \".../\"." @@ -123,6 +122,45 @@ em-cmpl-test/parse-arguments/variable/splice (car (eshell-complete-parse-arguments)) '("echo" "foo" "bar")))))) +(ert-deftest em-cmpl-test/parse-arguments/unevaluated-subcommand () + "Test that subcommands return a stub when parsing for completion." + (with-temp-eshell + (insert "echo {echo hi}") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + `("echo" ,(propertize + "\0" 'eshell-argument-stub 'named-command))))) + (with-temp-eshell + (insert "echo ${echo hi}") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + `("echo" ,(propertize + "\0" 'eshell-argument-stub 'named-command)))))) + +(ert-deftest em-cmpl-test/parse-arguments/unevaluated-lisp-form () + "Test that Lisp forms return a stub when parsing for completion." + (with-temp-eshell + (insert "echo (concat \"hi\")") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + `("echo" ,(propertize + "\0" 'eshell-argument-stub 'lisp-command))))) + (with-temp-eshell + (insert "echo $(concat \"hi\")") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + `("echo" ,(propertize + "\0" 'eshell-argument-stub 'lisp-command)))))) + +(ert-deftest em-cmpl-test/parse-arguments/unevaluated-inner-subcommand () + "Test that nested subcommands return a stub when parsing for completion." + (with-temp-eshell + (insert "echo $exec-path[${echo 0}]") + (should (eshell-arguments-equal + (car (eshell-complete-parse-arguments)) + `("echo" ,(propertize + "\0" 'eshell-argument-stub 'named-command)))))) + (ert-deftest em-cmpl-test/file-completion/unique () "Test completion of file names when there's a unique result." (with-temp-eshell @@ -150,14 +188,39 @@ em-cmpl-test/file-completion/non-unique (forward-line -1) (should (looking-at "Complete, but not unique"))))))) +(ert-deftest em-cmpl-test/file-completion/glob () + "Test completion of file names using a glob." + (with-temp-eshell + (ert-with-temp-directory default-directory + (write-region nil nil (expand-file-name "file.txt")) + (write-region nil nil (expand-file-name "file.el")) + (should (equal (eshell-insert-and-complete "echo fi*.el") + "echo file.el "))))) + (ert-deftest em-cmpl-test/file-completion/after-list () "Test completion of file names after previous list arguments. See bug#59956." (with-temp-eshell - (ert-with-temp-directory default-directory - (write-region nil nil (expand-file-name "file.txt")) - (should (equal (eshell-insert-and-complete "echo (list 1 2) fi") - "echo (list 1 2) file.txt "))))) + (let ((eshell-test-value '("foo" "bar"))) + (ert-with-temp-directory default-directory + (write-region nil nil (expand-file-name "file.txt")) + (should (equal (eshell-insert-and-complete "echo $eshell-test-value fi") + "echo $eshell-test-value file.txt ")))))) + +(ert-deftest em-cmpl-test/command-completion () + "Test completion of command names like \"command\"." + (with-temp-eshell + (should (equal (eshell-insert-and-complete "listif") + "listify ")))) + +(ert-deftest em-cmpl-test/subcommand-completion () + "Test completion of command names like \"{command}\"." + (with-temp-eshell + (should (equal (eshell-insert-and-complete "{ listif") + "{ listify "))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo ${ listif") + "echo ${ listify ")))) (ert-deftest em-cmpl-test/lisp-symbol-completion () "Test completion of Lisp forms like \"#'symbol\" and \"`symbol\". @@ -174,7 +237,10 @@ em-cmpl-test/lisp-function-completion See ." (with-temp-eshell (should (equal (eshell-insert-and-complete "echo (eshell/ech") - "echo (eshell/echo")))) + "echo (eshell/echo"))) + (with-temp-eshell + (should (equal (eshell-insert-and-complete "echo $(eshell/ech") + "echo $(eshell/echo")))) (ert-deftest em-cmpl-test/special-ref-completion/type () "Test completion of the start of special references like \"# Date: Mon Mar 20 17:25:24 2023 -0700 Simplify parsing subcommands slightly This mainly reduces some overly-deep indentation, but also fixes some minor issues with the "$" form: it unnecessarily added " > TEMP" (we already set this later via 'eshell-create-handles'), and it didn't properly unescape inner double quotes. * lisp/eshell/esh-cmd.el (eshell-parse-subcommand-argument): Simplify. * lisp/eshell/esh-var.el (eshell-parse-variable-ref): Simplify and fix edge cases in "$". * test/lisp/eshell/esh-var-tests.el (esh-var-test/quoted-interp-temp-cmd): Adjust test to check behavior of inner double quotes. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index e0651b76249..1a458290dfe 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -675,13 +675,13 @@ eshell-parse-subcommand-argument (or (= (point-max) (1+ (point))) (not (eq (char-after (1+ (point))) ?\})))) (let ((end (eshell-find-delimiter ?\{ ?\}))) - (if (not end) - (throw 'eshell-incomplete "{") - (when (eshell-arg-delimiter (1+ end)) - (prog1 - `(eshell-as-subcommand - ,(eshell-parse-command (cons (1+ (point)) end))) - (goto-char (1+ end)))))))) + (unless end + (throw 'eshell-incomplete "{")) + (when (eshell-arg-delimiter (1+ end)) + (prog1 + `(eshell-as-subcommand + ,(eshell-parse-command (cons (1+ (point)) end))) + (goto-char (1+ end))))))) (defun eshell-parse-lisp-argument () "Parse a Lisp expression which is specified as an argument." diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el index 5d6299af564..7dcaff1e24f 100644 --- a/lisp/eshell/esh-var.el +++ b/lisp/eshell/esh-var.el @@ -507,55 +507,56 @@ eshell-parse-variable-ref (cond ((eq (char-after) ?{) (let ((end (eshell-find-delimiter ?\{ ?\}))) - (if (not end) - (throw 'eshell-incomplete "${") - (forward-char) - (prog1 - `(eshell-apply-indices - (eshell-convert - (eshell-command-to-value - (eshell-as-subcommand - ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) - (cons (point) end))) - (eshell-current-quoted nil)) - (eshell-parse-command subcmd)))) - ;; If this is a simple double-quoted form like - ;; "${COMMAND}" (i.e. no indices after the subcommand - ;; and no `#' modifier before), ensure we convert to a - ;; single string. This avoids unnecessary work - ;; (e.g. splitting the output by lines) when it would - ;; just be joined back together afterwards. - ,(when (and (not modifier-p) eshell-current-quoted) - '(not indices))) - indices ,eshell-current-quoted) - (goto-char (1+ end)))))) + (unless end + (throw 'eshell-incomplete "${")) + (forward-char) + (prog1 + `(eshell-apply-indices + (eshell-convert + (eshell-command-to-value + (eshell-as-subcommand + ,(let ((subcmd (or (eshell-unescape-inner-double-quote end) + (cons (point) end))) + (eshell-current-quoted nil)) + (eshell-parse-command subcmd)))) + ;; If this is a simple double-quoted form like + ;; "${COMMAND}" (i.e. no indices after the subcommand and + ;; no `#' modifier before), ensure we convert to a single + ;; string. This avoids unnecessary work (e.g. splitting + ;; the output by lines) when it would just be joined back + ;; together afterwards. + ,(when (and (not modifier-p) eshell-current-quoted) + '(not indices))) + indices ,eshell-current-quoted) + (goto-char (1+ end))))) ((eq (char-after) ?\<) (let ((end (eshell-find-delimiter ?\< ?\>))) - (if (not end) - (throw 'eshell-incomplete "$<") - (let* ((temp (make-temp-file temporary-file-directory)) - (cmd (concat (buffer-substring (1+ (point)) end) - " > " temp))) - (prog1 - `(let ((eshell-current-handles - (eshell-create-handles ,temp 'overwrite))) - (progn - (eshell-as-subcommand - ,(let ((eshell-current-quoted nil)) - (eshell-parse-command cmd))) - (ignore - (nconc eshell-this-command-hook - ;; Quote this lambda; it will be evaluated - ;; by `eshell-do-eval', which requires very - ;; particular forms in order to work - ;; properly. See bug#54190. - (list (function - (lambda () - (delete-file ,temp) - (when-let ((buffer (get-file-buffer ,temp))) - (kill-buffer buffer))))))) - (eshell-apply-indices ,temp indices ,eshell-current-quoted))) - (goto-char (1+ end))))))) + (unless end + (throw 'eshell-incomplete "$<")) + (forward-char) + (let* ((temp (make-temp-file temporary-file-directory)) + (subcmd (or (eshell-unescape-inner-double-quote end) + (cons (point) end)))) + (prog1 + `(let ((eshell-current-handles + (eshell-create-handles ,temp 'overwrite))) + (progn + (eshell-as-subcommand + ,(let ((eshell-current-quoted nil)) + (eshell-parse-command subcmd))) + (ignore + (nconc eshell-this-command-hook + ;; Quote this lambda; it will be evaluated by + ;; `eshell-do-eval', which requires very + ;; particular forms in order to work + ;; properly. See bug#54190. + (list (function + (lambda () + (delete-file ,temp) + (when-let ((buffer (get-file-buffer ,temp))) + (kill-buffer buffer))))))) + (eshell-apply-indices ,temp indices ,eshell-current-quoted))) + (goto-char (1+ end)))))) ((eq (char-after) ?\() (condition-case nil `(eshell-apply-indices diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el index 6767d9289f9..771bd5a419c 100644 --- a/test/lisp/eshell/esh-var-tests.el +++ b/test/lisp/eshell/esh-var-tests.el @@ -454,7 +454,7 @@ esh-var-test/quoted-interp-temp-cmd (let ((temporary-file-directory (file-name-as-directory (make-temp-file "esh-vars-tests" t)))) (unwind-protect - (eshell-command-result-equal "cat \"$\"" "hi") + (eshell-command-result-equal "cat \"$\"" "hi") (delete-directory temporary-file-directory t)))) (ert-deftest esh-var-test/quoted-interp-concat-cmd () commit 5b005f26a831881b0509f05d3b28dafbbe5bad41 Author: Jim Porter Date: Mon Mar 20 17:24:28 2023 -0700 ; Fix an edge case in how 'eshell-do-eval' handles 'let' bodies * lisp/eshell/esh-cmd.el (ehell-do-eval): Use 'car-safe'; the object in question might not be a cons cell. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 93f2616020c..e0651b76249 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -1168,7 +1168,7 @@ eshell-do-eval (setcar (cdr args) (eshell-do-eval (cadr args) synchronous-p)) (eval form)) ((eq (car form) 'let) - (when (not (eq (car (cadr args)) 'eshell-do-eval)) + (unless (eq (car-safe (cadr args)) 'eshell-do-eval) (eshell-manipulate "evaluating let args" (dolist (letarg (car args)) (when (and (listp letarg) commit 3965c65d5e28e0efdfa693046f6a2059e74465f9 (refs/remotes/origin/emacs-29) Author: Eli Zaretskii Date: Tue Mar 28 21:31:51 2023 +0300 ; * lisp/subr.el (read-char-choice): Fix last change. diff --git a/lisp/subr.el b/lisp/subr.el index a9d93e5fe5e..f82826e819c 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3210,13 +3210,15 @@ read-char-choice "Read and return one of the characters in CHARS, prompting with PROMPT. CHARS should be a list of single characters. The function discards any input character that is not one of CHARS, -and shows a message to the effect that it is not one of the expected -charcaters. - -By default, use the minibuffer to read the key non-modally (see -`read-char-from-minibuffer'). But if `read-char-choice-use-read-key' -is non-nil, the modal `read-key' function is used instead (see -`read-char-choice-with-read-key')." +and by default shows a message to the effect that it is not one of +the expected characters. + +By default, this function uses the minibuffer to read the key +non-modally (see `read-char-from-minibuffer'), and the optional +argument INHIBIT-KEYBOARD-QUIT is ignored. However, if +`read-char-choice-use-read-key' is non-nil, the modal `read-key' +function is used instead (see `read-char-choice-with-read-key'), +and INHIBIT-KEYBOARD-QUIT is passed to it." (if (not read-char-choice-use-read-key) (read-char-from-minibuffer prompt chars) (read-char-choice-with-read-key prompt chars inhibit-keyboard-quit))) commit c1eac5b6586a79e0d84cbdb2ea310b7acee66414 Author: Eli Zaretskii Date: Tue Mar 28 21:08:12 2023 +0300 Improve documentation of 'read-choice' and related symbols * doc/lispref/commands.texi (Reading One Event): * lisp/subr.el (read-char-choice-use-read-key, read-char-choice) (read-char-choice-with-read-key, y-or-n-p-use-read-key): Improve documentation of these functions and variables. diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index 20be706bebd..62a0939a47e 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -3215,15 +3215,24 @@ Reading One Event event. @end defun +@vindex read-char-choice-use-read-key @defun read-char-choice prompt chars &optional inhibit-quit -This function uses @code{read-key} to read and return a single -character. It ignores any input that is not a member of @var{chars}, -a list of accepted characters. Optionally, it will also ignore -keyboard-quit events while it is waiting for valid input. If you bind -@code{help-form} (@pxref{Help Functions}) to a non-@code{nil} value -while calling @code{read-char-choice}, then pressing @code{help-char} -causes it to evaluate @code{help-form} and display the result. It -then continues to wait for a valid input character, or keyboard-quit. +This function uses @code{read-from-minibuffer} to read and return a +single character that is a member of @var{chars}, which should be a +list of single characters. It discards any input characters that are +not members of @var{chars}, and shows a message to that effect. + +The optional argument @var{inhibit-quit} is by default ignored, but if +the variable @code{read-char-choice-use-read-key} is non-@code{nil}, +this function uses @code{read-key} instead of +@code{read-from-minibuffer}, and in that case @var{inhibit-quit} +non-@code{nil} means ignore keyboard-quit events while waiting for +valid input. In addition, if @code{read-char-choice-use-read-key} is +non-@code{nil}, binding @code{help-form} (@pxref{Help Functions}) to a +non-@code{nil} value while calling this function causes it to evaluate +@code{help-form} and display the result when the user presses +@code{help-char}; it then continues to wait for a valid input +character, or for keyboard-quit. @end defun @defun read-multiple-choice prompt choices &optional help-string show-help long-form diff --git a/lisp/subr.el b/lisp/subr.el index 8d27c831c96..a9d93e5fe5e 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3196,34 +3196,38 @@ read-number n)) (defvar read-char-choice-use-read-key nil - "Prefer `read-key' when reading a character by `read-char-choice'. -Otherwise, use the minibuffer. + "If non-nil, use `read-key' when reading a character by `read-char-choice'. +Otherwise, use the minibuffer (this is the default). -When using the minibuffer, the user is less constrained, and can -use the normal commands available in the minibuffer, and can, for -instance, switch to another buffer, do things there, and then -switch back again to the minibuffer before entering the -character. This is not possible when using `read-key', but using -`read-key' may be less confusing to some users.") +When reading via the minibuffer, you can use the normal commands +available in the minibuffer, and can, for instance, temporarily +switch to another buffer, do things there, and then switch back +to the minibuffer before entering the character. This is not +possible when using `read-key', but using `read-key' may be less +confusing to some users.") (defun read-char-choice (prompt chars &optional inhibit-keyboard-quit) - "Read and return one of CHARS, prompting for PROMPT. -Any input that is not one of CHARS is ignored. - -By default, the minibuffer is used to read the key -non-modally (see `read-char-from-minibuffer'). If -`read-char-choice-use-read-key' is non-nil, the modal `read-key' -function is used instead (see `read-char-choice-with-read-key')." + "Read and return one of the characters in CHARS, prompting with PROMPT. +CHARS should be a list of single characters. +The function discards any input character that is not one of CHARS, +and shows a message to the effect that it is not one of the expected +charcaters. + +By default, use the minibuffer to read the key non-modally (see +`read-char-from-minibuffer'). But if `read-char-choice-use-read-key' +is non-nil, the modal `read-key' function is used instead (see +`read-char-choice-with-read-key')." (if (not read-char-choice-use-read-key) (read-char-from-minibuffer prompt chars) (read-char-choice-with-read-key prompt chars inhibit-keyboard-quit))) (defun read-char-choice-with-read-key (prompt chars &optional inhibit-keyboard-quit) - "Read and return one of CHARS, prompting for PROMPT. + "Read and return one of the characters in CHARS, prompting with PROMPT. +CHARS should be a list of single characters. Any input that is not one of CHARS is ignored. If optional argument INHIBIT-KEYBOARD-QUIT is non-nil, ignore -`keyboard-quit' events while waiting for a valid input. +`keyboard-quit' events while waiting for valid input. If you bind the variable `help-form' to a non-nil value while calling this function, then pressing `help-char' @@ -3519,15 +3523,15 @@ y-or-n-p-insert-other (sit-for 2))) (defvar y-or-n-p-use-read-key nil - "Prefer `read-key' when answering a \"y or n\" question by `y-or-n-p'. -Otherwise, use the minibuffer. - -When using the minibuffer, the user is less constrained, and can -use the normal commands available in the minibuffer, and can, for -instance, switch to another buffer, do things there, and then -switch back again to the minibuffer before entering the -character. This is not possible when using `read-key', but using -`read-key' may be less confusing to some users.") + "Use `read-key' when reading answers to \"y or n\" questions by `y-or-n-p'. +Otherwise, use the `read-from-minibuffer' to read the answers. + +When reading via the minibuffer, you can use the normal commands +available in the minibuffer, and can, for instance, temporarily +switch to another buffer, do things there, and then switch back +to the minibuffer before entering the character. This is not +possible when using `read-key', but using `read-key' may be less +confusing to some users.") (defvar from--tty-menu-p nil "Non-nil means the current command was invoked from a TTY menu.") commit a8c9283e1702af06fb6ad598ae32a2c124860af1 Author: Andrea Corallo Date: Tue Mar 28 14:56:47 2023 +0200 Revert "Comp fix calls to redefined primtives with op-bytecode (bug#61917)" This reverts commit 263d6c38539691c954f4c3057cbe8d5468499b91. These patch series caused a number of regression and more analysis is required. diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index febca8df19c..283c00103b5 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -1773,25 +1773,17 @@ comp-emit-set-call-subr (maxarg (cdr arity))) (when (eq maxarg 'unevalled) (signal 'native-ice (list "subr contains unevalled args" subr-name))) - (if (not (subrp subr-name)) - ;; The primitive got redefined before the compiler is - ;; invoked! (bug#61917) - (comp-emit-set-call `(callref funcall - ,(make-comp-mvar :constant subr-name) - ,@(cl-loop repeat nargs - for sp from (comp-sp) - collect (comp-slot-n sp)))) - (if (eq maxarg 'many) - ;; callref case. - (comp-emit-set-call (comp-callref subr-name nargs (comp-sp))) - ;; Normal call. - (unless (and (>= maxarg nargs) (<= minarg nargs)) - (signal 'native-ice - (list "incoherent stack adjustment" nargs maxarg minarg))) - (let* ((subr-name subr-name) - (slots (cl-loop for i from 0 below maxarg - collect (comp-slot-n (+ i (comp-sp)))))) - (comp-emit-set-call (apply #'comp-call (cons subr-name slots))))))))) + (if (eq maxarg 'many) + ;; callref case. + (comp-emit-set-call (comp-callref subr-name nargs (comp-sp))) + ;; Normal call. + (unless (and (>= maxarg nargs) (<= minarg nargs)) + (signal 'native-ice + (list "incoherent stack adjustment" nargs maxarg minarg))) + (let* ((subr-name subr-name) + (slots (cl-loop for i from 0 below maxarg + collect (comp-slot-n (+ i (comp-sp)))))) + (comp-emit-set-call (apply #'comp-call (cons subr-name slots)))))))) (eval-when-compile (defun comp-op-to-fun (x) diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el index 1615b2838fc..926ba27e563 100644 --- a/test/src/comp-tests.el +++ b/test/src/comp-tests.el @@ -532,19 +532,6 @@ 48029-1 (should (subr-native-elisp-p (symbol-function 'comp-test-48029-nonascii-žžž-f)))) -(comp-deftest 61917-1 () - "Verify we can compile calls to redefined primitives with -dedicated byte-op code." - (let ((f (lambda (fn &rest args) - (apply fn args)))) - (advice-add #'delete-region :around f) - (unwind-protect - (should (subr-native-elisp-p - (native-compile - '(lambda () - (delete-region (point-min) (point-max)))))) - (advice-remove #'delete-region f)))) - ;;;;;;;;;;;;;;;;;;;;; ;; Tromey's tests. ;; commit 8b66d8abd0119a250bc81ca7625a0c8de3e40555 Author: Andrea Corallo Date: Tue Mar 28 14:56:37 2023 +0200 Revert "* lisp/emacs-lisp/comp.el (comp-emit-set-call-subr): Improve..." This reverts commit 4a7a0c9a9f521b04b23580901e9c0a662b504e32. These patch series caused a number of regression and more analysis is required. diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 3dcbc2cca4d..febca8df19c 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -1773,7 +1773,7 @@ comp-emit-set-call-subr (maxarg (cdr arity))) (when (eq maxarg 'unevalled) (signal 'native-ice (list "subr contains unevalled args" subr-name))) - (if (not (subr-primitive-p subr-name)) + (if (not (subrp subr-name)) ;; The primitive got redefined before the compiler is ;; invoked! (bug#61917) (comp-emit-set-call `(callref funcall commit 4ec4f614c712b8283b669feb7a6f87a700cdf2e6 Author: Eli Zaretskii Date: Tue Mar 28 14:08:29 2023 +0300 ; Fix incompatibility in 'display-buffer-assq-regexp' * lisp/window.el (display-buffer-assq-regexp): Make it accept a buffer's name again, as it did in Emacs 28. This makes computing the buffer's name inside the function unnecessary. (display-buffer): Always pass the buffer's name to 'display-buffer-assq-regexp'. (Bug#62417) diff --git a/lisp/window.el b/lisp/window.el index 4bdc26571f5..016d53ffbdd 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7556,19 +7556,16 @@ display-buffer-fallback-action `display-buffer'.") (put 'display-buffer-fallback-action 'risky-local-variable t) -(defun display-buffer-assq-regexp (buffer-or-name alist action) - "Retrieve ALIST entry corresponding to buffer specified by BUFFER-OR-NAME. +(defun display-buffer-assq-regexp (buffer-name alist action) + "Retrieve ALIST entry corresponding to buffer whose name is BUFFER-NAME. This returns the cdr of the alist entry ALIST if the entry's key (its car) and the name of the buffer designated by -BUFFER-OR-NAME satisfy `buffer-match-p', using the key as +BUFFER-NAME satisfy `buffer-match-p', using the key as CONDITION argument of `buffer-match-p'. ACTION should have the form of the action argument passed to `display-buffer'." (catch 'match (dolist (entry alist) - (when (buffer-match-p (car entry) (if (stringp buffer-or-name) - buffer-or-name - (buffer-name buffer-or-name)) - action) + (when (buffer-match-p (car entry) buffer-name action) (throw 'match (cdr entry)))))) (defvar display-buffer--same-window-action @@ -7727,6 +7724,9 @@ display-buffer (let ((buffer (if (bufferp buffer-or-name) buffer-or-name (get-buffer buffer-or-name))) + (buf-name (if (bufferp buffer-or-name) + (buffer-name buffer-or-name) + buffer-or-name)) ;; Make sure that when we split windows the old window keeps ;; point, bug#14829. (split-window-keep-point t) @@ -7735,7 +7735,7 @@ display-buffer (unless (listp action) (setq action nil)) (let* ((user-action (display-buffer-assq-regexp - buffer display-buffer-alist action)) + buf-name display-buffer-alist action)) (special-action (display-buffer--special-action buffer)) ;; Extra actions from the arguments to this function: (extra-action commit ba3ade58f3b7083b40e4f995388d6246cc81ba82 Author: Michael Albinus Date: Tue Mar 28 13:04:09 2023 +0200 Skip ruby-ts-imenu-index test if needed * test/lisp/progmodes/ruby-ts-mode-tests.el (ruby-ts-imenu-index): Add check for treesitter. diff --git a/test/lisp/progmodes/ruby-ts-mode-tests.el b/test/lisp/progmodes/ruby-ts-mode-tests.el index 11125dc5cd3..55782f886f6 100644 --- a/test/lisp/progmodes/ruby-ts-mode-tests.el +++ b/test/lisp/progmodes/ruby-ts-mode-tests.el @@ -282,6 +282,7 @@ ruby-ts-resource-file (expand-file-name (format "ruby-mode-resources/%s" ,file)))))) (ert-deftest ruby-ts-imenu-index () + (skip-unless (treesit-ready-p 'ruby t)) (ruby-ts-with-temp-buffer (ruby-ts-test-string "module Foo commit 9133446db873415e05f331d9bd55cdfe960a0c55 Author: Michael Albinus Date: Tue Mar 28 12:43:01 2023 +0200 Fix Eglot Tramp tests on EMBA * test/lisp/progmodes/eglot-tests.el (eglot--call-with-tramp-test): Bind `tramp-allow-unsafe-temporary-files' with t. (Bug#62289) diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 7a90d68d213..2388cf9ef51 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -1261,6 +1261,7 @@ eglot--call-with-tramp-test ;; really just the local host. (let* ((tramp-remote-path (cons 'tramp-own-remote-path tramp-remote-path)) (tramp-histfile-override t) + (tramp-allow-unsafe-temporary-files t) (tramp-verbose 1) (temporary-file-directory ert-remote-temporary-file-directory) (default-directory temporary-file-directory)) commit 5b351bc7fa94d26ba439461920d2b67595f351d4 Author: Michael Albinus Date: Tue Mar 28 09:38:07 2023 +0200 * test/infra/Dockerfile.emba (emacs-gnustep): Instrument "make V=1 ...". diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba index 593756aba3b..946aa9235fb 100644 --- a/test/infra/Dockerfile.emba +++ b/test/infra/Dockerfile.emba @@ -71,7 +71,7 @@ COPY . /checkout WORKDIR /checkout RUN ./autogen.sh autoconf RUN ./configure --with-ns -RUN make bootstrap +RUN make V=1 bootstrap FROM emacs-base as emacs-native-comp