diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index d79bcf3fe0f..b2fcb3c489f 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -3138,30 +3138,33 @@ elisp, The Emacs Lisp Reference Manual}. If the directory specified by @code{user-lisp-directory}, defaulting to @file{~/.config/emacs/user-lisp/} or @file{~/.emacs.d/user-lisp/}, exists, then at startup Emacs will prepare Lisp files within that -directory for use in the session. Emacs does the following things: +directory for use in the session. Specifically, Emacs does the +following: @itemize @item Gather and activate autoload cookies. This means that you can use autoloaded commands and other entry points for the files in your @code{user-lisp-directory} without explicitly loading any of the -files in your initialization file. (@pxref{Autoload,,, elisp, The -Emacs Lisp Reference Manual}.) +files in your initialization file. @xref{Autoload,,, elisp, The +Emacs Lisp Reference Manual}. @item -Byte-compile all files, and if supported on your system, natively -compile them too. This speeds up the execution of the code in the -files when they are loaded. (@pxref{Byte Compilation,,, elisp, The -Emacs Lisp Reference Manual}.) +Byte-compile all the files (@pxref{Byte Compilation,,, elisp, The Emacs +Lisp Reference Manual}), and if supported by your build of Emacs, +compile them to native code as well (@pxref{Native Compilation,,, elisp, +The Emacs Lisp Reference Manual}). This speeds up the execution of the +code in those files when they are loaded and when they are executed +later. @item Adjust @code{load-path} such that all the files can be loaded and -autoloaded in the usual ways. (@pxref{Library Search,,, elisp, The -Emacs Lisp Reference Manual}.) +autoloaded in the usual ways. @xref{Library Search,,, elisp, The +Emacs Lisp Reference Manual}. @end itemize - The User Lisp directory is processed before loading the @ref{Init -File} file. Therefore any customizations to the user options discussed -below must be made in your early init file (@pxref{Early Init File}) in -order to have any effect. + The User Lisp directory is processed before loading your init file +(@pxref{Init File}). Therefore any customizations to the user +options discussed below must be made in your early init file +(@pxref{Early Init File}) in order to have any effect. @vindex user-lisp-ignored-directories @vindex user-lisp-auto-scrape diff --git a/etc/NEWS b/etc/NEWS index 3a9d5ef6f8f..9e5ac796697 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2885,6 +2885,11 @@ This command is Diff mode's specialized 'narrow-to-region'. consistency, 'diff-restrict-view' is now too. To enable it again, use 'M-x enable-command'. +--- +*** 'C-x v !' has its own input history. +This is shared with the input history of 'C-x v P' for certain backends +which use the same mechanism as 'C-x v !'. + ** Package +++ diff --git a/lisp/align.el b/lisp/align.el index 1f1c8f58009..362d59f2231 100644 --- a/lisp/align.el +++ b/lisp/align.el @@ -1407,11 +1407,18 @@ aligner would have dealt with are." (align-region beg end 'entire exclude-rules nil + ;; Use markers for exclusion area bounds so + ;; they remain accurate after subsequent + ;; alignment sections modify the buffer. (lambda (b e mode) (or (and mode (listp mode)) + (let ((bm (copy-marker b)) + (em (copy-marker e t))) + (push bm markers) + (push em markers) (setq exclude-areas - (cons (cons b e) - exclude-areas))))) + (cons (cons bm em) + exclude-areas)))))) (setq exclude-areas (nreverse (sort exclude-areas #'car-less-than-car)))) @@ -1458,14 +1465,17 @@ aligner would have dealt with are." (setq same nil) (align--set-marker eol (line-end-position))) - ;; remember the beginning position of this rule - ;; match, and save the match-data, since either - ;; the `valid' form, or the code that searches for - ;; section separation, might alter it - (setq rule-beg (match-beginning first) - save-match-data (match-data)) + ;; Remember the beginning position of this rule + ;; match as a marker so it remains accurate after + ;; `align-regions' modifies the buffer for a + ;; previous alignment section. Also save the + ;; match-data, since either the `valid' form, or + ;; the code that searches for section separation, + ;; might alter it. + (align--set-marker rule-beg (match-beginning first) t) + (setq save-match-data (match-data)) - (or rule-beg + (or (marker-position rule-beg) (error "No match for subexpression %s" first)) ;; unless the `valid' attribute is set, and tells @@ -1480,6 +1490,18 @@ aligner would have dealt with are." (when (and last-point (align-new-section-p last-point rule-beg thissep)) + ;; Convert saved match-data positions to + ;; markers before `align-regions' modifies + ;; the buffer, so the restored match-data + ;; reflects the updated buffer state. + (setq save-match-data + (mapcar (lambda (pos) + (if (integerp pos) + (let ((m (copy-marker pos))) + (push m markers) + m) + pos)) + save-match-data)) (align-regions regions align-props rule func) (setq regions nil) (setq align-props nil)) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 28ee14c67cb..89fbdec131f 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2030,21 +2030,25 @@ according to `eglot-advertise-cancellation'.") (timeout-fn nil timeout-fn-supplied-p) (timeout nil timeout-supplied-p) hint - &aux moreargs - id (buf (current-buffer))) + &aux moreargs id + (buf (current-buffer)) + (inflight eglot--inflight-async-requests)) "Like `jsonrpc-async-request', but for Eglot LSP requests. SUCCESS-FN, ERROR-FN and TIMEOUT-FN run in buffer of call site. HINT argument is a symbol passed as DEFERRED to `jsonrpc-async-request' and also used as a hint of the request cancellation mechanism (see `eglot-advertise-cancellation')." (cl-labels - ((clearing-fn (fn) + ((wrapfn (fn) (lambda (&rest args) (eglot--when-live-buffer buf - (when (and - fn (memq id (cl-getf eglot--inflight-async-requests hint))) - (apply fn args)) - (cl-remf eglot--inflight-async-requests hint))))) + (cond (eglot-advertise-cancellation + (when-let* ((tail (and fn (plist-member inflight hint)))) + (when (memq id (cadr tail)) + (apply fn args)) + (setf (cadr tail) (delete id (cadr tail))))) + (t + (apply fn args))))))) (eglot--cancel-inflight-async-requests (list hint)) (when timeout-supplied-p (setq moreargs (nconc `(:timeout ,timeout) moreargs))) @@ -2053,13 +2057,12 @@ and also used as a hint of the request cancellation mechanism (see (setq id (car (apply #'jsonrpc-async-request server method params - :success-fn (clearing-fn success-fn) - :error-fn (clearing-fn error-fn) - :timeout-fn (clearing-fn timeout-fn) + :success-fn (wrapfn success-fn) + :error-fn (wrapfn error-fn) + :timeout-fn (wrapfn timeout-fn) moreargs))) (when (and hint eglot-advertise-cancellation) - (push id - (plist-get eglot--inflight-async-requests hint))) + (push id (plist-get inflight hint))) id)) (cl-defun eglot--delete-overlays (&optional (prop 'eglot--overlays)) diff --git a/lisp/subr.el b/lisp/subr.el index fcf03dd4f67..6f2dcb8c16d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -1148,8 +1148,8 @@ side-effects, and the argument LIST is not modified." (make-symbol "f"))) (r (make-symbol "r"))) `(let (,@(and f `((,f ,pred))) - (,tail ,list) - (,r nil)) + (,r nil) + (,tail ,list)) (while (and ,tail (funcall ,(or f pred) (car ,tail))) (push (car ,tail) ,r) (setq ,tail (cdr ,tail))) diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el index 2f0d949f108..559310ff770 100644 --- a/lisp/vc/diff-mode.el +++ b/lisp/vc/diff-mode.el @@ -201,8 +201,9 @@ The default \"-b\" means to ignore whitespace-only changes, (defvar-keymap diff-mode-shared-map :doc "Bindings for read-only `diff-mode' buffers. These bindings are also available with an ESC prefix -(i.e. a \\=`M-' prefix) in read-write `diff-mode' buffers, -and with a `diff-minor-mode-prefix' prefix in `diff-minor-mode'. +(i.e. a \\=`M-' prefix) in all `diff-mode' buffers, including in +particular read-write `diff-mode' buffers, and with a +`diff-minor-mode-prefix' prefix in `diff-minor-mode'. See also `diff-mode-read-only-map'." "n" #'diff-hunk-next "N" #'diff-file-next @@ -217,16 +218,7 @@ See also `diff-mode-read-only-map'." "RET" #'diff-goto-source "" #'diff-goto-source "o" #'diff-goto-source ; other-window - " " #'undo-ignore-read-only - "s" #'diff-split-hunk - - ;; The foregoing commands don't affect buffers beyond this one. - ;; The following command is the only one that has a single-character - ;; binding and which affects buffers beyond this one. - ;; However, the following command asks for confirmation by default, - ;; so that seems okay. --spwhitton - "u" #'diff-revert-and-kill-hunk - "@" #'diff-revert-and-kill-hunk) + " " #'undo-ignore-read-only) ;; Not `diff-read-only-mode-map' because there is no such mode ;; `diff-read-only-mode'; see comment above. @@ -235,15 +227,28 @@ See also `diff-mode-read-only-map'." :doc "Additional bindings for read-only `diff-mode' buffers. Most of the bindings for read-only `diff-mode' buffers are in `diff-mode-shared-map'. This map contains additional bindings for -read-only `diff-mode' buffers that are *not* available with an ESC -prefix (i.e. a \\=`M-' prefix) in read-write `diff-mode' buffers." +read-only `diff-mode' buffers that are *not* also available with an ESC +prefix (i.e. a \\=`M-' prefix) in read-write (nor read-only) `diff-mode' +buffers." ;; We don't want the following in read-write `diff-mode' buffers ;; because they hide useful `M-' global bindings when editing. "W" #'widen "w" #'diff-kill-ring-save "A" #'diff-ediff-patch "r" #'diff-restrict-view - "R" #'diff-reverse-direction) + "R" #'diff-reverse-direction + "s" #'diff-split-hunk + + ;; The foregoing commands in `diff-mode-shared-map' and + ;; `diff-mode-read-only-map' don't affect buffers beyond this one. + ;; The following command is the only one that has a single-character + ;; binding and which affects buffers beyond this one. However, the + ;; following command asks for confirmation by default, so that seems + ;; okay. --spwhitton + "u" #'diff-revert-and-kill-hunk + ;; `diff-revert-and-kill-hunk' is the `diff-mode' analogue of what '@' + ;; does in VC-Dir, so give it the same short binding. + "@" #'diff-revert-and-kill-hunk) (defvar-keymap diff-mode-map :doc "Keymap for `diff-mode'. See also `diff-mode-shared-map'." @@ -2327,10 +2332,10 @@ If REVERTP is non-nil, reverse-apply hunks before killing them." (setq beg (copy-marker beg) end (point-marker)) (unwind-protect (cl-loop initially (goto-char beg) + with inhibit-read-only = t for (hunk-beg hunk-end) = (diff-bounds-of-hunk) for file-bounds = (ignore-errors (diff-bounds-of-file)) for (file-beg file-end) = file-bounds - for inhibit-read-only = t if (and file-bounds (progn (goto-char file-beg) diff --git a/lisp/vc/vc-dispatcher.el b/lisp/vc/vc-dispatcher.el index dc17b582ed7..374ae778d55 100644 --- a/lisp/vc/vc-dispatcher.el +++ b/lisp/vc/vc-dispatcher.el @@ -384,6 +384,9 @@ the man pages for \"torsocks\" for more details about Tor." :version "27.1" :group 'vc) +(defvar vc-user-edit-command-history nil + "Minibuffer history for `vc-user-edit-command'.") + (defun vc-user-edit-command (command file-or-list flags) "Prompt the user to edit VC command COMMAND and FLAGS. Intended to be used as the value of `vc-filter-command-function'." @@ -398,7 +401,8 @@ Intended to be used as the value of `vc-filter-command-function'." (cons command (remq nil (if files-separator-p (butlast flags) flags)))) - " "))))) + " ") + 'vc-user-edit-command-history)))) (list (car edited) file-or-list (nconc (cdr edited) (and files-separator-p '("--")))))) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index d6a7145b34e..9c97fcad97d 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -1472,7 +1472,9 @@ line of the commit message in an entry with key \"Subject\"." (if (eq system-type 'windows-nt) locale-coding-system coding-system-for-write))) - (vc-git--call input-file t "mailinfo" msg-file patch-file)) + (vc-git--call input-file t "mailinfo" + (file-local-name msg-file) + (file-local-name patch-file))) (goto-char (point-min)) ;; git-mailinfo joins up any header continuation lines for us. (while (re-search-forward "^\\([^\t\n\s:]+\\):\\(.*\\)$" nil t) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 14da03cda1d..3d85453a3b3 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -3347,7 +3347,9 @@ Uncommitted changes are included in the diff. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3375,7 +3377,9 @@ Uncommitted changes are included in the diff. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3409,7 +3413,9 @@ working revision and UPSTREAM-LOCATION. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. @@ -3441,7 +3447,9 @@ working revision and UPSTREAM-LOCATION. When unspecified, UPSTREAM-LOCATION is the outgoing base. For a trunk branch this is always the place \\[vc-push] would push to. -For a topic branch, query the backend for an appropriate outgoing base. +For a topic branch, see whether the branch matches one of +`vc-trunk-branch-regexps' or `vc-topic-branch-regexps', or else query +the backend for an appropriate outgoing base. See `vc-trunk-branch-regexps' and `vc-topic-branch-regexps' regarding the difference between trunk and topic branches. diff --git a/lisp/window.el b/lisp/window.el index 3a1ebd16fa6..2327ffcd5f2 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -7586,7 +7586,7 @@ strategy." (defun window--frame-landscape-p (&optional frame) "Non-nil if FRAME is wider than it is tall. -This means actually wider on the screen, not character-wise. +This means actually wider on the screen, not wider character-wise. On text frames, use the heuristic that characters are roughtly twice as tall as they are wide." (if (display-graphic-p frame) diff --git a/test/lisp/align-tests.el b/test/lisp/align-tests.el index 92605a7f4aa..43660f8de87 100644 --- a/test/lisp/align-tests.el +++ b/test/lisp/align-tests.el @@ -36,6 +36,53 @@ (ert-test-erts-file (ert-resource-file "c-mode.erts") (test-align-transform-fun #'c-mode))) +(ert-deftest align-c-multi-section () + "Test alignment of multiple sections in C code. +Regression test for bug where positions become stale after earlier +sections are aligned, causing incorrect alignment in later sections." + (let ((input "int main(void) +{ + long signed int foo = 5; + int bar = 7; + { + int a1 = 4; + int b1 = 2; + long signed int junk1 = 2; + } + { + int a2 = 4; /* comment */ + int b2 = 2; + long signed int junk2 = 2; /* another comment */ + } + + return 0; +} +") + (expected "int main(void) +{ + long signed int foo = 5; + int bar = 7; + { + int a1 = 4; + int b1 = 2; + long signed int junk1 = 2; + } + { + int a2 = 4; /* comment */ + int b2 = 2; + long signed int junk2 = 2; /* another comment */ + } + + return 0; +} +")) + (with-temp-buffer + (c-mode) + (setq indent-tabs-mode nil) + (insert input) + (align (point-min) (point-max)) + (should (equal (buffer-string) expected))))) + (ert-deftest align-css () (let ((indent-tabs-mode nil)) (ert-test-erts-file (ert-resource-file "css-mode.erts") diff --git a/test/lisp/vc/ediff-mult-tests.el b/test/lisp/vc/ediff-mult-tests.el index 4d7f3f35859..7887ae086fe 100644 --- a/test/lisp/vc/ediff-mult-tests.el +++ b/test/lisp/vc/ediff-mult-tests.el @@ -20,38 +20,34 @@ ;;; Code: (require 'ert) +(require 'ert-x) (require 'ediff-mult) (ert-deftest ediff-test-bug3348 () "After saving `ediff-meta-diff-buffer' to a file, we should not reuse it." - (let ((test-dir - (expand-file-name "bug-3348-testdir" temporary-file-directory))) - (make-directory test-dir t) - (unwind-protect - (progn - (cd test-dir) + (ert-with-temp-directory test-dir + (cd test-dir) - (make-directory "dir-a" t) - (make-directory "dir-b" t) + (make-directory "dir-a" t) + (make-directory "dir-b" t) - (with-temp-file "dir-a/file" - (insert "aaa\n")) - (with-temp-file "dir-b/file" - (insert "bbb\n")) + (with-temp-file "dir-a/file" + (insert "aaa\n")) + (with-temp-file "dir-b/file" + (insert "bbb\n")) - (ediff-directories "dir-a" "dir-b" nil) - (switch-to-buffer "*Ediff Session Group Panel*") + (ediff-directories "dir-a" "dir-b" nil) + (switch-to-buffer "*Ediff Session Group Panel*") - (ediff-next-meta-item 1) - (ediff-mark-for-operation-at-pos nil) - (ediff-collect-custom-diffs) + (ediff-next-meta-item 1) + (ediff-mark-for-operation-at-pos nil) + (ediff-collect-custom-diffs) - (with-current-buffer "*Ediff Multifile Diffs*" - (write-file "foo.patch")) + (with-current-buffer "*Ediff Multifile Diffs*" + (write-file "foo.patch")) - (with-temp-file "dir-b/file" - (insert "BBB\n")) - (ediff-collect-custom-diffs) + (with-temp-file "dir-b/file" + (insert "BBB\n")) + (ediff-collect-custom-diffs) - (should-not (equal ediff-meta-diff-buffer (get-buffer "foo.patch")))) - (delete-directory test-dir t)))) + (should-not (equal ediff-meta-diff-buffer (get-buffer "foo.patch")))))