commit c82495dea767334c4b4423cf0358c76ca1edc4b4 (HEAD, refs/remotes/origin/master) Author: Daniel Colascione Date: Fri Mar 7 22:18:22 2025 -0800 Let repeated windmove override motion restrictions interactively * lisp/windmove.el (windmove-allow-all-windows): document feature (windmove-allow-repeated-command-override): new option (windmove-do-window-select, windmove-left, windmove-up, windmove-right) (windmove-down): pass interactive * etc/NEWS: mention feature diff --git a/etc/NEWS b/etc/NEWS index 4c433fbded0..c384b226ad4 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -205,6 +205,12 @@ Several functions to modify the window layout have been added: 'flip-window-layout-vertically', 'flip-window-layout-horizontally', 'transpose-window-layout', 'rotate-windows', and 'rotate-windows-back'. ++++ +*** New user option 'windmove-allow-repeated-command-override'. +This option controls whether pressing the same windmove command twice +overrides the no-other-window property, allowing navigation to windows +that would normally be skipped. + +++ *** New hook 'window-deletable-functions'. This abnormal hook gives its client a way to save a window from getting diff --git a/lisp/windmove.el b/lisp/windmove.el index ebadbbbf4cb..88895d43d79 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -170,10 +170,19 @@ placement bugs in old versions of Emacs." "Whether the windmove commands are allowed to target all type of windows. If this variable is set to non-nil, all windmove commands will ignore the `no-other-window' parameter applied by `display-buffer-alist' -or `set-window-parameter'." +or `set-window-parameter'. + +Another way to move into windows with the no-other-window property is +by invoking the same movement command twice in succession when +`windmove-allow-repeated-command-override' is true." :type 'boolean :version "28.1") +(defcustom windmove-allow-repeated-command-override t + "Control whether pressing the same windmove command twice overrides the no-other-window property." + :type 'boolean + :version "31.1") + ;; Note: ;; @@ -359,21 +368,47 @@ use the left or top edge of WINDOW as reference point." ;; Selects the window that's hopefully at the location returned by ;; `windmove-find-other-window', or screams if there's no window there. -(defun windmove-do-window-select (dir &optional arg window) +(defun windmove-do-window-select (dir &optional arg window calling-command) "Move to the window at direction DIR as seen from WINDOW. DIR, ARG, and WINDOW are handled as by `windmove-find-other-window'. If no window is at direction DIR, an error is signaled. If `windmove-create-window' is a function, call that function with DIR, ARG and WINDOW. If it is non-nil, try to create a new window -in direction DIR instead." - (let ((other-window (windmove-find-other-window dir arg window))) +in direction DIR instead. + +When the same windmove command is invoked twice in succession, +the second invocation will override the `no-other-window' property. +CALLING-COMMAND is the command that called this function, used to detect +repeated commands." + (let* ((repeated-command + (and calling-command (eq last-command calling-command))) + (other-window (windmove-find-other-window dir arg window))) + + (when (and (null other-window) + repeated-command windmove-allow-repeated-command-override) + (setf other-window (window-in-direction dir window t arg windmove-wrap-around t))) + + ;; Create window if needed (when (and windmove-create-window (or (null other-window) (and (window-minibuffer-p other-window) (not (minibuffer-window-active-p other-window))))) - (setq other-window (if (functionp windmove-create-window) - (funcall windmove-create-window dir arg window) - (split-window window nil dir)))) + (setf other-window + (if (functionp windmove-create-window) + (funcall windmove-create-window dir arg window) + (split-window window nil dir)))) + + ;; If we still don't have a window but could with allow-all-windows, + ;; fail with a helpful message. + (when (and (null other-window) + calling-command + (not windmove-allow-all-windows) + (not repeated-command) + windmove-allow-repeated-command-override) + (let ((test-window (window-in-direction dir window t arg windmove-wrap-around t))) + (when test-window + (user-error "No window %s (repeat to override)" dir)))) + (cond ((null other-window) (user-error "No window %s from selected window" dir)) ((and (window-minibuffer-p other-window) @@ -389,7 +424,7 @@ in direction DIR instead." ;; `windmove-do-window-select', meant to be bound to keys. ;;;###autoload -(defun windmove-left (&optional arg) +(defun windmove-left (&optional arg is-interactive) "Select the window to the left of the current one. With no prefix argument, or with prefix argument equal to zero, \"left\" is relative to the position of point in the window; otherwise @@ -397,35 +432,50 @@ it is relative to the top edge (for positive ARG) or the bottom edge \(for negative ARG) of the current window. If no window is at the desired location, an error is signaled unless `windmove-create-window' is non-nil and a new window is created." - (interactive "P") - (windmove-do-window-select 'left (and arg (prefix-numeric-value arg)))) + (interactive "P\np") + (windmove-do-window-select + 'left (and arg (prefix-numeric-value arg)) nil + (and is-interactive this-command))) ;;;###autoload -(defun windmove-up (&optional arg) +(defun windmove-up (&optional arg is-interactive) "Select the window above the current one. With no prefix argument, or with prefix argument equal to zero, \"up\" is relative to the position of point in the window; otherwise it is relative to the left edge (for positive ARG) or the right edge (for negative ARG) of the current window. If no window is at the desired location, an error is signaled -unless `windmove-create-window' is non-nil and a new window is created." - (interactive "P") - (windmove-do-window-select 'up (and arg (prefix-numeric-value arg)))) +unless `windmove-create-window' is non-nil and a new window is created. + +When this command is used twice in quick succession (within +`windmove-double-command-timeout' seconds), the second invocation +will override the `no-other-window' property of windows, allowing +you to move to windows that would normally be skipped." + (interactive "P\np") + (windmove-do-window-select + 'up (and arg (prefix-numeric-value arg)) nil + (and is-interactive this-command))) ;;;###autoload -(defun windmove-right (&optional arg) +(defun windmove-right (&optional arg is-interactive) "Select the window to the right of the current one. With no prefix argument, or with prefix argument equal to zero, \"right\" is relative to the position of point in the window; otherwise it is relative to the top edge (for positive ARG) or the bottom edge (for negative ARG) of the current window. If no window is at the desired location, an error is signaled -unless `windmove-create-window' is non-nil and a new window is created." - (interactive "P") - (windmove-do-window-select 'right (and arg (prefix-numeric-value arg)))) +unless `windmove-create-window' is non-nil and a new window is created. + +If `windmove-double-command-timeout' is set and a window exists in the +requested direction that is marked with the no-other-window property, you +can press this command twice in quick succession to override that property." + (interactive "P\np") + (windmove-do-window-select + 'right (and arg (prefix-numeric-value arg)) nil + (and is-interactive this-command))) ;;;###autoload -(defun windmove-down (&optional arg) +(defun windmove-down (&optional arg is-interactive) "Select the window below the current one. With no prefix argument, or with prefix argument equal to zero, \"down\" is relative to the position of point in the window; otherwise @@ -433,8 +483,10 @@ it is relative to the left edge (for positive ARG) or the right edge \(for negative ARG) of the current window. If no window is at the desired location, an error is signaled unless `windmove-create-window' is non-nil and a new window is created." - (interactive "P") - (windmove-do-window-select 'down (and arg (prefix-numeric-value arg)))) + (interactive "P\np") + (windmove-do-window-select + 'down (and arg (prefix-numeric-value arg)) nil + (and is-interactive this-command))) ;;; set up keybindings commit 0972a54a5ac52f731c0ea7c8538c8f3b7b6b36b4 Author: Daniel Colascione Date: Fri Mar 7 21:47:56 2025 -0800 Add static-when, static-unless like static-if * lisp/subr.el (static-when, static-unless): define * doc/lispref/control.texi (Conditional Compilation): document * etc/NEWS: mention diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi index a7b2b35f58a..4d00d27bd46 100644 --- a/doc/lispref/control.texi +++ b/doc/lispref/control.texi @@ -2841,6 +2841,19 @@ Test @var{condition} at macro-expansion time. If its value is non-@code{nil}, expand the macro to @var{then-form}, otherwise expand it to @var{else-forms} enclosed in a @code{progn}. @var{else-forms} may be empty. +@end defmac + +@defmac static-when condition body... +Test @var{condition} at macro-expansion time. If its value is +non-@code{nil}, expand the macro to evaluate all @var{body} forms +sequentially and return the value of the last one, or @code{nil} if there +are none. +@end defmac + +@defmac static-unless condition body... +Test @var{condition} at macro-expansion time. If its value is @code{nil}, +expand the macro to evaluate all @var{body} forms sequentially and return +the value of the last one, or @code{nil} if there are none. Here is an example of its use from CC Mode, which prevents a @code{defadvice} form being compiled in newer versions of Emacs: diff --git a/etc/NEWS b/etc/NEWS index 258f0dcc4ba..4c433fbded0 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1507,6 +1507,12 @@ Previously, its argument was always evaluated using dynamic binding. * Lisp Changes in Emacs 31.1 ++++ +** New macros 'static-when' and 'static-unless' implement conditional +compilation like 'static-if'. +These macros evaluate their condition at macro-expansion time and are useful +for writing code that can work across different Emacs versions. + --- ** You can change the default value of 'lexical-binding'. While the default is still the use dynamic binding dialect of ELisp diff --git a/lisp/subr.el b/lisp/subr.el index 8f0366824d9..110bebed789 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -301,6 +301,19 @@ value of last one, or nil if there are none." (macroexp-warn-and-return (format-message "`when' with empty body") (list 'progn cond nil) '(empty-body when) t))) +(defmacro static-when (condition &rest body) + "A conditional compilation macro. +Evaluate CONDITION at macro-expansion time. If it is non-nil, +expand the macro to evaluate all BODY forms sequentially and return +the value of the last one, or nil if there are none." + (declare (indent 1) (debug t)) + (if body + (if (eval condition lexical-binding) + (cons 'progn body) + nil) + (macroexp-warn-and-return (format-message "`static-when' with empty body") + (list 'progn nil nil) '(empty-body static-when) t))) + (defmacro unless (cond &rest body) "If COND yields nil, do BODY, else return nil. When COND yields nil, eval BODY forms sequentially and return @@ -311,6 +324,19 @@ value of last one, or nil if there are none." (macroexp-warn-and-return (format-message "`unless' with empty body") (list 'progn cond nil) '(empty-body unless) t))) +(defmacro static-unless (condition &rest body) + "A conditional compilation macro. +Evaluate CONDITION at macro-expansion time. If it is nil, +expand the macro to evaluate all BODY forms sequentially and return +the value of the last one, or nil if there are none." + (declare (indent 1) (debug t)) + (if body + (if (eval condition lexical-binding) + nil + (cons 'progn body)) + (macroexp-warn-and-return (format-message "`static-unless' with empty body") + (list 'progn nil nil) '(empty-body static-unless) t))) + (defsubst subr-primitive-p (object) "Return t if OBJECT is a built-in primitive written in C. Such objects can be functions or special forms." commit 1c313f8dce0ac9e0520f885420cd696703736baf Author: João Távora Date: Sat Mar 8 05:36:48 2025 +0000 Eglot: the margin code action indicator is interactive * doc/misc/eglot.texi (Customization Variables): Fix. diff --git a/doc/misc/eglot.texi b/doc/misc/eglot.texi index 333e369e440..fac90562f6b 100644 --- a/doc/misc/eglot.texi +++ b/doc/misc/eglot.texi @@ -958,8 +958,7 @@ point. Value is a list of symbols, more than one can be specified: @code{eldoc-hint}: ElDoc is used to hint about at-point actions. @item @code{margin}: A special indicator appears in the margin of the line -that point is currently on. This indicator is not interactive (you -cannot click on it with the mouse). +that point is currently on. @item @code{nearby}: An interactive special indicator appears near point. @item commit 02f9b525fc2188a57ff36ec38a60fa0032e2e547 Author: João Távora Date: Sat Mar 8 05:20:30 2025 +0000 Revert "Eglot: tests must work on 26.3" This reverts commit 331492a148588991af5ce9a24a2020b3d380e03f. My bad: gensym wasn't the problem, it's available from 26.1. Incf was the problem, in the main program file. * test/lisp/progmodes/eglot-tests.el (eglot--with-timeout): Back to gensym diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 07e96fad588..2b6e09a4d16 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -165,7 +165,7 @@ directory hierarchy." `(eglot--call-with-timeout ,timeout (lambda () ,@body))) (defun eglot--call-with-timeout (timeout fn) - (let* ((tag (cl-gensym "eglot-test-timeout")) + (let* ((tag (gensym "eglot-test-timeout")) (timed-out (make-symbol "timeout")) (timeout-and-message (if (listp timeout) timeout commit d81cdf9fd23910d38f13a65ccb4909af2c2bdfd9 Author: João Távora Date: Sat Mar 8 05:15:57 2025 +0000 Eglot: unbreak from Emacs 26.3 (two-arg setq-local) * lisp/progmodes/eglot.el (eglot--hierarchy-1): Use two-arg setq-local diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 2446cc6e3ed..bc70db34fb5 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -4601,20 +4601,19 @@ If NOERROR, return predicate, else erroring function." (eglot--error "No hierarchy information here")) (with-current-buffer (get-buffer-create name) (eglot-hierarchy-mode) - (setq-local - eglot--hierarchy-roots roots - eglot--hierarchy-specs specs - eglot--cached-server server - eglot--hierarchy-source-major-mode mode - buffer-read-only t - revert-buffer-function - (lambda (&rest _ignore) - ;; flush cache, would defeat purpose of a revert - (mapc (lambda (r) - (eglot--dbind ((HierarchyItem) name) r - (set-text-properties 0 1 nil name))) - eglot--hierarchy-roots) - (eglot--hierarchy-2))) + (setq-local eglot--hierarchy-roots roots) + (setq-local eglot--hierarchy-specs specs) + (setq-local eglot--cached-server server) + (setq-local eglot--hierarchy-source-major-mode mode) + (setq-local buffer-read-only t) + (setq-local revert-buffer-function + (lambda (&rest _ignore) + ;; flush cache, would defeat purpose of a revert + (mapc (lambda (r) + (eglot--dbind ((HierarchyItem) name) r + (set-text-properties 0 1 nil name))) + eglot--hierarchy-roots) + (eglot--hierarchy-2))) (eglot--hierarchy-2)))) (defun eglot--hierarchy-2 () commit 331492a148588991af5ce9a24a2020b3d380e03f Author: João Távora Date: Sat Mar 8 04:42:21 2025 +0000 Eglot: tests must work on 26.3 ;; IMPORTANT: Since Eglot is a :core ELPA package, these tests are ;; supposed to run on Emacsen down to 26.3. Do not use bleeding-edge ;; functionality not compatible with that Emacs version. * test/lisp/progmodes/eglot-tests.el (eglot--call-with-timeout): Back to cl-gensym. diff --git a/test/lisp/progmodes/eglot-tests.el b/test/lisp/progmodes/eglot-tests.el index 2b6e09a4d16..07e96fad588 100644 --- a/test/lisp/progmodes/eglot-tests.el +++ b/test/lisp/progmodes/eglot-tests.el @@ -165,7 +165,7 @@ directory hierarchy." `(eglot--call-with-timeout ,timeout (lambda () ,@body))) (defun eglot--call-with-timeout (timeout fn) - (let* ((tag (gensym "eglot-test-timeout")) + (let* ((tag (cl-gensym "eglot-test-timeout")) (timed-out (make-symbol "timeout")) (timeout-and-message (if (listp timeout) timeout commit 1efcd32cda6450f1db435c33ce73bb28c9dcf2ac Author: Stefan Kangas Date: Sat Mar 8 02:41:32 2025 +0100 Expand word list in admin/notes/jargon * admin/notes/jargon: Add some more acronyms, remove some rare ones, add section headers "Acronyms" and "Glossary", add entries under "Glossary", sort, fix formatting, realign. diff --git a/admin/notes/jargon b/admin/notes/jargon index 93ac3506fc6..aa214b289e0 100644 --- a/admin/notes/jargon +++ b/admin/notes/jargon @@ -1,38 +1,75 @@ Glossary of Abbreviations, Acronyms, and Jargon This document provides a list of common abbreviations, acronyms, and -jargon used in emacs-devel@gnu.org. This is a non-exhaustive list. +jargon used on emacs-devel@gnu.org. This is a non-exhaustive list. Feel free to expand as needed. ---- - -AKA - Also known as -ASAP - As soon as possible -AFAICT - As far as I can tell -BTW - By the way -DTRT - Do the right thing -FYI - For your information -FWIW - For what it's worth -HTH - Hope this helps -ICYMI - In case you missed it -IIRC - If I recall correctly -IIUC - If I understand correctly -IMO - In my opinion -IMHO - In my humble opinion -IMNSHO - In my not so humble opinion -IOW - In other words -LMK - Let me know -LGTM - Looks good to me -NBD - No big deal -NP - No problem -OTOH - On the other hand -PFA - Please find attached -POV - Point of view -TBH - To be honest -TL;DR - Too long; didn't read -TRT - The right thing -TIA - Thanks in advance -WIP - Work in progress -WFM - Works for me -WRT - With respect to -YMMV - Your mileage may vary +See also (info "(emacs) Glossary"). + + +## Glossary + +bikeshedding – excessive discussion over minor details rather than + focusing on the main issue +bitrot – gradual deterioration of software due to changes in + its environment or dependencies +cockpit error - user error +code smell – an indication that a section of code may have + underlying issues or could be improved +foo, bar, baz – generic placeholder names used in examples and + documentation +gross – an inelegant, messy, or overly complicated solution + that works but is suboptimal; describes necessary + workarounds or code that should ideally be improved +hysterical raisins - historical reasons +install on - push to Git branch in repository +notabug - an issue reported as a bug but deemed to be + expected behavior +paper cut – a minor but annoying issue that should be easy to fix +pilot error - user error +yak shaving – engaging in a series of seemingly unrelated tasks + to accomplish an initial goal +wontfix – an issue reported as a bug but that won't be fixed, + often due to design decisions or low priority + + +## Abbreviations + +AFAICT - as far as I can tell +AFAIK - as far as I know +AFAIR - as far as I remember +AFAIU - as far as I understand +AKA - also known as +ASAP - as soon as possible +BTW - by the way +CL - Common Lisp +DTRT - do the right thing +DWIM - do what I mean +ENOPATCH - no patch is attached +FTR - for the record +FWIW - for what it's worth +FYI - for your information +GNU - GNU is not Unix +HTH - hope this helps +IANAL - I am not a lawyer +ICYMI - in case you missed it +IIRC - if I recall correctly +IIUC - if I understand correctly +IMHO - in my humble opinion +IMNSHO - in my not so humble opinion +IMO - in my opinion +IOW - in other words +LGTM - looks good to me +LMK - let me know +OOTB - out of the box +OTOH - on the other hand +SNAFU - situation normal, all fouled up +TBD - to be determined +TBH - to be honest +TIA - thanks in advance +TL;DR - too long; didn't read +TRT - the right thing +WFM - works for me +WIP - work in progress +WRT - with respect to +YMMV - your mileage may vary commit ce43d6732ba967edc85c88647f50b7df0e580624 Author: Stefan Kangas Date: Sat Mar 8 02:26:29 2025 +0100 Support :maintainers in plural in -pkg.el For some reason, MELPA emits the keyword :maintainers, despite it being unsupported and thus leads to the "Maintainer" field being empty in all released Emacs versions. That said, it seems like a good idea to support the plural form, to be consistent with :authors. * lisp/emacs-lisp/package.el (describe-package-1): Support :maintainers in plural, in addition to :maintainer, to be consistent with :authors. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 805727ff562..b9a8dacab15 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2824,7 +2824,8 @@ Helper function for `describe-package'." (status (if desc (package-desc-status desc) "orphan")) (incompatible-reason (package--incompatible-p desc)) (signed (if desc (package-desc-signed desc))) - (maintainers (cdr (assoc :maintainer extras))) + (maintainers (or (cdr (assoc :maintainer extras)) + (cdr (assoc :maintainers extras)))) (authors (cdr (assoc :authors extras))) (news (and-let* (pkg-dir ((not built-in)) commit 062c6ab3dd5a1ce85fb7cb0fc84b65aa2cf60369 Author: Daniel Colascione Date: Fri Mar 7 16:22:56 2025 -0800 Stop term-erase-in-line disturbing markers * lisp/term.el (term-erase-in-line): do nothing if there's nothing to do; insert new newlines before deleting old ones. diff --git a/lisp/term.el b/lisp/term.el index 25f90045925..8d57f949615 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -4050,19 +4050,24 @@ all pending output has been dealt with.")) (wrapped (and (zerop (term-horizontal-column)) (not (zerop (term-current-column)))))) (term-vertical-motion 1) - (delete-region saved-point (point)) - ;; wrapped is true if we're at the beginning of screen line, - ;; but not a buffer line. If we delete the current screen line - ;; that will make the previous line no longer wrap, and (because - ;; of the way Emacs display works) point will be at the end of - ;; the previous screen line rather then the beginning of the - ;; current one. To avoid that, we make sure that current line - ;; contain a space, to force the previous line to continue to wrap. - ;; We could do this always, but it seems preferable to not add the - ;; extra space when wrapped is false. - (when wrapped - (insert ? )) - (insert ?\n) + ;; Do nothing if we have nothing to delete + (unless (and (eq saved-point (1- (point))) + (eq (char-before) ?\n) + (not wrapped)) + ;; Insert before deletion to preserve markers. + ;; wrapped is true if we're at the beginning of screen line, + ;; but not a buffer line. If we delete the current screen line + ;; that will make the previous line no longer wrap, and (because + ;; of the way Emacs display works) point will be at the end of + ;; the previous screen line rather then the beginning of the + ;; current one. To avoid that, we make sure that current line + ;; contain a space, to force the previous line to continue to wrap. + ;; We could do this always, but it seems preferable to not add the + ;; extra space when wrapped is false. + (when wrapped + (insert-before-markers ? )) + (insert-before-markers ?\n) + (delete-region saved-point (point))) (put-text-property saved-point (point) 'font-lock-face 'default) (goto-char saved-point)))) commit a48659e57c8f89c3182274c9faac87ff17e0ab64 Author: dimagid Date: Sun Mar 2 10:30:59 2025 -0400 Add admin/notes/jargon used in emacs-devel * admin/notes/jargon: New file. Ref: https://lists.gnu.org/r/emacs-devel/2025-02/msg00950.html diff --git a/admin/notes/jargon b/admin/notes/jargon new file mode 100644 index 00000000000..93ac3506fc6 --- /dev/null +++ b/admin/notes/jargon @@ -0,0 +1,38 @@ +Glossary of Abbreviations, Acronyms, and Jargon + +This document provides a list of common abbreviations, acronyms, and +jargon used in emacs-devel@gnu.org. This is a non-exhaustive list. +Feel free to expand as needed. + +--- + +AKA - Also known as +ASAP - As soon as possible +AFAICT - As far as I can tell +BTW - By the way +DTRT - Do the right thing +FYI - For your information +FWIW - For what it's worth +HTH - Hope this helps +ICYMI - In case you missed it +IIRC - If I recall correctly +IIUC - If I understand correctly +IMO - In my opinion +IMHO - In my humble opinion +IMNSHO - In my not so humble opinion +IOW - In other words +LMK - Let me know +LGTM - Looks good to me +NBD - No big deal +NP - No problem +OTOH - On the other hand +PFA - Please find attached +POV - Point of view +TBH - To be honest +TL;DR - Too long; didn't read +TRT - The right thing +TIA - Thanks in advance +WIP - Work in progress +WFM - Works for me +WRT - With respect to +YMMV - Your mileage may vary commit ebb94d712e21a3985fd90ea7011f14b420ff590b Author: Stefan Kangas Date: Fri Mar 7 22:09:47 2025 +0100 ; Add Maintainer header to checkdoc.el * lisp/emacs-lisp/checkdoc.el: Add Maintainer header. diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index c3b43b6a97b..a45c7dd04cc 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -3,7 +3,7 @@ ;; Copyright (C) 1997-2025 Free Software Foundation, Inc. ;; Author: Eric M. Ludlam -;; Old-Version: 0.6.2 +;; Maintainer: emacs-devel@gnu.org ;; Keywords: docs, maint, lisp ;; This file is part of GNU Emacs. commit 9277b037938b79e13a26c30ec0d2be30cfafd32b Author: Gerd Möllmann Date: Fri Mar 7 09:35:20 2025 +0100 Fix tty underline capability check (bug#75024) * src/dispextern.h (TTY_CAP_UNDERLINE_STYLED): Fix. Also make this an enum. diff --git a/src/dispextern.h b/src/dispextern.h index 1b383164752..bd48005b83f 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3482,13 +3482,16 @@ enum tool_bar_item_image capabilities being queried for when calling `tty_capable_p' (which returns true if the terminal supports all of them). */ -#define TTY_CAP_INVERSE 0x01 -#define TTY_CAP_UNDERLINE 0x02 -#define TTY_CAP_BOLD 0x04 -#define TTY_CAP_DIM 0x08 -#define TTY_CAP_ITALIC 0x10 -#define TTY_CAP_STRIKE_THROUGH 0x20 -#define TTY_CAP_UNDERLINE_STYLED (0x32 & TTY_CAP_UNDERLINE) +enum +{ + TTY_CAP_INVERSE = 1 << 1, + TTY_CAP_UNDERLINE = 1 << 2, + TTY_CAP_BOLD = 1 << 3, + TTY_CAP_DIM = 1 << 4, + TTY_CAP_ITALIC = 1 << 5, + TTY_CAP_STRIKE_THROUGH = 1 << 6, + TTY_CAP_UNDERLINE_STYLED = 1 << 7 +}; /*********************************************************************** commit ae4671a7abb279aa9f3a9600028bdc85aff27c93 Author: Daniel Colascione Date: Fri Mar 7 12:17:54 2025 -0800 Revert "Stop moving markers during erase-in-line" This reverts commit 6f19715937bbeaec5fb80ee9dad0d14b7712a989. diff --git a/lisp/term.el b/lisp/term.el index 1cdfcffa0bf..25f90045925 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -4062,10 +4062,7 @@ all pending output has been dealt with.")) ;; extra space when wrapped is false. (when wrapped (insert ? )) - ;; If there's a marker at the start of the next line, we shouldn't - ;; disturb it: erase-in-line doesn't change logical - ;; line structure. - (insert-before-markers ?\n) + (insert ?\n) (put-text-property saved-point (point) 'font-lock-face 'default) (goto-char saved-point)))) commit 6f19715937bbeaec5fb80ee9dad0d14b7712a989 Author: Daniel Colascione Date: Fri Mar 7 11:10:09 2025 -0800 Stop moving markers during erase-in-line We shouldn't move a line marker just because we cleared a line next to it. clear-in-line is defined not to affect line structure. * lisp/term.el (term-erase-in-line): use insert-before-markers diff --git a/lisp/term.el b/lisp/term.el index 25f90045925..1cdfcffa0bf 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -4062,7 +4062,10 @@ all pending output has been dealt with.")) ;; extra space when wrapped is false. (when wrapped (insert ? )) - (insert ?\n) + ;; If there's a marker at the start of the next line, we shouldn't + ;; disturb it: erase-in-line doesn't change logical + ;; line structure. + (insert-before-markers ?\n) (put-text-property saved-point (point) 'font-lock-face 'default) (goto-char saved-point)))) commit 4ea07cc4b4a676a5f8094d565cd3cea89e6ec77d Author: Daniel Colascione Date: Fri Mar 7 11:07:12 2025 -0800 Make erase-in-line conform to ANSI spec in term When handling \e[K escape sequences, we're supposed to erase both to the left _and_ to the right of the cursor when N is two. * lisp/term.el (term-erase-in-line): make condition check more correct diff --git a/lisp/term.el b/lisp/term.el index a74216f00c5..25f90045925 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -4040,7 +4040,7 @@ all pending output has been dealt with.")) '(term-line-wrap t rear-nonsticky t))))) (defun term-erase-in-line (kind) - (when (= kind 1) ;; erase left of point + (when (>= kind 1) ;; erase left of point (let ((cols (term-horizontal-column)) (saved-point (point))) (term-vertical-motion 0) (delete-region (point) saved-point) commit af828499c6a280e3efe017898aab15fba3fae0aa Author: Stefan Kangas Date: Fri Mar 7 17:42:11 2025 +0100 Add type check to package-upgrade * lisp/emacs-lisp/package.el (package-upgrade): Add type check. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 8d498c216dc..805727ff562 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2265,6 +2265,7 @@ NAME should be a symbol." (list (intern (completing-read "Upgrade package: " (package--upgradeable-packages t) nil t)))) + (cl-check-type name symbol) (let* ((pkg-desc (cadr (assq name package-alist))) (package-install-upgrade-built-in (not pkg-desc))) ;; `pkg-desc' will be nil when the package is an "active built-in". commit e62e7aa8990fd6c0b3a8742c8283efd20a2b10b7 Author: Basil L. Contovounesios Date: Thu Feb 20 10:34:00 2025 +0100 Clean up ert-font-lock error messages * lisp/emacs-lisp/ert-font-lock.el: Remove redundant requires. (ert-font-lock--parse-macro-args): First return value 'doc' being nil already indicates omission of a docstring, so remove redundant second return value doc-p. All users updated. Fix error messages (bug#76372). (ert-font-lock--check-faces): Simplify with ensure-list. diff --git a/lisp/emacs-lisp/ert-font-lock.el b/lisp/emacs-lisp/ert-font-lock.el index 80f4a6d5467..0f8e90d747c 100644 --- a/lisp/emacs-lisp/ert-font-lock.el +++ b/lisp/emacs-lisp/ert-font-lock.el @@ -37,8 +37,6 @@ (require 'ert) (require 'ert-x) -(require 'newcomment) -(require 'pcase) (defconst ert-font-lock--face-symbol-re (rx (+ (or alphanumeric "-" "_" "." "/"))) @@ -100,25 +98,24 @@ Argument TEST-NAME - name of the currently running ert test." (defun ert-font-lock--parse-macro-args (doc-keys-mode-arg) "Parse DOC-KEYS-MODE-ARG macro argument list." - (let (doc doc-p mode arg) + (let (doc mode arg) (when (stringp (car doc-keys-mode-arg)) - (setq doc (pop doc-keys-mode-arg) - doc-p t)) + (setq doc (pop doc-keys-mode-arg))) (pcase-let ((`(,keys ,mode-arg) (ert--parse-keys-and-body doc-keys-mode-arg))) (unless (symbolp (car mode-arg)) - (error "A major mode symbol expected: %S" (car mode-arg))) + (error "Expected a major mode symbol: %S" (car mode-arg))) (setq mode (pop mode-arg)) (unless (stringp (car mode-arg)) - (error "A string or file with assertions expected: %S" (car mode-arg))) + (error "Expected a string or file with assertions: %S" (car mode-arg))) (setq arg (pop mode-arg)) - (list doc doc-p keys mode arg)))) + (list doc keys mode arg)))) ;;;###autoload (defmacro ert-font-lock-deftest (name &rest docstring-keys-mode-and-str) @@ -139,22 +136,20 @@ used through `ert'. stringp)) (doc-string 2) (indent 1)) - (pcase-let ((`(,documentation - ,documentation-supplied-p - ,keys ,mode ,arg) + (pcase-let ((`(,documentation ,keys ,mode ,arg) (ert-font-lock--parse-macro-args docstring-keys-mode-and-str))) `(ert-set-test ',name (make-ert-test :name ',name - ,@(when documentation-supplied-p + ,@(when documentation `(:documentation ,documentation)) ,@(when (map-contains-key keys :expected-result) `(:expected-result-type ,(map-elt keys :expected-result))) ,@(when (map-contains-key keys :tags) `(:tags ,(map-elt keys :tags))) - :body (lambda () (ert-font-lock--test-body-str ',mode ,arg ',name)) - + :body (lambda () + (ert-font-lock--test-body-str ',mode ,arg ',name)) :file-name ,(or (macroexp-file-name) buffer-file-name))))) ;;;###autoload @@ -178,23 +173,20 @@ through `ert'. stringp)) (doc-string 2) (indent 1)) - - (pcase-let ((`(,documentation - ,documentation-supplied-p - ,keys ,mode ,arg) + (pcase-let ((`(,documentation ,keys ,mode ,arg) (ert-font-lock--parse-macro-args docstring-keys-mode-and-file))) `(ert-set-test ',name (make-ert-test :name ',name - ,@(when documentation-supplied-p + ,@(when documentation `(:documentation ,documentation)) ,@(when (map-contains-key keys :expected-result) `(:expected-result-type ,(map-elt keys :expected-result))) ,@(when (map-contains-key keys :tags) `(:tags ,(map-elt keys :tags))) :body (lambda () (ert-font-lock--test-body-file - ',mode (ert-resource-file ,arg) ',name)) + ',mode (ert-resource-file ,arg) ',name)) :file-name ,(or (macroexp-file-name) buffer-file-name))))) (defun ert-font-lock--in-comment-p () @@ -357,10 +349,8 @@ The function is meant to be run from within an ERT test." ;; normalize both expected and resulting face - these can be ;; either symbols, nils or lists of symbols - (when (not (listp actual-face)) - (setq actual-face (list actual-face))) - (when (not (listp expected-face)) - (setq expected-face (list expected-face))) + (setq actual-face (ensure-list actual-face)) + (setq expected-face (ensure-list expected-face)) ;; fail when lists are not 'equal and the assertion is *not negated* (when (and (not negation) (not (equal actual-face expected-face))) commit e35435daf392462440bbc51a5b82d93eea7757c6 Author: Tomas Nordin Date: Sun Feb 9 22:39:58 2025 +0100 view-search: Start search from beginning or end of line * lisp/view.el (view-search): Go to beginning-of-line or end-of-line instead of previous or next line before the search. (Bug#76167) diff --git a/lisp/view.el b/lisp/view.el index dc157d8996a..3db7d6038bd 100644 --- a/lisp/view.el +++ b/lisp/view.el @@ -885,7 +885,9 @@ for highlighting the match that is found." (t (error "No previous View-mode search"))) (save-excursion (if end (goto-char (if (< times 0) (point-max) (point-min))) - (forward-line (if (< times 0) -1 1))) + (if (< times 0) + (beginning-of-line) + (end-of-line))) (if (if no (view-search-no-match-lines times regexp) (re-search-forward regexp nil t times)) (setq where (point)))) commit c6fe5b779564001e40d5779976968850aa2a166a Author: Stefan Kangas Date: Fri Mar 7 09:36:38 2025 +0100 Fix using log-edit-mode with git-commit-mode * lisp/vc/log-edit.el (log-edit-font-lock-keywords): Avoid incorrect fontification when used with the third-party git-commit-mode (part of Magit). diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index e23e7414a18..bb85de8bd10 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el @@ -457,9 +457,10 @@ The first subexpression is the actual text of the field.") 'log-edit-header) nil lax)) ("^\n" - (progn (goto-char (match-end 0)) (1+ (match-end 0))) nil - (0 '(face log-edit-headers-separator - display-line-numbers-disable t rear-nonsticky t)))) + (and (not (bound-and-true-p git-commit-mode)) + (progn (goto-char (match-end 0)) (1+ (match-end 0)))) nil + (0 '( face log-edit-headers-separator + display-line-numbers-disable t rear-nonsticky t)))) (log-edit--match-first-line (0 'log-edit-summary)))) (defvar log-edit-font-lock-gnu-style nil commit 646b3f8c5c206b0005020311f382206219f15e64 Author: Stefan Kangas Date: Fri Mar 7 09:28:41 2025 +0100 ; Fix file headers in tty-tip.el * lisp/tty-tip.el: Fix file headers. diff --git a/lisp/tty-tip.el b/lisp/tty-tip.el index e02efdfd359..d738ff9ed92 100644 --- a/lisp/tty-tip.el +++ b/lisp/tty-tip.el @@ -1,5 +1,4 @@ -;;; -*- lexical-binding: t; symbol-packages: t; -*- -;;; tty-tip.el --- Display help in kind of tooltips on ttys +;;; tty-tip.el --- Display help in kind of tooltips on ttys -*- lexical-binding: t; symbol-packages: t; -*- ;; Copyright (C) 2024-2025 Free Software Foundation, Inc. @@ -28,6 +27,8 @@ ;; You can customize face `tooltip', `tooltip-short-delay', ;; `tooltip-delay', `tooltip-recent-seconds'. +;;; Code: + (require 'tooltip) (defvar tty-tip--frame nil) @@ -205,4 +206,4 @@ (provide 'tty-tip) -;;; End +;;; tty-tip.el ends here commit 53b84f7fddbcde969f44318ffcdab889c767352c Author: Stefan Kangas Date: Thu Mar 6 12:41:57 2025 +0100 Use substitute-command-keys in gnus-score-insert-help * lisp/gnus/gnus-score.el (gnus-score-insert-help): Use substitute-command-keys. Clean up the code a bit. diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el index 4f6c12a81ba..a4102ef0b51 100644 --- a/lisp/gnus/gnus-score.el +++ b/lisp/gnus/gnus-score.el @@ -789,31 +789,28 @@ current score file." (delete-windows-on (current-buffer)) (erase-buffer) (insert string ":\n\n") - (let ((max -1) - (list alist) - (i 0) - n width pad format) - ;; find the longest string to display - (while list - (setq n (length (nth idx (car list)))) - (unless (> max n) - (setq max n)) - (setq list (cdr list))) - (setq max (+ max 4)) ; %c, `:', SPACE, a SPACE at end - (setq n (/ (1- (window-width)) max)) ; items per line - (setq width (/ (1- (window-width)) n)) ; width of each item - ;; insert `n' items, each in a field of width `width' - (while alist - (if (< i n) - () - (setq i 0) + (let* ((longest-string (+ 4 ; %c, `:', SPACE, a SPACE at end + (seq-reduce #'max + (mapcar (lambda (elem) + (length (nth idx elem))) + alist) + 0))) + (w (1- (window-width))) + (items-per-line (/ w longest-string)) + (item-width (/ w items-per-line)) + (pad (- item-width 3)) + (i 0)) + ;; Insert `items-per-line' items, each in a field of width + ;; `item-width'. + (dolist (elem alist) + (when (>= i items-per-line) + (setq i 0) (delete-char -1) ; the `\n' takes a char (insert "\n")) - (setq pad (- width 3)) - (setq format (concat "%c: %-" (int-to-string pad) "s")) - (insert (format format (caar alist) (nth idx (car alist)))) - (setq alist (cdr alist)) - (setq i (1+ i)))) + (insert (substitute-command-keys + (format (concat "\\`%c': %-" (int-to-string pad) "s") + (car elem) (nth idx elem)))) + (incf i))) (goto-char (point-min)) ;; display ourselves in a small window at the bottom (appt-select-lowest-window)