From b3502b922821fd100fb86b8cda6a0a62fba7d394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?andr=C3=A9s=20ram=C3=ADrez?= Date: Mon, 13 Feb 2023 15:02:52 +0000 Subject: [PATCH 1/3] Allow disabling viper faces in the minibuffer * lisp/emulation/viper-cmd.el (viper-enable-minibuffer-faces): New defcustom. (viper-set-mode-vars-for): Use it to decide whether to use distinct faces in the minibuffer. (Bug#61432) Copyright-paperwork-exempt: yes --- lisp/emulation/viper-cmd.el | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el index 0eb58565b37..8cf81c33b5b 100644 --- a/lisp/emulation/viper-cmd.el +++ b/lisp/emulation/viper-cmd.el @@ -466,6 +466,12 @@ ;; Viper mode-changing commands and utilities +(defcustom viper-enable-minibuffer-faces t + "If non-nil, viper uses distinct faces in the minibuffer." + :type 'boolean + :version "30.1" + :group 'viper-misc) + ;; Modifies mode-line-buffer-identification. (defun viper-refresh-mode-line () (setq-local viper-mode-string @@ -561,7 +567,7 @@ )) ;; minibuffer faces - (if (viper-has-face-support-p) + (if (and (viper-has-face-support-p) viper-enable-minibuffer-faces) (setq viper-minibuffer-current-face (cond ((eq state 'emacs-state) viper-minibuffer-emacs-face) ((eq state 'vi-state) viper-minibuffer-vi-face) From 2ac8d7e64a08ea6e22bb90ad16e2880440fbcf16 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 18 Feb 2023 18:27:56 +0100 Subject: [PATCH 2/3] Improve Tramp's user and host name completion * lisp/net/tramp.el (tramp-completion-handle-file-exists-p): Improve user name completion. (tramp-skeleton-file-exists-p): New defmacro, which also handles host name completion. (tramp-handle-file-exists-p): * lisp/net/tramp-adb.el (tramp-adb-handle-file-exists-p): * lisp/net/tramp-sh.el (tramp-sh-handle-file-exists-p): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-file-exists-p): Use it. --- lisp/net/tramp-adb.el | 13 ++------- lisp/net/tramp-sh.el | 21 +++++--------- lisp/net/tramp-sudoedit.el | 13 ++------- lisp/net/tramp.el | 58 +++++++++++++++++++++++++------------- 4 files changed, 51 insertions(+), 54 deletions(-) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 38fd8a4e258..f8c38859477 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -487,16 +487,9 @@ Emacs dired can't find files." (defun tramp-adb-handle-file-exists-p (filename) "Like `file-exists-p' for Tramp files." - ;; `file-exists-p' is used as predicate in file name completion. - ;; We don't want to run it when `non-essential' is t, or there is - ;; no connection process yet. - (when (tramp-connectable-p filename) - (with-parsed-tramp-file-name (expand-file-name filename) nil - (with-tramp-file-property v localname "file-exists-p" - (if (tramp-file-property-p v localname "file-attributes") - (not (null (tramp-get-file-property v localname "file-attributes"))) - (tramp-adb-send-command-and-check - v (format "test -e %s" (tramp-shell-quote-argument localname)))))))) + (tramp-skeleton-file-exists-p filename + (tramp-adb-send-command-and-check + v (format "test -e %s" (tramp-shell-quote-argument localname))))) (defun tramp-adb-handle-file-readable-p (filename) "Like `file-readable-p' for Tramp files." diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 7a6c9658aa9..b3d837f9514 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -1186,20 +1186,13 @@ Operations not mentioned here will be handled by the normal Emacs functions.") (defun tramp-sh-handle-file-exists-p (filename) "Like `file-exists-p' for Tramp files." - ;; `file-exists-p' is used as predicate in file name completion. - ;; We don't want to run it when `non-essential' is t, or there is - ;; no connection process yet. - (when (tramp-connectable-p filename) - (with-parsed-tramp-file-name (expand-file-name filename) nil - (with-tramp-file-property v localname "file-exists-p" - (if (tramp-file-property-p v localname "file-attributes") - (not (null (tramp-get-file-property v localname "file-attributes"))) - (tramp-send-command-and-check - v - (format - "%s %s" - (tramp-get-file-exists-command v) - (tramp-shell-quote-argument localname)))))))) + (tramp-skeleton-file-exists-p filename + (tramp-send-command-and-check + v + (format + "%s %s" + (tramp-get-file-exists-command v) + (tramp-shell-quote-argument localname))))) (defun tramp-sh-handle-file-attributes (filename &optional id-format) "Like `file-attributes' for Tramp files." diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el index 1f646253579..fa1689d6851 100644 --- a/lisp/net/tramp-sudoedit.el +++ b/lisp/net/tramp-sudoedit.el @@ -454,16 +454,9 @@ the result will be a local, non-Tramp, file name." (defun tramp-sudoedit-handle-file-exists-p (filename) "Like `file-exists-p' for Tramp files." - ;; `file-exists-p' is used as predicate in file name completion. - ;; We don't want to run it when `non-essential' is t, or there is - ;; no connection process yet. - (when (tramp-connectable-p filename) - (with-parsed-tramp-file-name (expand-file-name filename) nil - (with-tramp-file-property v localname "file-exists-p" - (if (tramp-file-property-p v localname "file-attributes") - (not (null (tramp-get-file-property v localname "file-attributes"))) - (tramp-sudoedit-send-command - v "test" "-e" (file-name-unquote localname))))))) + (tramp-skeleton-file-exists-p filename + (tramp-sudoedit-send-command + v "test" "-e" (file-name-unquote localname)))) (defun tramp-sudoedit-handle-file-name-all-completions (filename directory) "Like `file-name-all-completions' for Tramp files." diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 95b42fb1c43..baa9f966dd8 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -2976,8 +2976,9 @@ not in completion mode." ;; We need special handling only when a method is needed. Then we ;; regard all files "/method:" or "/[method/" as existent, if ;; "method" is a valid Tramp method. And we regard all files - ;; "/method:user@host" or "/[method/user@host" as existent, if - ;; "user@host" is a valid file name completion. + ;; "/method:user@", "/user@" or "/[method/user@" as existent, if + ;; "user@" is a valid file name completion. Host completion is + ;; performed in the respective backen operation. (or (and (cond ;; Completion styles like `flex' and `substring' check for ;; the file name "/". This does exist. @@ -2989,27 +2990,30 @@ not in completion mode." (regexp tramp-prefix-regexp) (* (regexp tramp-remote-file-name-spec-regexp) (regexp tramp-postfix-hop-regexp)) - (group (regexp tramp-method-regexp)) + (group-n 9 (regexp tramp-method-regexp)) (? (regexp tramp-postfix-method-regexp)) eos) filename)) - (assoc (match-string 1 filename) tramp-methods)) - ;; Is it a valid user@host? + (assoc (match-string 9 filename) tramp-methods)) + ;; Is it a valid user? ((string-match (rx (regexp tramp-prefix-regexp) (* (regexp tramp-remote-file-name-spec-regexp) (regexp tramp-postfix-hop-regexp)) - (group (regexp tramp-remote-file-name-spec-regexp)) + (group-n 10 + (regexp tramp-method-regexp) + (regexp tramp-postfix-method-regexp)) + (group-n 11 + (regexp tramp-user-regexp) + (regexp tramp-postfix-user-regexp)) eos) filename) - (member - (concat - (file-name-nondirectory filename) tramp-postfix-host-format) - (file-name-all-completions - (file-name-nondirectory filename) - (file-name-directory filename))))) - t) + (member + (match-string 11 filename) + (file-name-all-completions + "" (concat tramp-prefix-format (match-string 10 filename)))))) + t) (tramp-run-real-handler #'file-exists-p (list filename)))) @@ -3629,6 +3633,25 @@ BODY is the backend specific code." (tramp-dissect-file-name ,directory) 'file-missing ,directory) nil))) +(defmacro tramp-skeleton-file-exists-p (filename &rest body) + "Skeleton for `tramp-*-handle-file-exists-p'. +BODY is the backend specific code." + (declare (indent 1) (debug t)) + ;; `file-exists-p' is used as predicate in file name completion. + `(or (and minibuffer-completing-file-name + (file-name-absolute-p ,filename) + (tramp-string-empty-or-nil-p + (tramp-file-name-localname (tramp-dissect-file-name ,filename)))) + ;; We don't want to run it when `non-essential' is t, or there + ;; is no connection process yet. + (when (tramp-connectable-p ,filename) + (with-parsed-tramp-file-name (expand-file-name ,filename) nil + (with-tramp-file-property v localname "file-exists-p" + (if (tramp-file-property-p v localname "file-attributes") + (not + (null (tramp-get-file-property v localname "file-attributes"))) + ,@body)))))) + (defmacro tramp-skeleton-file-local-copy (filename &rest body) "Skeleton for `tramp-*-handle-file-local-copy'. BODY is the backend specific code." @@ -4066,13 +4089,8 @@ Let-bind it when necessary.") (defun tramp-handle-file-exists-p (filename) "Like `file-exists-p' for Tramp files." - ;; `file-exists-p' is used as predicate in file name completion. - ;; We don't want to run it when `non-essential' is t, or there is - ;; no connection process yet. - (when (tramp-connectable-p filename) - (with-parsed-tramp-file-name (expand-file-name filename) nil - (with-tramp-file-property v localname "file-exists-p" - (not (null (file-attributes filename))))))) + (tramp-skeleton-file-exists-p filename + (not (null (file-attributes filename))))) (defun tramp-handle-file-in-directory-p (filename directory) "Like `file-in-directory-p' for Tramp files." From 750bc57cbb8d081566e671e8fc3e27a82588c197 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Sat, 18 Feb 2023 12:56:24 -0500 Subject: [PATCH 3/3] Don't rely on dynamic scoping to fix bug#59213 Rather than look up a dynamically scoped var to decide whether to trim closures, use an ad-hoc marker on those closures which should not be trimmed. * lisp/emacs-lisp/cconv.el (cconv-dont-trim-unused-variables): Delete var. (cconv-make-interpreted-closure): Use a `:closure-dont-trim-context` markers instead. * lisp/emacs-lisp/edebug.el (edebug-make-enter-wrapper): Use `:closure-dont-trim-context` rather than `cconv-dont-trim-unused-variables`. * lisp/emacs-lisp/testcover.el (testcover-analyze-coverage): Remove workaround for `cconv-dont-trim-unused-variables`. * test/lisp/emacs-lisp/cconv-tests.el (cconv-safe-for-space): New test. --- lisp/emacs-lisp/cconv.el | 15 +++++++++------ lisp/emacs-lisp/edebug.el | 22 ++++++++++++---------- lisp/emacs-lisp/testcover.el | 5 ----- test/lisp/emacs-lisp/cconv-tests.el | 13 +++++++++++++ 4 files changed, 34 insertions(+), 21 deletions(-) diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index b8121aeba55..940a1045625 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el @@ -113,10 +113,6 @@ is less than this number.") (defvar cconv--dynbound-variables nil "List of variables known to be dynamically bound.") -(defvar cconv-dont-trim-unused-variables nil - "When bound to non-nil, don't remove unused variables from the environment. -This is intended for use by edebug and similar.") - ;;;###autoload (defun cconv-closure-convert (form &optional dynbound-vars) "Main entry point for closure conversion. @@ -882,15 +878,22 @@ lexically and dynamically bound symbols actually used by FORM." (cons fvs dyns))))) (defun cconv-make-interpreted-closure (fun env) + ;; FIXME: I don't know what "This function is evaluated both at + ;; compile time and run time" is intended to mean here. "Make a closure for the interpreter. This function is evaluated both at compile time and run time. FUN, the closure's function, must be a lambda form. ENV, the closure's environment, is a mixture of lexical bindings of the form -(SYMBOL . VALUE) and symbols which indicate dynamic bindings of those +\(SYMBOL . VALUE) and symbols which indicate dynamic bindings of those symbols." (cl-assert (eq (car-safe fun) 'lambda)) (let ((lexvars (delq nil (mapcar #'car-safe env)))) - (if (or cconv-dont-trim-unused-variables (null lexvars)) + (if (or (null lexvars) + ;; Functions with a `:closure-dont-trim-context' marker + ;; should keep their whole context untrimmed (bug#59213). + (and (eq :closure-dont-trim-context (nth 2 fun)) + ;; Check the function doesn't just return the magic keyword. + (nthcdr 3 fun))) ;; The lexical environment is empty, or needs to be preserved, ;; so there's no need to look for free variables. ;; Attempting to replace ,(cdr fun) by a macroexpanded version diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 735a358cdba..552526b6efc 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -1217,16 +1217,18 @@ purpose by adding an entry to this alist, and setting (setq edebug-old-def-name nil)) (setq edebug-def-name (or edebug-def-name edebug-old-def-name (gensym "edebug-anon"))) - `(let ((cconv-dont-trim-unused-variables t)) - (edebug-enter - (quote ,edebug-def-name) - ,(if edebug-inside-func - `(list - ;; Doesn't work with more than one def-body!! - ;; But the list will just be reversed. - ,@(nreverse edebug-def-args)) - 'nil) - (function (lambda () ,@forms))))) + `(edebug-enter + (quote ,edebug-def-name) + ,(if edebug-inside-func + `(list + ;; Doesn't work with more than one def-body!! + ;; But the list will just be reversed. + ,@(nreverse edebug-def-args)) + 'nil) + ;; Make sure `forms' is not nil so we don't accidentally return + ;; the magic keyword. Mark the closure so we don't throw away + ;; unused vars (bug#59213). + #'(lambda () :closure-dont-trim-context ,@(or forms '(nil))))) (defvar edebug-form-begin-marker) ; the mark for def being instrumented diff --git a/lisp/emacs-lisp/testcover.el b/lisp/emacs-lisp/testcover.el index 1212905f08a..ed31b90ca32 100644 --- a/lisp/emacs-lisp/testcover.el +++ b/lisp/emacs-lisp/testcover.el @@ -442,11 +442,6 @@ or return multiple values." (let ((testcover-vector (get sym 'edebug-coverage))) (testcover-analyze-coverage-progn body))) - (`(let ((cconv-dont-trim-unused-variables t)) - (edebug-enter ',sym ,_ (function (lambda nil . ,body)))) - (let ((testcover-vector (get sym 'edebug-coverage))) - (testcover-analyze-coverage-progn body))) - (`(edebug-after ,(and before-form (or `(edebug-before ,before-id) before-id)) ,after-id ,wrapped-form) diff --git a/test/lisp/emacs-lisp/cconv-tests.el b/test/lisp/emacs-lisp/cconv-tests.el index 83013cf46a9..349ffeb7e47 100644 --- a/test/lisp/emacs-lisp/cconv-tests.el +++ b/test/lisp/emacs-lisp/cconv-tests.el @@ -364,5 +364,18 @@ (call-interactively f)) '((t 51696) (nil 51695) (t 51697))))))) +(ert-deftest cconv-safe-for-space () + (let* ((magic-string "This-is-a-magic-string") + (safe-p (lambda (x) (not (string-match magic-string (format "%S" x)))))) + (should (funcall safe-p (lambda (x) (+ x 1)))) + (should (funcall safe-p (eval '(lambda (x) (+ x 1)) + `((y . ,magic-string))))) + (should (funcall safe-p (eval '(lambda (x) :closure-dont-trim-context) + `((y . ,magic-string))))) + (should-not (funcall safe-p + (eval '(lambda (x) :closure-dont-trim-context (+ x 1)) + `((y . ,magic-string))))))) + + (provide 'cconv-tests) ;;; cconv-tests.el ends here