From 0c50af054f94313c458495524c90205fd4415bc8 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 27 Aug 2023 08:24:39 +0300 Subject: [PATCH 01/10] Fix applying patches with Git on MS-Windows * lisp/vc/vc.el (vc-diff-internal): For Git, always suppress EOL conversion when reading the diffs into a buffer. Doc fix. * lisp/vc/vc-git.el (vc-git-checkin): Make sure to suppress EOL conversion when the patch file is written. (Bug#65049) --- lisp/vc/vc-git.el | 10 +++++++++- lisp/vc/vc.el | 21 +++++++++++++++++---- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 7ae763d2ee4..218696c05f4 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1051,7 +1051,15 @@ It is based on `log-edit-mode', and has Git-specific extensions." (user-error "Index not empty")) (setq pos (point)))))) (unless (string-empty-p vc-git-patch-string) - (let ((patch-file (make-nearby-temp-file "git-patch"))) + (let ((patch-file (make-nearby-temp-file "git-patch")) + ;; Temporarily countermand the let-binding at the + ;; beginning of this function. + (coding-system-for-write + (coding-system-change-eol-conversion + ;; On DOS/Windows, it is important for the patch file + ;; to have the Unix EOL format, because Git expects + ;; that, even on Windows. + (or pcsw vc-git-commits-coding-system) 'unix))) (with-temp-file patch-file (insert vc-git-patch-string)) (unwind-protect diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 410fe5c01e1..db4fa76abd4 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1894,7 +1894,9 @@ in the output buffer." (vc-run-delayed (vc-diff-finish (current-buffer) nil)))) (defun vc-diff-internal (async vc-fileset rev1 rev2 &optional verbose buffer) - "Report diffs between two revisions of a fileset. + "Report diffs between revisions REV1 and REV2 of a fileset in VC-FILESET. +ASYNC non-nil means run the backend's commands asynchronously if possible. +VC-FILESET should have the format described in `vc-deduce-fileset'. Output goes to the buffer BUFFER, which defaults to *vc-diff*. BUFFER, if non-nil, should be a buffer or a buffer name. Return t if the buffer had changes, nil otherwise." @@ -1910,15 +1912,26 @@ Return t if the buffer had changes, nil otherwise." ;; but the only way to set it for each file included would ;; be to call the back end separately for each file. (coding-system-for-read - (if files (vc-coding-system-for-diff (car files)) 'undecided)) + ;; Force the EOL conversion to be -unix, in case the files + ;; to be compared have DOS EOLs. In that case, EOL + ;; conversion will produce a patch file that will either + ;; fail to apply, or will change the EOL format of some of + ;; the lines in the patched file. + (coding-system-change-eol-conversion + (if files (vc-coding-system-for-diff (car files)) 'undecided) + 'unix)) (orig-diff-buffer-clone (if revert-buffer-in-progress-p (clone-buffer (generate-new-buffer-name " *vc-diff-clone*") nil)))) ;; On MS-Windows and MS-DOS, Diff is likely to produce DOS-style ;; EOLs, which will look ugly if (car files) happens to have Unix - ;; EOLs. - (if (memq system-type '(windows-nt ms-dos)) + ;; EOLs. But for Git, we must force Unix EOLs in the diffs, since + ;; Git always produces Unix EOLs in the parts that didn't come + ;; from the file, and wants to see any CR characters when applying + ;; patches. + (if (and (memq system-type '(windows-nt ms-dos)) + (not (eq (car vc-fileset) 'Git))) (setq coding-system-for-read (coding-system-change-eol-conversion coding-system-for-read 'dos))) From 31d3808fb9df98b75d8b199885cc9875f26a9215 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sun, 27 Aug 2023 13:20:37 +0200 Subject: [PATCH 02/10] Adapt Eshell manual * doc/misc/eshell.texi (Arguments): Mention more special characters to be quoted in remote file names. (Bug#65431) --- doc/misc/eshell.texi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index c9d84cf2851..3c2b4bd3a7c 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -333,7 +333,8 @@ As with other shells, you can escape special characters and spaces by prefixing the character with a backslash (@samp{\}), or by surrounding the string with apostrophes (@samp{''}) or double quotes (@samp{""}). This is needed especially for file names with special characters like -pipe (@samp{|}), which could be part of remote file names. +pipe (@samp{|}) or square brackets (@samp{[} or @samp{]}), which could +be part of remote file names. When you escape a character with @samp{\} outside of any quotes, the result is the literal character immediately following it. For From 45cf3a0cede6662418bbab4897a2f04a9ef9c962 Mon Sep 17 00:00:00 2001 From: Jonas Bernoulli Date: Fri, 25 Aug 2023 22:22:47 +0200 Subject: [PATCH 03/10] Update to Transient v0.4.3 --- doc/misc/transient.texi | 66 ++++++------- lisp/transient.el | 205 ++++++++++++++++++++-------------------- 2 files changed, 128 insertions(+), 143 deletions(-) diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index be9e8698ab4..e6144dcf2bc 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -31,7 +31,7 @@ General Public License for more details. @finalout @titlepage @title Transient User and Developer Manual -@subtitle for version 0.4.1 +@subtitle for version 0.4.3 @author Jonas Bernoulli @page @vskip 0pt plus 1filll @@ -74,7 +74,7 @@ that hurdle is Psionic K's interactive tutorial, available at @end quotation @noindent -This manual is for Transient version 0.4.1. +This manual is for Transient version 0.4.3. @insertcopying @end ifnottex @@ -248,18 +248,18 @@ When using Transient, one can call a command with arguments that are just as complex as when calling the same function non-interactively from Lisp. -Invoking a transient command with arguments is similar to invoking a -command in a shell with command-line completion and history enabled. -One benefit of the Transient interface is that it remembers history -not only on a global level (“this command was invoked using these -arguments, and previously it was invoked using those other arguments”), -but also remembers the values of individual arguments independently. -@xref{Using History}. +Invoking a transient suffix command with arguments is similar to +invoking a command in a shell with command-line completion and history +enabled. One benefit of the Transient interface is that it remembers +history not only on a global level (“this command was invoked using +these arguments, and previously it was invoked using those other +arguments”), but also remembers the values of individual arguments +independently. See @xref{Using History}. After a transient prefix command is invoked, @kbd{C-h @var{KEY}} can be used to show the documentation for the infix or suffix command that @kbd{@var{KEY}} is -bound to (@pxref{Getting Help for Suffix Commands}), and infixes and -suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes +bound to (see @ref{Getting Help for Suffix Commands}), and infixes and +suffixes can be removed from the transient using @kbd{C-x l @var{KEY}}. Infixes and suffixes that are disabled by default can be enabled the same way. @xref{Enabling and Disabling Suffixes}. @@ -270,21 +270,26 @@ Additionally, Transient provides abstractions for defining new types, which the author of Transient did not anticipate (or didn't get around to implementing yet). +Note that suffix commands also support regular prefix arguments. A +suffix command may even be called with both infix and prefix arguments +at the same time. If you invoke a command as a suffix of a transient +prefix command, but also want to pass prefix arguments to it, then +first invoke the prefix command, and only after doing that invoke the +prefix arguments, before finally invoking the suffix command. If you +instead began by providing the prefix arguments, then those would +apply to the prefix command, not the suffix command. Likewise, if you +want to change infix arguments before invoking a suffix command with +prefix arguments, then change the infix arguments before invoking the +prefix arguments. In other words, regular prefix arguments always +apply to the next command, and since transient prefix, infix and +suffix commands are just regular commands, the same applies to them. +(Regular prefix keys behave differently because they are not commands +at all, instead they are just incomplete key sequences, and those +cannot be interrupted with prefix commands.) + @node Usage @chapter Usage -@menu -* Invoking Transients:: -* Aborting and Resuming Transients:: -* Common Suffix Commands:: -* Saving Values:: -* Using History:: -* Getting Help for Suffix Commands:: -* Enabling and Disabling Suffixes:: -* Other Commands:: -* Configuration:: -@end menu - @node Invoking Transients @section Invoking Transients @@ -997,14 +1002,6 @@ signal an error. @node Defining New Commands @chapter Defining New Commands -@menu -* Defining Transients:: -* Binding Suffix and Infix Commands:: -* Defining Suffix and Infix Commands:: -* Using Infix Arguments:: -* Transient State:: -@end menu - @node Defining Transients @section Defining Transients @@ -2234,11 +2231,6 @@ available depending on user preference. @node Related Abstractions and Packages @chapter Related Abstractions and Packages -@menu -* Comparison With Prefix Keys and Prefix Arguments:: -* Comparison With Other Packages:: -@end menu - @node Comparison With Prefix Keys and Prefix Arguments @section Comparison With Prefix Keys and Prefix Arguments @@ -2559,8 +2551,6 @@ currently exist. @node FAQ @appendix FAQ - - @anchor{Can I control how the popup buffer is displayed?} @appendixsec Can I control how the popup buffer is displayed? diff --git a/lisp/transient.el b/lisp/transient.el index 048554eee13..52c21871548 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -6,7 +6,7 @@ ;; URL: https://github.com/magit/transient ;; Keywords: extensions -;; Package-Version: 0.4.1 +;; Package-Version: 0.4.3 ;; Package-Requires: ((emacs "26.1")) ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -67,6 +67,7 @@ (defvar display-line-numbers) ; since Emacs 26.1 (defvar Man-notify-method) +(defvar pp-default-function) ; since Emacs 29.1 (defmacro transient--with-emergency-exit (&rest body) (declare (indent defun)) @@ -565,7 +566,9 @@ the previous prefix." (setq list (cl-sort (copy-sequence list) #'string< :key #'car)) (with-temp-file file (let ((print-level nil) - (print-length nil)) + (print-length nil) + (pp-default-function 'pp-28) + (fill-column 999)) (pp list (current-buffer))))) (defvar transient-values @@ -953,7 +956,7 @@ keyword. (pcase-let ((`(,class ,slots ,_ ,docstr ,_) (transient--expand-define-args args arglist))) `(progn - (defalias ',name ,(transient--default-infix-command)) + (defalias ',name #'transient--default-infix-command) (put ',name 'interactive-only t) (put ',name 'command-modes (list 'not-a-mode)) (put ',name 'function-documentation ,docstr) @@ -969,6 +972,15 @@ example, sets a variable, use `transient-define-infix' instead. \(fn NAME ARGLIST [DOCSTRING] [KEYWORD VALUE]...)") +(defun transient--default-infix-command () + "Most transient infix commands are but an alias for this command." + (interactive) + (let ((obj (transient-suffix-object))) + (transient-infix-set obj (transient-infix-read obj))) + (transient--show)) +(put 'transient--default-infix-command 'interactive-only t) +(put 'transient--default-infix-command 'command-modes (list 'not-a-mode)) + (defun transient--expand-define-args (args &optional arglist) (unless (listp arglist) (error "Mandatory ARGLIST is missing")) @@ -1071,11 +1083,16 @@ example, sets a variable, use `transient-define-infix' instead. (if (and desc (or (stringp desc) (symbolp desc))) desc (plist-get args :key))))))) - (setq args (plist-put args :command - `(defalias ',sym ,(macroexp-quote cmd)))))) + (setq args (plist-put + args :command + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'command-modes (list 'not-a-mode)) + (defalias ',sym ,(macroexp-quote cmd))))))) ((or (stringp car) (and car (listp car))) - (let ((arg pop)) + (let ((arg pop) + (sym nil)) (cl-typecase arg (list (setq args (plist-put args :shortarg (car arg))) @@ -1085,9 +1102,13 @@ example, sets a variable, use `transient-define-infix' instead. (when-let ((shortarg (transient--derive-shortarg arg))) (setq args (plist-put args :shortarg shortarg))) (setq args (plist-put args :argument arg)))) - (setq args (plist-put args :command - (list 'quote (intern (format "transient:%s:%s" - prefix arg))))) + (setq sym (intern (format "transient:%s:%s" prefix arg))) + (setq args (plist-put + args :command + `(prog1 ',sym + (put ',sym 'interactive-only t) + (put ',sym 'command-modes (list 'not-a-mode)) + (defalias ',sym #'transient--default-infix-command)))) (cond ((and car (not (keywordp car))) (setq class 'transient-option) (setq args (plist-put args :reader (macroexp-quote pop)))) @@ -1116,26 +1137,6 @@ example, sets a variable, use `transient-define-infix' instead. (macroexp-quote (or class 'transient-suffix)) (cons 'list args)))) -(defun transient--default-infix-command () - (cons 'lambda - '(() - (interactive) - (let ((obj (transient-suffix-object))) - (transient-infix-set obj (transient-infix-read obj))) - (transient--show)))) - -(defun transient--ensure-infix-command (obj) - (let ((cmd (oref obj command))) - (unless (or (commandp cmd) - (get cmd 'transient--infix-command)) - (if (or (cl-typep obj 'transient-switch) - (cl-typep obj 'transient-option)) - (put cmd 'transient--infix-command - (transient--default-infix-command)) - ;; This is not an anonymous infix argument. - (when (transient--use-suffix-p obj) - (error "Suffix %s is not defined or autoloaded as a command" cmd)))))) - (defun transient--derive-shortarg (arg) (save-match-data (and (string-match "\\`\\(-[a-zA-Z]\\)\\(\\'\\|=\\)" arg) @@ -1420,11 +1421,11 @@ Each suffix commands is associated with an object, which holds additional information about the suffix, such as its value (in the case of an infix command, which is a kind of suffix command). -This function is intended to be called by infix commands, whose -command definition usually (at least when defined using -`transient-define-infix') is this: +This function is intended to be called by infix commands, which +are usually aliases of `transient--default-infix-command', which +is defined like this: - (lambda () + (defun transient--default-infix-command () (interactive) (let ((obj (transient-suffix-object))) (transient-infix-set obj (transient-infix-read obj))) @@ -1441,7 +1442,7 @@ commands) may also need the object to guide their behavior. This function attempts to return the object associated with the current suffix command even if the suffix command was not invoked from a transient. (For some suffix command that is a valid thing -to do, for others it is not.) In that case nil may be returned +to do, for others it is not.) In that case nil may be returned, if the command was not defined using one of the macros intended to define such commands. @@ -1457,7 +1458,7 @@ probably use this instead: (let ((suffixes (cl-remove-if-not (lambda (obj) - (eq (transient--suffix-command obj) + (eq (oref obj command) (or command (if (eq this-command 'transient-set-level) ;; This is how it can look up for which @@ -1480,38 +1481,6 @@ probably use this instead: (transient-init-value obj) obj))) -(defun transient--suffix-command (object) - "Return the command represented by OBJECT. - -If the value of OBJECT's `command' slot is a command, then return -that. Otherwise it is a symbol whose `transient--infix-command' -property holds an anonymous command, which is returned instead." - (cl-check-type object transient-suffix) - (let ((sym (oref object command))) - (if (commandp sym) - sym - (get sym 'transient--infix-command)))) - -(defun transient--suffix-symbol (arg) - "Return a symbol representing ARG. - -ARG must be a command and/or a symbol. If it is a symbol, -then just return it. Otherwise return the symbol whose -`transient--infix-command' property's value is ARG." - (or (cl-typep arg 'command) - (cl-typep arg 'symbol) - (signal 'wrong-type-argument `((command symbol) ,arg))) - (if (symbolp arg) - arg - (let* ((obj (transient-suffix-object)) - (sym (oref obj command))) - (if (eq (get sym 'transient--infix-command) arg) - sym - (catch 'found - (mapatoms (lambda (sym) - (when (eq (get sym 'transient--infix-command) arg) - (throw 'found sym))))))))) - ;;; Keymaps (defvar-keymap transient-base-map @@ -1709,7 +1678,7 @@ of the corresponding object." (funcall transient-substitute-key-function obj))) (oset obj key key)) (let ((kbd (kbd key)) - (cmd (transient--suffix-command obj))) + (cmd (oref obj command))) (when-let ((conflict (and transient-detect-key-conflicts (transient--lookup-key map kbd)))) (unless (eq cmd conflict) @@ -1737,13 +1706,12 @@ of the corresponding object." (keymap-set map "" #'transient--do-suspend)) (dolist (obj transient--suffixes) (let* ((cmd (oref obj command)) - (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t)) - (sym (transient--suffix-symbol cmd))) + (sub-prefix (and (symbolp cmd) (get cmd 'transient--prefix) t))) (cond ((oref obj inapt) - (define-key map (vector sym) #'transient--do-warn-inapt)) + (define-key map (vector cmd) #'transient--do-warn-inapt)) ((slot-boundp obj 'transient) - (define-key map (vector sym) + (define-key map (vector cmd) (let ((do (oref obj transient))) (pcase (list do sub-prefix) ('(t t) #'transient--do-recurse) @@ -1753,8 +1721,8 @@ of the corresponding object." ('(nil t) #'transient--do-replace) ('(nil nil) #'transient--do-exit) (_ do))))) - ((not (lookup-key transient-predicate-map (vector sym))) - (define-key map (vector sym) + ((not (lookup-key transient-predicate-map (vector cmd))) + (define-key map (vector cmd) (if sub-prefix #'transient--do-replace (or (oref transient--prefix transient-suffix) @@ -1904,21 +1872,28 @@ value. Otherwise return CHILDREN as is." (defun transient--init-suffix (levels spec) (pcase-let* ((`(,level ,class ,args) spec) (cmd (plist-get args :command)) - (level (or (alist-get (transient--suffix-symbol cmd) levels) - level))) + (level (or (alist-get cmd levels) level))) (let ((fn (and (symbolp cmd) (symbol-function cmd)))) (when (autoloadp fn) (transient--debug " autoload %s" cmd) (autoload-do-load fn))) (when (transient--use-level-p level) - (let ((obj (if-let ((proto (and cmd - (symbolp cmd) - (get cmd 'transient--suffix)))) + (unless (and cmd (symbolp cmd)) + (error "BUG: Non-symbolic suffix command: %s" cmd)) + (let ((obj (if-let ((proto (get cmd 'transient--suffix))) (apply #'clone proto :level level args) - (apply class :level level args)))) + (apply class :command cmd :level level args)))) + (cond ((commandp cmd)) + ((or (cl-typep obj 'transient-switch) + (cl-typep obj 'transient-option)) + ;; As a temporary special case, if the package was compiled + ;; with an older version of Transient, then we must define + ;; "anonymous" switch and option commands here. + (defalias cmd #'transient--default-infix-command)) + ((transient--use-suffix-p obj) + (error "Suffix command %s is not defined or autoloaded" cmd))) (transient--init-suffix-key obj) - (transient--ensure-infix-command obj) (when (transient--use-suffix-p obj) (if (transient--inapt-suffix-p obj) (oset obj inapt t) @@ -2074,8 +2049,7 @@ value. Otherwise return CHILDREN as is." (defun transient--get-predicate-for (cmd &optional suffix-only) (or (ignore-errors - (lookup-key transient--predicate-map - (vector (transient--suffix-symbol cmd)))) + (lookup-key transient--predicate-map (vector cmd))) (and (not suffix-only) (let ((pred (oref transient--prefix transient-non-suffix))) (pcase pred @@ -2189,6 +2163,37 @@ value. Otherwise return CHILDREN as is." ,@body))) (defun transient--wrap-command () + (if (>= emacs-major-version 30) + (transient--wrap-command-30) + (transient--wrap-command-29))) + +(defun transient--wrap-command-30 () + (letrec + ((prefix transient--prefix) + (suffix this-command) + (advice (lambda (fn &rest args) + (interactive + (lambda (spec) + (let ((abort t)) + (unwind-protect + (prog1 (advice-eval-interactive-spec spec) + (setq abort nil)) + (when abort + (when-let ((unwind (oref prefix unwind-suffix))) + (transient--debug 'unwind-interactive) + (funcall unwind suffix)) + (advice-remove suffix advice) + (oset prefix unwind-suffix nil)))))) + (unwind-protect + (apply fn args) + (when-let ((unwind (oref prefix unwind-suffix))) + (transient--debug 'unwind-command) + (funcall unwind suffix)) + (advice-remove suffix advice) + (oset prefix unwind-suffix nil))))) + (advice-add suffix :around advice '((depth . -99))))) + +(defun transient--wrap-command-29 () (let* ((prefix transient--prefix) (suffix this-command) (advice nil) @@ -2202,9 +2207,7 @@ value. Otherwise return CHILDREN as is." (when-let ((unwind (oref prefix unwind-suffix))) (transient--debug 'unwind-interactive) (funcall unwind suffix)) - (if (symbolp suffix) - (advice-remove suffix advice) - (remove-function suffix advice)) + (advice-remove suffix advice) (oset prefix unwind-suffix nil)))))) (advice-body (lambda (fn &rest args) @@ -2213,16 +2216,12 @@ value. Otherwise return CHILDREN as is." (when-let ((unwind (oref prefix unwind-suffix))) (transient--debug 'unwind-command) (funcall unwind suffix)) - (if (symbolp suffix) - (advice-remove suffix advice) - (remove-function suffix advice)) + (advice-remove suffix advice) (oset prefix unwind-suffix nil))))) (setq advice `(lambda (fn &rest args) (interactive ,advice-interactive) (apply ',advice-body fn args))) - (if (symbolp suffix) - (advice-add suffix :around advice '((depth . -99))) - (add-function :around (var suffix) advice '((depth . -99)))))) + (advice-add suffix :around advice '((depth . -99))))) (defun transient--premature-post-command () (and (equal (this-command-keys-vector) []) @@ -2343,7 +2342,7 @@ value. Otherwise return CHILDREN as is." (if (symbolp arg) (message "-- %-22s (cmd: %s, event: %S, exit: %s%s)" arg - (or (ignore-errors (transient--suffix-symbol this-command)) + (or (and (symbolp this-command) this-command) (if (byte-code-function-p this-command) "#[...]" this-command)) @@ -2526,12 +2525,9 @@ prefix argument and pivot to `transient-update'." (propertize "?" 'face 'transient-key) ;; `this-command' is `transient-undefined' or `transient-inapt'. ;; Show the command (`this-original-command') the user actually - ;; tried to invoke. For an anonymous inapt command that is a - ;; lambda expression, which cannot be mapped to a symbol, so - ;; forgo displaying the command. - (if-let ((cmd (ignore-errors - (symbol-name (transient--suffix-symbol - this-original-command))))) + ;; tried to invoke. + (if-let ((cmd (or (ignore-errors (symbol-name this-original-command)) + (ignore-errors (symbol-name this-command))))) (format " [%s]" (propertize cmd 'face 'font-lock-warning-face)) "")) (unless (and transient--transient-map @@ -2621,8 +2617,7 @@ transient is active." (transient-suffix-object command))) (transient--show) (transient--read-number-N - (format "Set level for `%s': " - (transient--suffix-symbol command)) + (format "Set level for `%s': " command) nil nil (not (eq command prefix))))))))))) (cond ((not command) @@ -2631,7 +2626,7 @@ transient is active." (level (let* ((prefix (oref transient--prefix command)) (alist (alist-get prefix transient-levels)) - (sym (transient--suffix-symbol command))) + (sym command)) (if (eq command prefix) (progn (oset transient--prefix level level) (setq sym t)) @@ -3463,7 +3458,7 @@ Optional support for popup buttons is also implemented here." (if transient-enable-popup-navigation (make-text-button str nil 'type 'transient - 'command (transient--suffix-command obj)) + 'command (oref obj command)) str))) (cl-defmethod transient-format ((obj transient-infix)) @@ -3663,7 +3658,7 @@ that, else its name. Intended to be temporarily used as the `:suffix-description' of a prefix command, while porting a regular keymap to a transient." - (let ((command (transient--suffix-symbol (oref obj command)))) + (let ((command (oref obj command))) (if-let ((doc (documentation command))) (propertize (car (split-string doc "\n")) 'face 'font-lock-doc-face) (propertize (symbol-name command) 'face 'font-lock-function-name-face)))) @@ -3691,7 +3686,7 @@ prefix method." (cond ((eq this-command 'transient-help) (transient-show-help transient--prefix)) - ((let ((prefix (get (transient--suffix-command obj) + ((let ((prefix (get (oref obj command) 'transient--prefix))) (and prefix (not (eq (oref transient--prefix command) this-command)) (prog1 t (transient-show-help prefix))))) From e7ac50a153901a2ae05eee797959874a3297faa4 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Sun, 27 Aug 2023 16:07:30 +0200 Subject: [PATCH 04/10] * lisp/emacs-lisp/comp.el (comp--native-compile): Fix OUTPUT for non abs paths --- lisp/emacs-lisp/comp.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 0c70789be71..b5355acf7cc 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -4096,7 +4096,8 @@ the deferred compilation mechanism." (symbols-with-pos-enabled t) ;; Have byte compiler signal an error when compilation fails. (byte-compile-debug t) - (comp-ctxt (make-comp-ctxt :output output + (comp-ctxt (make-comp-ctxt :output (when output + (expand-file-name output)) :with-late-load with-late-load))) (comp-log "\n \n" 1) (unwind-protect From 91d2d8439bb3a3e5ff739396af44bd0314b6f3c3 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Sun, 27 Aug 2023 16:51:16 +0200 Subject: [PATCH 05/10] * Handle missing eln file when trying to disassble (bug#65455) * lisp/emacs-lisp/disass.el (disassemble-internal): Handle missing eln file. --- lisp/emacs-lisp/disass.el | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el index 9dd08d00920..859a494a697 100644 --- a/lisp/emacs-lisp/disass.el +++ b/lisp/emacs-lisp/disass.el @@ -89,8 +89,10 @@ redefine OBJECT if it is a symbol." (subr-native-elisp-p obj)) (progn (require 'comp) - (call-process "objdump" nil (current-buffer) t "-S" - (native-comp-unit-file (subr-native-comp-unit obj))) + (let ((eln (native-comp-unit-file (subr-native-comp-unit obj)))) + (if (file-exists-p eln) + (call-process "objdump" nil (current-buffer) t "-S" eln) + (error "Missing eln file for #" name))) (goto-char (point-min)) (re-search-forward (concat "^.*" (regexp-quote From ea5fd6c96bcf62e999ed2b8491b7a80e9e52ec33 Mon Sep 17 00:00:00 2001 From: Andrea Corallo Date: Sun, 27 Aug 2023 18:59:40 +0200 Subject: [PATCH 06/10] * Fix native disassemble on Windows platforms (bug#65455) * lisp/emacs-lisp/disass.el (disassemble-internal): Improve regexp. --- lisp/emacs-lisp/disass.el | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/lisp/emacs-lisp/disass.el b/lisp/emacs-lisp/disass.el index 859a494a697..f9f7448d81c 100644 --- a/lisp/emacs-lisp/disass.el +++ b/lisp/emacs-lisp/disass.el @@ -94,14 +94,11 @@ redefine OBJECT if it is a symbol." (call-process "objdump" nil (current-buffer) t "-S" eln) (error "Missing eln file for #" name))) (goto-char (point-min)) - (re-search-forward (concat "^.*" + (re-search-forward (concat "^.*<_?" (regexp-quote - (concat "<" - (when (eq system-type 'darwin) - "_") - (comp-c-func-name - (subr-name obj) "F" t) - ">:")))) + (comp-c-func-name + (subr-name obj) "F" t)) + ">:")) (beginning-of-line) (delete-region (point-min) (point)) (when (re-search-forward "^.*<.*>:" nil t 2) From 34f7a47c9ce0581a89b30cc06243788b354f2e7a Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sun, 27 Aug 2023 20:06:13 +0200 Subject: [PATCH 07/10] Fix Tramp on MS Windows * lisp/net/tramp-sh.el (tramp-sh-handle-expand-file-name): Apply `tramp-drop-volume-letter' consequently. --- lisp/net/tramp-sh.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index ffd910b41c4..5a1e73aab2b 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2825,7 +2825,8 @@ the result will be a local, non-Tramp, file name." (with-parsed-tramp-file-name name nil ;; If connection is not established yet, run the real handler. (if (not (tramp-connectable-p v)) - (tramp-run-real-handler #'expand-file-name (list name)) + (tramp-drop-volume-letter + (tramp-run-real-handler #'expand-file-name (list name))) (unless (tramp-run-real-handler #'file-name-absolute-p (list localname)) (setq localname (concat "~/" localname))) ;; Tilde expansion if necessary. This needs a shell which From bc0426ce8ed7d58eb228ee1c78679db43d4a9cb0 Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Sun, 27 Aug 2023 12:49:25 -0700 Subject: [PATCH 08/10] Don't add an extraneous slash in remote PATH list in Eshell Previously, in a remote directory, '(eshell-get-path)' would return a list of strings like "/ssh:localhost://usr/bin". While that shouldn't break most things, it's not strictly correct either. See bug#65551. * lisp/eshell/esh-util.el (eshell-get-path): Use 'concat' instead of 'file-name-concat'. * test/lisp/eshell/esh-util-tests.el: Require 'tramp' and 'eshell-tests-helpers'. (esh-util-test/path/get, eshell-util-test/path/get-remote): New tests. --- lisp/eshell/esh-util.el | 2 +- test/lisp/eshell/esh-util-tests.el | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el index d003148dc96..6fe260cbb46 100644 --- a/lisp/eshell/esh-util.el +++ b/lisp/eshell/esh-util.el @@ -283,7 +283,7 @@ as the $PATH was actually specified." (eshell-under-windows-p)) (push "." path)) (if (and remote (not literal-p)) - (mapcar (lambda (x) (file-name-concat remote x)) path) + (mapcar (lambda (x) (concat remote x)) path) path)))) (defun eshell-set-path (path) diff --git a/test/lisp/eshell/esh-util-tests.el b/test/lisp/eshell/esh-util-tests.el index afaf1b77f2b..9546a4a62fd 100644 --- a/test/lisp/eshell/esh-util-tests.el +++ b/test/lisp/eshell/esh-util-tests.el @@ -19,9 +19,15 @@ ;;; Code: +(require 'tramp) (require 'ert) (require 'esh-util) +(require 'eshell-tests-helpers + (expand-file-name "eshell-tests-helpers" + (file-name-directory (or load-file-name + default-directory)))) + ;;; Tests: (ert-deftest esh-util-test/eshell-stringify/string () @@ -54,4 +60,28 @@ "Test that `eshell-stringify' correctly stringifies complex objects." (should (equal (eshell-stringify (list 'quote 'hello)) "'hello"))) +(ert-deftest esh-util-test/path/get () + "Test that getting the Eshell path returns the expected results." + (let ((expected-path (butlast (exec-path)))) + (should (equal (eshell-get-path) + (if (eshell-under-windows-p) + (cons "." expected-path) + expected-path))) + (should (equal (eshell-get-path 'literal) + expected-path)))) + +(ert-deftest esh-util-test/path/get-remote () + "Test that getting the remote Eshell path returns the expected results." + (let* ((default-directory ert-remote-temporary-file-directory) + (expected-path (butlast (exec-path)))) + ;; Make sure we don't have a doubled directory separator. + (should (seq-every-p (lambda (i) (not (string-match-p "//" i))) + (eshell-get-path))) + (should (equal (eshell-get-path) + (mapcar (lambda (i) + (concat (file-remote-p default-directory) i)) + expected-path))) + (should (equal (eshell-get-path 'literal) + expected-path)))) + ;;; esh-util-tests.el ends here From 458442fe78c4223cc87d44d862f1912a1bd66e37 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Sun, 27 Aug 2023 14:49:56 -0700 Subject: [PATCH 09/10] Escape percent character in treesit--inspect-name (bug#65540) * lisp/treesit.el (treesit-inspect-node-at-point): Escape percent. --- lisp/treesit.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/treesit.el b/lisp/treesit.el index 04d460fdea4..41ebc62fca6 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2459,7 +2459,8 @@ in `treesit-parser-list'." 'bold nil)) name (if (treesit-node-check node 'named) ")" "\"")))) - (setq treesit--inspect-name name) + ;; Escape the percent character for mode-line. (Bug#65540) + (setq treesit--inspect-name (string-replace "%" "%%" name)) (force-mode-line-update) (when arg (if node-list From 648a5e33e80417855b908693e36cba56cd2c796c Mon Sep 17 00:00:00 2001 From: Kyle Meyer Date: Sun, 27 Aug 2023 22:38:34 -0400 Subject: [PATCH 10/10] Update to Org 9.6.8-3-g21171d --- etc/refcards/orgcard.tex | 2 +- lisp/org/oc-basic.el | 2 +- lisp/org/org-element.el | 18 +++--------------- lisp/org/org-version.el | 4 ++-- lisp/org/org.el | 25 ++++++++++++++++--------- 5 files changed, 23 insertions(+), 28 deletions(-) diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index dd8cae5ce5e..23a2f73dba7 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,5 +1,5 @@ % Reference Card for Org Mode -\def\orgversionnumber{9.6.7} +\def\orgversionnumber{9.6.8} \def\versionyear{2023} % latest update \input emacsver.tex diff --git a/lisp/org/oc-basic.el b/lisp/org/oc-basic.el index 1c8c37aa941..5c9aad8f6a5 100644 --- a/lisp/org/oc-basic.el +++ b/lisp/org/oc-basic.el @@ -162,7 +162,7 @@ Return a hash table with citation references as keys and fields alist as values. (puthash (cdr (assq 'id item)) (mapcar (pcase-lambda (`(,field . ,value)) (pcase field - ((or 'author 'editors) + ((or 'author 'editor) ;; Author and editors are arrays of ;; objects, each of them designing a ;; person. These objects may contain diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index 296468eed1a..0debd1a6818 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -6705,20 +6705,8 @@ The function returns the new value of `org-element--cache-change-warning'." (setq org-element--cache-change-tic (buffer-chars-modified-tick)) (setq org-element--cache-last-buffer-size (buffer-size)) (goto-char beg) - (beginning-of-line) - (let ((bottom (save-excursion - (goto-char end) - (if (and (bolp) - ;; When beg == end, still extent to eol. - (> (point) beg)) - ;; FIXME: Potential pitfall. - ;; We are appending to an element end. - ;; Unless the last inserted char is not - ;; newline, the next element is not broken - ;; and does not need to be purged from the - ;; cache. - end - (line-end-position))))) + (forward-line 0) + (let ((bottom (save-excursion (goto-char end) (line-end-position)))) (prog1 ;; Use the worst change warning to not miss important edits. ;; This function is called before edit and after edit by @@ -7859,7 +7847,7 @@ element ending there." (setq cached-only nil)) (let (element) (when (org-element--cache-active-p) - (if (not org-element--cache) (org-element-cache-reset) + (if (not (org-with-base-buffer nil org-element--cache)) (org-element-cache-reset) (unless cached-only (org-element--cache-sync (current-buffer) pom)))) (setq element (if cached-only (when (and (org-element--cache-active-p) diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 57e406b24fc..3b58ea06818 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -5,13 +5,13 @@ (defun org-release () "The release version of Org. Inserted by installing Org mode or when a release is made." - (let ((org-release "9.6.7")) + (let ((org-release "9.6.8")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.6.7-13-g99cc96")) + (let ((org-git-version "release_9.6.8-3-g21171d")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index c5c0808104f..750c8f97201 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -9,7 +9,7 @@ ;; URL: https://orgmode.org ;; Package-Requires: ((emacs "26.1")) -;; Version: 9.6.7 +;; Version: 9.6.8 ;; This file is part of GNU Emacs. ;; @@ -6323,7 +6323,10 @@ unconditionally." (if (not level) (outline-next-heading) ;before first headline (org-back-to-heading invisible-ok) (when (equal arg '(16)) (org-up-heading-safe)) - (org-end-of-subtree))) + (org-end-of-subtree invisible-ok 'to-heading))) + ;; At `point-max', if the file does not have ending newline, + ;; create one, so that we are not appending stars at non-empty + ;; line. (unless (bolp) (insert "\n")) (when (and blank? (save-excursion (backward-char) @@ -6335,7 +6338,9 @@ unconditionally." (backward-char)) (unless (and blank? (org-previous-line-empty-p)) (org-N-empty-lines-before-current (if blank? 1 0))) - (insert stars " ") + (insert stars " " "\n") + ;; Move point after stars. + (backward-char) ;; When INVISIBLE-OK is non-nil, ensure newly created headline ;; is visible. (unless invisible-ok @@ -14754,12 +14759,12 @@ is considered `day' (i.e. only `bracket', `day', and `after' return values are possible). When matching, the match groups are the following: - group 1: year, if any - group 2: month, if any - group 3: day number, if any - group 4: day name, if any - group 5: hours, if any - group 6: minutes, if any" + group 2: year, if any + group 3: month, if any + group 4: day number, if any + group 5: day name, if any + group 7: hours, if any + group 8: minutes, if any" (let* ((regexp (if extended (if (eq extended 'agenda) @@ -17663,6 +17668,8 @@ If INDENT is non-nil, call `newline-and-indent' with ARG to indent unconditionally; otherwise, call `newline' with ARG and INTERACTIVE, which can trigger indentation if `electric-indent-mode' is enabled." + (when interactive + (org-fold-check-before-invisible-edit 'insert)) (if indent (org-newline-and-indent arg) (newline arg interactive)))