commit 5db9471453af4a47d7665295ea007faf35c069b6 (HEAD, refs/remotes/origin/master) Author: Pengji Zhang Date: Wed Dec 11 09:05:09 2024 +0200 Do not call custom-reevaluate-setting in comint.el (bug#74287) * lisp/comint.el (comint--force-history-isearch): New internal variable. (comint-history-isearch-backward, comint-history-isearch-backward-regexp): Set comint--force-history-isearch to t. (comint-history-isearch-setup): Check comint--force-history-isearch. (comint-history-isearch-end): Set comint--force-history-isearch back to nil instead of calling custom-reevaluate-setting. diff --git a/lisp/comint.el b/lisp/comint.el index 6423e695430..d966625550c 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -1538,16 +1538,20 @@ If nil, Isearch operates on the whole comint buffer." :group 'comint :version "23.2") +(defvar comint--force-history-isearch nil + "Non-nil means to force searching in input history. +If nil, respect the option `comint-history-isearch'.") + (defun comint-history-isearch-backward () "Search for a string backward in input history using Isearch." (interactive nil comint-mode) - (setq comint-history-isearch t) + (setq comint--force-history-isearch t) (isearch-backward nil t)) (defun comint-history-isearch-backward-regexp () "Search for a regular expression backward in input history using Isearch." (interactive nil comint-mode) - (setq comint-history-isearch t) + (setq comint--force-history-isearch t) (isearch-backward-regexp nil t)) (defvar-local comint-history-isearch-message-overlay nil) @@ -1563,7 +1567,8 @@ Intended to be added to `isearch-mode-hook' in `comint-mode'." (forward-line 0) (point)) (comint-line-beginning-position))) - (or (eq comint-history-isearch t) + (or comint--force-history-isearch + (eq comint-history-isearch t) (and (eq comint-history-isearch 'dwim) ;; Point is at command line. (comint-after-pmark-p)))) @@ -1593,7 +1598,7 @@ Intended to be added to `isearch-mode-hook' in `comint-mode'." (kill-local-variable 'isearch-lazy-count) (remove-hook 'isearch-mode-end-hook 'comint-history-isearch-end t) (unless isearch-suspended - (custom-reevaluate-setting 'comint-history-isearch))) + (setq comint--force-history-isearch nil))) (defun comint-goto-input (pos) "Put input history item of the absolute history position POS." commit 10e49d7fae708d64fe68effe5890ea77c875a799 Author: Yuan Fu Date: Tue Dec 10 22:08:10 2024 -0800 Make c-ts-mode tests pass even for older tree-sitter libraries * lisp/progmodes/c-ts-mode.el (c-ts-mode--for-loop-indent-rule): Use child index instead of field name. diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index dec9411b87c..4cf0c6c405b 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -364,20 +364,31 @@ PARENT is the parent of the current node." NODE and PARENT as usual." (when (treesit-node-match-p parent "for_statement") - (pcase (treesit-node-field-name node) - ("initializer" - ;; Anchor is the opening paren. - (cons (treesit-node-start (treesit-node-child parent 1)) 1)) - ((or "condition" "update") - (cons (treesit-node-start (treesit-node-prev-sibling node 'named)) - 0)) - ("body" - (cons (c-ts-common--standalone-parent parent) - c-ts-mode-indent-offset)) - (_ (if (treesit-node-match-p node ")") - ;; Anchor is the opening paren. - (cons (treesit-node-start (treesit-node-child parent 1)) 0) - nil))))) + ;; The first version of this function tests for the field name of + ;; NODE, which is a lot cleaner. Alas, older tree-sitter library + ;; has a bug in treesit-node-field-name-for-child, which make it + ;; give the wrong field name for a child node. + (cond + ;; Body (Check if NODE is the last child, because when + ;; initializer/condition/update is empty, the index of body can + ;; change). Eg, for (;;) {...} + ((treesit-node-eq node (treesit-node-child parent -1 'named)) + (cons (c-ts-common--standalone-parent parent) + c-ts-mode-indent-offset)) + ;; Initializer. + ((and (treesit-node-check node 'named) + (eq (treesit-node-index node 'named) 0 )) + ;; Anchor is the opening paren. + (cons (treesit-node-start (treesit-node-child parent 1)) 1)) + ;; Condition and update. + ((and (treesit-node-check node 'named) + (<= 1 (treesit-node-index node 'named) 2)) + (cons (treesit-node-start (treesit-node-prev-sibling node 'named)) + 0)) + ((treesit-node-match-p node ")") + ;; Anchor is the opening paren. + (cons (treesit-node-start (treesit-node-child parent 1)) 0)) + (t nil)))) (defvar c-ts-mode--preproc-indent-rules `(((node-is "preproc") column-0 0) commit 63b9ddda8f8dcfea2927cc4fab7134a7f65c0229 Author: Björn Bidar Date: Wed Dec 11 00:43:29 2024 +0200 Update browse-url-kde variables * lisp/net/browse-url.el (browse-url-kde-program, browse-url-kde-args): Update defaults to more modern alternative to kfmclient. Kfmclient is only installed when Konqueror is installed, which isn't the default file-manager since KDE4. In contrast, it is more likely that kde-open is installed as it is required by Plasma, and it exists since KDE4. (Bug#74775) diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index c10bc671a88..5a54d653720 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -517,12 +517,12 @@ down (this *won't* always work)." :type 'number :version "23.1") -(defcustom browse-url-kde-program "kfmclient" +(defcustom browse-url-kde-program "kde-open" "The name by which to invoke the KDE web browser." :type 'string :version "21.1") -(defcustom browse-url-kde-args '("openURL") +(defcustom browse-url-kde-args nil "A list of strings defining options for `browse-url-kde-program'." :type '(repeat (string :tag "Argument"))) commit 2412b9d763390c26a903604867bad4d2a5ffa67c Author: Stefan Kangas Date: Wed Dec 11 01:06:00 2024 +0100 ; * lisp/loadup.el: Silence checkdoc. diff --git a/lisp/loadup.el b/lisp/loadup.el index bd74a9d6aff..613833c4184 100644 --- a/lisp/loadup.el +++ b/lisp/loadup.el @@ -41,7 +41,7 @@ ;; These rules are so that src/Makefile can construct lisp.mk ;; automatically. This ensures that the Lisp files are compiled (if -;; necessary) before the emacs executable is dumped. +;; necessary) before the "emacs" executable is dumped. ;;; Code: commit d657a38fd1270138301bcd5936f2c9319df69903 Author: Daniel Mendler Date: Wed Dec 11 01:29:01 2024 +0200 Update project-recompile's docstring * lisp/progmodes/project.el (project-recompile): Update the docstring accordingly (bug#74631). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index d4a1832b234..2b0d508cc66 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1488,7 +1488,7 @@ If non-nil, it overrides `compilation-buffer-name-function' for ;;;###autoload (defun project-recompile (&optional edit-command) - "Run `recompile' with appropriate buffer." + "Run `recompile' in the project root with an appropriate buffer." (declare (interactive-only recompile)) (interactive "P") (let ((default-directory (project-root (project-current t))) commit 1012e2a43b9d78ad623f2daa2204a2d1cec830a5 Author: Paul Eggert Date: Tue Dec 10 11:19:25 2024 -0800 Use builtin-expect directly * admin/merge-gnulib (GNULIB_MODULES): Add builtin-expect, since src/lisp.h now uses __builtin_expect directly, which we should no longer rely on it being pulled in as a dependency of some other Gnulib module that we use. diff --git a/admin/merge-gnulib b/admin/merge-gnulib index c265b53684e..0c7de65a323 100755 --- a/admin/merge-gnulib +++ b/admin/merge-gnulib @@ -26,8 +26,8 @@ GNULIB_URL=https://git.savannah.gnu.org/git/gnulib.git GNULIB_MODULES=' - alignasof alloca-opt binary-io boot-time byteswap c-ctype c-strcase - canonicalize-lgpl + alignasof alloca-opt binary-io boot-time builtin-expect byteswap + c-ctype c-strcase canonicalize-lgpl careadlinkat close-stream copy-file-range crypto/md5 crypto/md5-buffer crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer commit 7665ec8df8d1c01211db6a85dda4813d6912ffee Author: Stephen Gildea Date: Tue Dec 10 09:09:39 2024 -0800 time-stamp: properly abbreviate instead of truncating names * lisp/time-stamp (time-stamp-string-preprocess): Stop truncating month and weekday name strings; it didn't internationalize well. Some historical conversions, previously accepted quietly, now warn. (time-stamp-format): Recommend the simpler formats implemented in 2019. * test/lisp/time-stamp-tests.el: Update tests and comments to match. Revert commit 83e4559664 (2022-07-01), which was working around the former confusion between truncation and abbreviation. diff --git a/lisp/time-stamp.el b/lisp/time-stamp.el index a02c1d4532d..50d75ecac01 100644 --- a/lisp/time-stamp.el +++ b/lisp/time-stamp.el @@ -41,53 +41,59 @@ :group 'extensions) -(defcustom time-stamp-format "%Y-%02m-%02d %02H:%02M:%02S %l" +(defcustom time-stamp-format "%Y-%m-%d %H:%M:%S %l" "Format of the string inserted by \\[time-stamp]. -This is a string, used verbatim except for character sequences beginning -with %, as follows. - -%:A weekday name: `Monday' %#A gives uppercase: `MONDAY' -%3a abbreviated weekday: `Mon' %#a gives uppercase: `MON' -%:B month name: `January' %#B gives uppercase: `JANUARY' -%3b abbreviated month: `Jan' %#b gives uppercase: `JAN' -%02d day of month -%02H 24-hour clock hour -%02I 12-hour clock hour -%02m month number -%02M minute -%#p `am' or `pm' %P gives uppercase: `AM' or `PM' -%02S seconds +The string is inserted verbatim except for character sequences beginning +with %, which are converted as follows: + +%A weekday name: `Monday' %a abbreviated weekday name: `Mon' +%B month name: `January' %b abbreviated month name: `Jan' +%d day of month +%H 24-hour clock hour %I 12-hour clock hour +%m month number +%M minute +%p `AM' or `PM' +%S seconds %w day number of week, Sunday is 0 -%02y 2-digit year %Y 4-digit year -%Z time zone name: `EST' %#Z gives lowercase: `est' -%5z time zone offset: `-0500' (since Emacs 27; see note below) +%Y 4-digit year %y 2-digit year +%Z time zone name: `EST' +%-z zone offset with hour: `-08' %:::z adds colons as needed: `+05:30' +%5z zone offset with mins: `-0800' %:z adds colon: `-08:00' Non-date items: -%% a literal percent character: `%' -%f file name without directory %F absolute file name -%l login name %L full name of logged-in user -%q unqualified host name %Q fully-qualified host name +%% literal percent character: \"%\" +%f file name without directory %F absolute file name +%l login name %L full name of logged-in user +%q unqualified host name %Q fully-qualified host name %h mail host name -Decimal digits between the % and the type character specify the -field width. Strings are truncated on the right. -A leading zero in the field width zero-fills a number. +A \"#\" after the % changes the case of letters. For example, on Mondays, +in the default locale, \"%#A\" converts to \"MONDAY\". -For example, to get a common format used by the `date' command, -use \"%3a %3b %2d %02H:%02M:%02S %Z %Y\". +Decimal digits before the type character specify the minimum field +width. A \"0\" before the field width adds insignificant zeroes +as appropriate, otherwise the padding is done with spaces. + +If no padding is specified, a field that can be one or two digits is padded +with \"0\" to two digits if necessary. Follow the % with \"_\" to pad with a +space instead, or follow it with \"-\" to suppress this padding entirely. +Thus, on the 5th of the month, the day is converted as follows: + +\"%d\" -> \"05\" +\"%_d\" -> \" 5\" +\"%-d\" -> \"5\" + +For example, to get a common format used by the \"date\" command, +use \"%a %b %_d %H:%M:%S %Z %Y\". The values of non-numeric formatted items depend on the locale setting recorded in `system-time-locale' and `locale-coding-system'. -The examples here are for the default (`C') locale. +The examples here are for the default (\"C\") locale. `time-stamp-time-zone' controls the time zone used. -The default padding of some formats has changed to be more compatible -with format-time-string. To be compatible with older versions of Emacs, -specify a padding width (as shown) or use the : modifier to request the -transitional behavior (again, as shown). - -The behavior of `%5z' is new in Emacs 27. If your files might be -edited by older versions of Emacs also, do not use this format yet." +Some of the conversions recommended here work only in Emacs 27 or later. +If your files might be edited by older versions of Emacs also, you should +limit yourself to the formats recommended by that older version." :type 'string :version "27.1") ;;;###autoload(put 'time-stamp-format 'safe-local-variable 'stringp) @@ -273,11 +279,11 @@ Examples: // time-stamp-pattern: \"-9/^Last modified: %%$\" (sets `time-stamp-line-limit', `time-stamp-start' and `time-stamp-end') -@c time-stamp-pattern: \"@set Time-stamp: %:B %1d, %Y$\" +@c time-stamp-pattern: \"@set Time-stamp: %B %-d, %Y$\" (sets `time-stamp-start', `time-stamp-format' and `time-stamp-end') %% time-stamp-pattern: \"newcommand{\\\\\\\\timestamp}{%%}\" - (sets `time-stamp-start'and `time-stamp-end') + (sets `time-stamp-start' and `time-stamp-end') See also `time-stamp-count' and `time-stamp-inserts-lines'.") @@ -483,7 +489,7 @@ normally the current time is used." ;;; At all times, all the formats recommended in the doc string ;;; of time-stamp-format will work not only in the current version of ;;; Emacs, but in all versions that have been released within the past -;;; two years. +;;; five years. ;;; The : modifier is a temporary conversion feature used to resolve ;;; ambiguous formats--formats that are changing (over time) incompatibly. (defun time-stamp-string-preprocess (format &optional time) @@ -576,10 +582,22 @@ and all `time-stamp-format' compatibility." (time-stamp--format "%#a" time) (time-stamp--format "%a" time)))) ((eq cur-char ?A) - (if (or change-case upcase (not (string-equal field-width - ""))) - (time-stamp--format "%#A" time) - (time-stamp--format "%A" time))) + (if (and (>= (string-to-number field-width) 1) + (<= (string-to-number field-width) 3) + (not flag-minimize) + (not flag-pad-with-spaces)) + (progn + (time-stamp-conv-warn "%3A" "%#a") + (time-stamp--format "%#a" time)) + (if (or change-case upcase) + (time-stamp--format "%#A" time) + (if (or (> alt-form 0) + flag-minimize flag-pad-with-spaces + (string-equal field-width "")) + (time-stamp--format "%A" time) + (time-stamp-conv-warn (format "%%%sA" field-width) + (format "%%#%sA" field-width)) + (time-stamp--format "%#A" time))))) ((eq cur-char ?b) ;month name (if (> alt-form 0) (if (string-equal field-width "") @@ -589,10 +607,22 @@ and all `time-stamp-format' compatibility." (time-stamp--format "%#b" time) (time-stamp--format "%b" time)))) ((eq cur-char ?B) - (if (or change-case upcase (not (string-equal field-width - ""))) - (time-stamp--format "%#B" time) - (time-stamp--format "%B" time))) + (if (and (>= (string-to-number field-width) 1) + (<= (string-to-number field-width) 3) + (not flag-minimize) + (not flag-pad-with-spaces)) + (progn + (time-stamp-conv-warn "%3B" "%#b") + (time-stamp--format "%#b" time)) + (if (or change-case upcase) + (time-stamp--format "%#B" time) + (if (or (> alt-form 0) + flag-minimize flag-pad-with-spaces + (string-equal field-width "")) + (time-stamp--format "%B" time) + (time-stamp-conv-warn (format "%%%sB" field-width) + (format "%%#%sB" field-width)) + (time-stamp--format "%#B" time))))) ((eq cur-char ?d) ;day of month, 1-31 (time-stamp-do-number cur-char alt-form field-width time)) ((eq cur-char ?H) ;hour, 0-23 @@ -620,13 +650,15 @@ and all `time-stamp-format' compatibility." ((eq cur-char ?w) ;weekday number, Sunday is 0 (time-stamp--format "%w" time)) ((eq cur-char ?y) ;year - (if (> alt-form 0) - (string-to-number (time-stamp--format "%Y" time)) - (if (or (string-equal field-width "") - (<= (string-to-number field-width) 2)) - (string-to-number (time-stamp--format "%y" time)) - (time-stamp-conv-warn (format "%%%sy" field-width) "%Y") - (string-to-number (time-stamp--format "%Y" time))))) + (if (= alt-form 0) + (if (or (string-equal field-width "") + (<= (string-to-number field-width) 2)) + (string-to-number (time-stamp--format "%y" time)) + (time-stamp-conv-warn + (format "%%%sy" field-width) "%Y") + (string-to-number (time-stamp--format "%Y" time))) + (time-stamp-conv-warn "%:y" "%Y") + (string-to-number (time-stamp--format "%Y" time)))) ((eq cur-char ?Y) ;4-digit year (string-to-number (time-stamp--format "%Y" time))) ((eq cur-char ?z) ;time zone offset @@ -673,10 +705,13 @@ and all `time-stamp-format' compatibility." (or buffer-file-name time-stamp-no-file)) ((eq cur-char ?s) ;system name, legacy + (time-stamp-conv-warn "%s" "%Q") (system-name)) ((eq cur-char ?u) ;user name, legacy + (time-stamp-conv-warn "%u" "%l") (user-login-name)) ((eq cur-char ?U) ;user full name, legacy + (time-stamp-conv-warn "%U" "%L") (user-full-name)) ((eq cur-char ?l) ;login name (user-login-name)) @@ -694,25 +729,14 @@ and all `time-stamp-format' compatibility." )) (and (numberp field-result) (= alt-form 0) - (string-equal field-width "") + (or (string-equal field-width "") + (string-equal field-width "0")) ;; no width provided; set width for default (setq field-width "02")) - (let ((padded-result - (format (format "%%%s%c" - field-width - (if (numberp field-result) ?d ?s)) - (or field-result "")))) - (let* ((initial-length (length padded-result)) - (desired-length (if (string-equal field-width "") - initial-length - (string-to-number field-width)))) - (if (> initial-length desired-length) - ;; truncate strings on right - (if (and (stringp field-result) - (not (eq cur-char ?z))) ;offset does not truncate - (substring padded-result 0 desired-length) - padded-result) ;numbers don't truncate - padded-result))))) + (format (format "%%%s%c" + field-width + (if (numberp field-result) ?d ?s)) + (or field-result "")))) (t (char-to-string cur-char))))) (setq ind (1+ ind))) @@ -883,7 +907,7 @@ OFFSET-SECS is the time zone offset (in seconds east of UTC) to be formatted according to the preceding parameters. This is an internal function used by `time-stamp'." - ;; The caller of this function must have already parsed the %z + ;; Callers of this function need to have already parsed the %z ;; format string; this function accepts just the parts of the format. ;; `time-stamp-string-preprocess' is the full-fledged parser normally ;; used. The unit test (in time-stamp-tests.el) defines the simpler diff --git a/test/lisp/time-stamp-tests.el b/test/lisp/time-stamp-tests.el index b05904ad017..7cf8f995c13 100644 --- a/test/lisp/time-stamp-tests.el +++ b/test/lisp/time-stamp-tests.el @@ -45,7 +45,7 @@ ,@body))) (defmacro with-time-stamp-test-time (reference-time &rest body) - "Force any contained time-stamp call to use time REFERENCE-TIME." + "Force `time-stamp' to use time REFERENCE-TIME while evaluating BODY." (declare (indent 1) (debug t)) `(cl-letf* ((orig-time-stamp-string-fn (symbol-function 'time-stamp-string)) @@ -55,14 +55,14 @@ ,@body)) (defmacro with-time-stamp-system-name (name &rest body) - "Force (system-name) to return NAME while evaluating BODY." + "Force `system-name' to return NAME while evaluating BODY." (declare (indent 1) (debug t)) `(cl-letf (((symbol-function 'system-name) (lambda () ,name))) ,@body)) (defmacro time-stamp-should-warn (form) - "Similar to `should' but verifies that a format warning is generated." + "Similar to `should' and also verify that FORM generates a format warning." (declare (debug t)) `(let ((warning-count 0)) (cl-letf (((symbol-function 'time-stamp-conv-warn) @@ -269,70 +269,111 @@ (ert-deftest time-stamp-format-day-of-week () "Test time-stamp formats for named day of week." (with-time-stamp-test-env - (let ((Mon (format-time-string "%a" ref-time1 t)) - (MON (format-time-string "%^a" ref-time1 t)) - (Monday (format-time-string "%A" ref-time1 t)) - (MONDAY (format-time-string "%^A" ref-time1 t))) - ;; implemented and documented since 1997 - (should (equal (time-stamp-string "%3a" ref-time1) Mon)) + (let* ((Mon (format-time-string "%a" ref-time1 t)) + (MON (format-time-string "%^a" ref-time1 t)) + (Monday (format-time-string "%A" ref-time1 t)) + (MONDAY (format-time-string "%^A" ref-time1 t)) + (p4-Mon (string-pad Mon 4 ?\s t)) + (p4-MON (string-pad MON 4 ?\s t)) + (p10-Monday (string-pad Monday 10 ?\s t)) + (p10-MONDAY (string-pad MONDAY 10 ?\s t))) + ;; implemented and recommended since 1997 (should (equal (time-stamp-string "%#A" ref-time1) MONDAY)) - ;; documented 1997-2019 - (should (equal (time-stamp-string "%3A" ref-time1) - (substring MONDAY 0 3))) + (should (equal (time-stamp-string "%#10A" ref-time1) p10-MONDAY)) + ;; implemented since 1997, recommended 1997-2024 + (should (equal (time-stamp-string "%3a" ref-time1) Mon)) + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:a" ref-time1) Monday)) - ;; implemented since 2001, documented since 2019 + ;; recommended 1997-2019, warned since 2024, will change + (time-stamp-should-warn + (should (equal (time-stamp-string "%3A" ref-time1) MON))) + (time-stamp-should-warn + (should (equal (time-stamp-string "%10A" ref-time1) p10-MONDAY))) + ;; implemented since 2001, recommended since 2019 (should (equal (time-stamp-string "%#a" ref-time1) MON)) + (should (equal (time-stamp-string "%#3a" ref-time1) MON)) + (should (equal (time-stamp-string "%#4a" ref-time1) p4-MON)) + ;; implemented since 2001, recommended 2019-2024 (should (equal (time-stamp-string "%:A" ref-time1) Monday)) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; broken 2019-2024 + (should (equal (time-stamp-string "%:10A" ref-time1) p10-Monday)) + ;; broken in 2019, changed in 2024 + (should (equal (time-stamp-string "%-A" ref-time1) Monday)) + (should (equal (time-stamp-string "%_A" ref-time1) Monday)) + ;; allowed but not recommended since 2019 (warned 1997-2019) (should (equal (time-stamp-string "%^A" ref-time1) MONDAY)) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%a" ref-time1) Mon)) + (should (equal (time-stamp-string "%4a" ref-time1) p4-Mon)) + (should (equal (time-stamp-string "%04a" ref-time1) p4-Mon)) + (should (equal (time-stamp-string "%A" ref-time1) Monday)) + ;; warned 1997-2019, changed in 2019 (should (equal (time-stamp-string "%^a" ref-time1) MON)) - (should (equal (time-stamp-string "%A" ref-time1) Monday))))) + (should (equal (time-stamp-string "%^4a" ref-time1) p4-MON))))) (ert-deftest time-stamp-format-month-name () "Test time-stamp formats for month name." (with-time-stamp-test-env - (let ((Jan (format-time-string "%b" ref-time1 t)) - (JAN (format-time-string "%^b" ref-time1 t)) - (January (format-time-string "%B" ref-time1 t)) - (JANUARY (format-time-string "%^B" ref-time1 t))) - ;; implemented and documented since 1997 - (should (equal (time-stamp-string "%3b" ref-time1) - (substring January 0 3))) + (let* ((Jan (format-time-string "%b" ref-time1 t)) + (JAN (format-time-string "%^b" ref-time1 t)) + (January (format-time-string "%B" ref-time1 t)) + (JANUARY (format-time-string "%^B" ref-time1 t)) + (p4-Jan (string-pad Jan 4 ?\s t)) + (p4-JAN (string-pad JAN 4 ?\s t)) + (p10-January (string-pad January 10 ?\s t)) + (p10-JANUARY (string-pad JANUARY 10 ?\s t))) + ;; implemented and recommended since 1997 (should (equal (time-stamp-string "%#B" ref-time1) JANUARY)) - ;; documented 1997-2019 - (should (equal (time-stamp-string "%3B" ref-time1) - (substring JANUARY 0 3))) + (should (equal (time-stamp-string "%#10B" ref-time1) p10-JANUARY)) + ;; implemented since 1997, recommended 1997-2024 + (should (equal (time-stamp-string "%3b" ref-time1) Jan)) + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:b" ref-time1) January)) - ;; implemented since 2001, documented since 2019 + ;; recommended 1997-2019, warned since 2024, will change + (time-stamp-should-warn + (should (equal (time-stamp-string "%3B" ref-time1) JAN))) + (time-stamp-should-warn + (should (equal (time-stamp-string "%10B" ref-time1) p10-JANUARY))) + ;; implemented since 2001, recommended since 2019 (should (equal (time-stamp-string "%#b" ref-time1) JAN)) + (should (equal (time-stamp-string "%#3b" ref-time1) JAN)) + (should (equal (time-stamp-string "%#4b" ref-time1) p4-JAN)) + ;; implemented since 2001, recommended 2019-2024 (should (equal (time-stamp-string "%:B" ref-time1) January)) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; broken 2019-2024 + (should (equal (time-stamp-string "%:10B" ref-time1) p10-January)) + ;; broken in 2019, changed in 2024 + (should (equal (time-stamp-string "%-B" ref-time1) January)) + (should (equal (time-stamp-string "%_B" ref-time1) January)) + ;; allowed but not recommended since 2019 (warned 1997-2019) (should (equal (time-stamp-string "%^B" ref-time1) JANUARY)) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%b" ref-time1) Jan)) + (should (equal (time-stamp-string "%4b" ref-time1) p4-Jan)) + (should (equal (time-stamp-string "%04b" ref-time1) p4-Jan)) + (should (equal (time-stamp-string "%B" ref-time1) January)) + ;; warned 1997-2019, changed in 2019 (should (equal (time-stamp-string "%^b" ref-time1) JAN)) - (should (equal (time-stamp-string "%B" ref-time1) January))))) + (should (equal (time-stamp-string "%^4b" ref-time1) p4-JAN))))) (ert-deftest time-stamp-format-day-of-month () "Test time-stamp formats for day of month." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2d" ref-time1) " 2")) (should (equal (time-stamp-string "%2d" ref-time2) "18")) (should (equal (time-stamp-string "%02d" ref-time1) "02")) (should (equal (time-stamp-string "%02d" ref-time2) "18")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:d" ref-time1) "2")) (should (equal (time-stamp-string "%:d" ref-time2) "18")) - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1d" ref-time1) "2")) (should (equal (time-stamp-string "%1d" ref-time2) "18")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-d" ref-time1) "2")) (should (equal (time-stamp-string "%-d" ref-time2) "18")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_d" ref-time1) " 2")) (should (equal (time-stamp-string "%_d" ref-time2) "18")) (should (equal (time-stamp-string "%d" ref-time1) "02")) @@ -341,26 +382,26 @@ (ert-deftest time-stamp-format-hours-24 () "Test time-stamp formats for hour on a 24-hour clock." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2H" ref-time1) "15")) (should (equal (time-stamp-string "%2H" ref-time2) "12")) (should (equal (time-stamp-string "%2H" ref-time3) " 6")) (should (equal (time-stamp-string "%02H" ref-time1) "15")) (should (equal (time-stamp-string "%02H" ref-time2) "12")) (should (equal (time-stamp-string "%02H" ref-time3) "06")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:H" ref-time1) "15")) (should (equal (time-stamp-string "%:H" ref-time2) "12")) (should (equal (time-stamp-string "%:H" ref-time3) "6")) - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended 2019-2024 (should (equal (time-stamp-string "%1H" ref-time1) "15")) (should (equal (time-stamp-string "%1H" ref-time2) "12")) (should (equal (time-stamp-string "%1H" ref-time3) "6")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-H" ref-time1) "15")) (should (equal (time-stamp-string "%-H" ref-time2) "12")) (should (equal (time-stamp-string "%-H" ref-time3) "6")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_H" ref-time1) "15")) (should (equal (time-stamp-string "%_H" ref-time2) "12")) (should (equal (time-stamp-string "%_H" ref-time3) " 6")) @@ -371,26 +412,26 @@ (ert-deftest time-stamp-format-hours-12 () "Test time-stamp formats for hour on a 12-hour clock." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2I" ref-time1) " 3")) (should (equal (time-stamp-string "%2I" ref-time2) "12")) (should (equal (time-stamp-string "%2I" ref-time3) " 6")) (should (equal (time-stamp-string "%02I" ref-time1) "03")) (should (equal (time-stamp-string "%02I" ref-time2) "12")) (should (equal (time-stamp-string "%02I" ref-time3) "06")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:I" ref-time1) "3")) ;PM (should (equal (time-stamp-string "%:I" ref-time2) "12")) ;PM (should (equal (time-stamp-string "%:I" ref-time3) "6")) ;AM - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended since 2019 (should (equal (time-stamp-string "%1I" ref-time1) "3")) (should (equal (time-stamp-string "%1I" ref-time2) "12")) (should (equal (time-stamp-string "%1I" ref-time3) "6")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-I" ref-time1) "3")) (should (equal (time-stamp-string "%-I" ref-time2) "12")) (should (equal (time-stamp-string "%-I" ref-time3) "6")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_I" ref-time1) " 3")) (should (equal (time-stamp-string "%_I" ref-time2) "12")) (should (equal (time-stamp-string "%_I" ref-time3) " 6")) @@ -401,21 +442,21 @@ (ert-deftest time-stamp-format-month-number () "Test time-stamp formats for month number." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2m" ref-time1) " 1")) (should (equal (time-stamp-string "%2m" ref-time2) "11")) (should (equal (time-stamp-string "%02m" ref-time1) "01")) (should (equal (time-stamp-string "%02m" ref-time2) "11")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:m" ref-time1) "1")) (should (equal (time-stamp-string "%:m" ref-time2) "11")) - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended since 2019 (should (equal (time-stamp-string "%1m" ref-time1) "1")) (should (equal (time-stamp-string "%1m" ref-time2) "11")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-m" ref-time1) "1")) (should (equal (time-stamp-string "%-m" ref-time2) "11")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_m" ref-time1) " 1")) (should (equal (time-stamp-string "%_m" ref-time2) "11")) (should (equal (time-stamp-string "%m" ref-time1) "01")) @@ -424,21 +465,21 @@ (ert-deftest time-stamp-format-minute () "Test time-stamp formats for minute." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2M" ref-time1) " 4")) (should (equal (time-stamp-string "%2M" ref-time2) "14")) (should (equal (time-stamp-string "%02M" ref-time1) "04")) (should (equal (time-stamp-string "%02M" ref-time2) "14")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:M" ref-time1) "4")) (should (equal (time-stamp-string "%:M" ref-time2) "14")) - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended since 2019 (should (equal (time-stamp-string "%1M" ref-time1) "4")) (should (equal (time-stamp-string "%1M" ref-time2) "14")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-M" ref-time1) "4")) (should (equal (time-stamp-string "%-M" ref-time2) "14")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_M" ref-time1) " 4")) (should (equal (time-stamp-string "%_M" ref-time2) "14")) (should (equal (time-stamp-string "%M" ref-time1) "04")) @@ -447,21 +488,21 @@ (ert-deftest time-stamp-format-second () "Test time-stamp formats for second." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended until 2024 (should (equal (time-stamp-string "%2S" ref-time1) " 5")) (should (equal (time-stamp-string "%2S" ref-time2) "15")) (should (equal (time-stamp-string "%02S" ref-time1) "05")) (should (equal (time-stamp-string "%02S" ref-time2) "15")) - ;; documented 1997-2019 + ;; recommended 1997-2019 (should (equal (time-stamp-string "%:S" ref-time1) "5")) (should (equal (time-stamp-string "%:S" ref-time2) "15")) - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended since 2019 (should (equal (time-stamp-string "%1S" ref-time1) "5")) (should (equal (time-stamp-string "%1S" ref-time2) "15")) - ;; allowed but undocumented since 2019 (warned 1997-2019) + ;; warned 1997-2019, allowed 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%-S" ref-time1) "5")) (should (equal (time-stamp-string "%-S" ref-time2) "15")) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%_S" ref-time1) " 5")) (should (equal (time-stamp-string "%_S" ref-time2) "15")) (should (equal (time-stamp-string "%S" ref-time1) "05")) @@ -470,12 +511,14 @@ (ert-deftest time-stamp-format-year-2digit () "Test time-stamp formats for %y." (with-time-stamp-test-env - ;; implemented and documented since 1995 + ;; implemented since 1995, recommended 1995-2024 (should (equal (time-stamp-string "%02y" ref-time1) "06")) (should (equal (time-stamp-string "%02y" ref-time2) "16")) - ;; documented 1997-2019 - (should (equal (time-stamp-string "%:y" ref-time1) "2006")) - (should (equal (time-stamp-string "%:y" ref-time2) "2016")) + ;; recommended 1997-2019, warned since 2024 + (time-stamp-should-warn + (should (equal (time-stamp-string "%:y" ref-time1) "2006"))) + (time-stamp-should-warn + (should (equal (time-stamp-string "%:y" ref-time2) "2016"))) ;; warned 1997-2019, changed in 2019 ;; (We don't expect the %-y or %_y form to be useful, ;; but we test both so that we can confidently state that @@ -484,6 +527,7 @@ (should (equal (time-stamp-string "%-y" ref-time2) "16")) (should (equal (time-stamp-string "%_y" ref-time1) " 6")) (should (equal (time-stamp-string "%_y" ref-time2) "16")) + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%y" ref-time1) "06")) (should (equal (time-stamp-string "%y" ref-time2) "16")) ;; implemented since 1995, warned since 2019, will change @@ -495,7 +539,7 @@ (ert-deftest time-stamp-format-year-4digit () "Test time-stamp format %Y." (with-time-stamp-test-env - ;; implemented since 1997, documented since 2019 + ;; implemented since 1997, recommended since 2019 (should (equal (time-stamp-string "%Y" ref-time1) "2006")) ;; numbers do not truncate (should (equal (time-stamp-string "%2Y" ref-time1) "2006")) @@ -510,15 +554,16 @@ (Am (format-time-string "%p" ref-time3 t)) (PM (format-time-string "%^p" ref-time1 t)) (AM (format-time-string "%^p" ref-time3 t))) - ;; implemented and documented since 1997 + ;; implemented and recommended since 1997 (should (equal (time-stamp-string "%#p" ref-time1) pm)) (should (equal (time-stamp-string "%#p" ref-time3) am)) + ;; implemented since 1997, recommended 1997-2024 (should (equal (time-stamp-string "%P" ref-time1) Pm)) (should (equal (time-stamp-string "%P" ref-time3) Am)) ;; implemented since 1997 (should (equal (time-stamp-string "%^#p" ref-time1) pm)) (should (equal (time-stamp-string "%^#p" ref-time3) am)) - ;; warned 1997-2019, changed in 2019 + ;; warned 1997-2019, changed in 2019, recommended (with caveat) since 2024 (should (equal (time-stamp-string "%p" ref-time1) Pm)) (should (equal (time-stamp-string "%p" ref-time3) Am)) ;; changed in 2024 @@ -543,19 +588,22 @@ (with-time-stamp-test-env (let ((UTC-abbr (format-time-string "%Z" ref-time1 t)) (utc-abbr (format-time-string "%#Z" ref-time1 t))) - ;; implemented and documented since 1995 + ;; implemented and recommended since 1995 (should (equal (time-stamp-string "%Z" ref-time1) UTC-abbr)) - ;; implemented since 1997, documented since 2019 - (should (equal (time-stamp-string "%#Z" ref-time1) utc-abbr))))) + ;; implemented since 1997, recommended since 2019 + (should (equal (time-stamp-string "%#Z" ref-time1) utc-abbr)) + ;; ^ accepted and ignored since 1995/1997, test for consistency with %p + (should (equal (time-stamp-string "%^Z" ref-time1) UTC-abbr)) + (should (equal (time-stamp-string "%^#Z" ref-time1) utc-abbr))))) (ert-deftest time-stamp-format-time-zone-offset () "Test time-stamp legacy format %z and spot-test new offset format %5z." (with-time-stamp-test-env (let ((utc-abbr (format-time-string "%#Z" ref-time1 t))) - ;; documented 1995-2019, warned since 2019, will change + ;; recommended 1995-2019, warned since 2019, will change (time-stamp-should-warn (equal (time-stamp-string "%z" ref-time1) utc-abbr))) - ;; implemented and documented (with compat caveat) since 2019 + ;; implemented and recommended (with compat caveat) since 2019 (should (equal (time-stamp-string "%5z" ref-time1) "+0000")) (let ((time-stamp-time-zone "PST8")) (should (equal (time-stamp-string "%5z" ref-time1) "-0800"))) @@ -563,20 +611,21 @@ (should (equal (time-stamp-string "%5z" ref-time1) "-1000"))) (let ((time-stamp-time-zone "CET-1")) (should (equal (time-stamp-string "%5z" ref-time1) "+0100"))) - ;; implemented since 2019, verify that these don't warn + ;; implemented since 2019, recommended (with compat caveat) since 2024 ;; See also the "formatz" tests below, which since 2021 test more ;; variants with more offsets. (should (equal (time-stamp-string "%-z" ref-time1) "+00")) + (should (equal (time-stamp-string "%:::z" ref-time1) "+00")) (should (equal (time-stamp-string "%:z" ref-time1) "+00:00")) + ;; implemented since 2019 (should (equal (time-stamp-string "%::z" ref-time1) "+00:00:00")) - (should (equal (time-stamp-string "%9::z" ref-time1) "+00:00:00")) - (should (equal (time-stamp-string "%:::z" ref-time1) "+00")))) + (should (equal (time-stamp-string "%9::z" ref-time1) "+00:00:00")))) (ert-deftest time-stamp-format-non-date-conversions () "Test time-stamp formats for non-date items." (with-time-stamp-test-env (with-time-stamp-system-name "test-system-name.example.org" - ;; implemented and documented since 1995 + ;; implemented and recommended since 1995 (should (equal (time-stamp-string "%%" ref-time1) "%")) ;% last char (should (equal (time-stamp-string "%%P" ref-time1) "%P")) ;% not last char (should (equal (time-stamp-string "%f" ref-time1) "time-stamped-file")) @@ -589,15 +638,18 @@ (let ((mail-host-address nil)) (should (equal (time-stamp-string "%h" ref-time1) "test-system-name.example.org"))) - ;; documented 1995-2019 - (should (equal (time-stamp-string "%s" ref-time1) - "test-system-name.example.org")) - (should (equal (time-stamp-string "%U" ref-time1) "100%d Tester")) - (should (equal (time-stamp-string "%u" ref-time1) "test-logname")) - ;; implemented since 2001, documented since 2019 + ;; recommended 1997-2019, warned since 2024 + (time-stamp-should-warn + (should (equal (time-stamp-string "%s" ref-time1) + "test-system-name.example.org"))) + (time-stamp-should-warn + (should (equal (time-stamp-string "%U" ref-time1) "100%d Tester"))) + (time-stamp-should-warn + (should (equal (time-stamp-string "%u" ref-time1) "test-logname"))) + ;; implemented since 2001, recommended since 2019 (should (equal (time-stamp-string "%L" ref-time1) "100%d Tester")) (should (equal (time-stamp-string "%l" ref-time1) "test-logname")) - ;; implemented since 2007, documented since 2019 + ;; implemented since 2007, recommended since 2019 (should (equal (time-stamp-string "%Q" ref-time1) "test-system-name.example.org")) (should (equal (time-stamp-string "%q" ref-time1) "test-system-name"))) @@ -668,24 +720,20 @@ (ert-deftest time-stamp-format-string-width () "Test time-stamp string width modifiers." (with-time-stamp-test-env - (let ((May (format-time-string "%b" ref-time3 t)) - (SUN (format-time-string "%^a" ref-time3 t)) - (NOV (format-time-string "%^b" ref-time2 t))) - ;; strings truncate on the right or are blank-padded on the left - (should (equal (time-stamp-string "%0b" ref-time3) "")) - (should (equal (time-stamp-string "%1b" ref-time3) (substring May 0 1))) - (should (equal (time-stamp-string "%2b" ref-time3) (substring May 0 2))) - (should (equal (time-stamp-string "%3b" ref-time3) (substring May 0 3))) - (should (equal (time-stamp-string "%4b" ref-time3) (concat " " May))) - (should (equal (time-stamp-string "%0%" ref-time3) "")) - (should (equal (time-stamp-string "%1%" ref-time3) "%")) - (should (equal (time-stamp-string "%2%" ref-time3) " %")) - (should (equal (time-stamp-string "%9%" ref-time3) " %")) - (should (equal (time-stamp-string "%10%" ref-time3) " %")) - (should (equal (time-stamp-string "%#3a" ref-time3) - (substring SUN 0 3))) - (should (equal (time-stamp-string "%#3b" ref-time2) - (substring NOV 0 3)))))) + (let ((UTC-abbr (format-time-string "%Z" ref-time1 t))) + (should (equal (time-stamp-string "%1%" ref-time3) "%")) + (should (equal (time-stamp-string "%2%" ref-time3) " %")) + (should (equal (time-stamp-string "%9%" ref-time3) " %")) + (should (equal (time-stamp-string "%10%" ref-time3) " %")) + (should (equal (time-stamp-string "%03d" ref-time3) "025")) + (should (equal (time-stamp-string "%3d" ref-time3) " 25")) + (should (equal (time-stamp-string "%_3d" ref-time3) " 25")) + ;; since 2024 + (should (equal (time-stamp-string "%0d" ref-time1) "02")) + (should (equal (time-stamp-string "%0d" ref-time2) "18")) + ;; broken 2019-2024 + (should (equal (time-stamp-string "%-Z" ref-time1) UTC-abbr)) + (should (equal (time-stamp-string "%_Z" ref-time1) UTC-abbr))))) ;;; Tests of helper functions @@ -895,11 +943,11 @@ The functions in `pattern-mod' are composed left to right." (defun formatz-mod-pad-r10 (string) "Return STRING padded on the right to 10 characters." - (concat string (make-string (- 10 (length string)) ?\s))) + (string-pad string 10)) (defun formatz-mod-pad-r12 (string) "Return STRING padded on the right to 12 characters." - (concat string (make-string (- 12 (length string)) ?\s))) + (string-pad string 12)) ;; Convenience macro for generating groups of test cases. @@ -966,7 +1014,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ;;;; The actual test cases for %z -;;; %z formats without colons. +;;; Test %z formats without colons. ;; Option character "-" (minus) minimizes; it removes "00" minutes. (formatz-generate-tests ("%-z" "%-3z") @@ -976,7 +1024,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00") ("+100:00:30")) -;; Tests that minus with padding pads with spaces. +;; Minus with padding pads with spaces. (formatz-generate-tests ("%-12z") ("+00 " formatz-mod-pad-r12) ("+0030 " formatz-mod-del-colons formatz-mod-pad-r12) @@ -984,7 +1032,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00 " formatz-mod-pad-r12) ("+100:00:30 " formatz-mod-pad-r12)) -;; Tests that 0 after other digits becomes padding of ten, not zero flag. +;; 0 after other digits becomes padding of ten, not zero flag. (formatz-generate-tests ("%-10z") ("+00 " formatz-mod-pad-r10) ("+0030 " formatz-mod-del-colons formatz-mod-pad-r10) @@ -1017,7 +1065,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00") ("+100:00:30")) -;; Tests that padding adds spaces. +;; Padding adds spaces. (formatz-generate-tests ("%12z") ("+0000 " formatz-mod-add-00 formatz-mod-pad-r12) ("+0030 " formatz-mod-del-colons formatz-mod-pad-r12) @@ -1049,7 +1097,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12) ("+100:00:30 " formatz-mod-pad-r12)) -;;; %z formats with colons +;;; Test %z formats with colons. ;; Three colons can output hours only, ;; like %-z, but uses colons with non-zero minutes and seconds. @@ -1061,14 +1109,15 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00") ("+100:00:30")) -;; Padding with three colons adds spaces +;; Padding with three colons adds spaces. (formatz-generate-tests ("%12:::z") ("+00 " formatz-mod-pad-r12) ("+00:30 " formatz-mod-pad-r12) ("+00:00:30 " formatz-mod-pad-r12) ("+100:00 " formatz-mod-pad-r12) ("+100:00:30 " formatz-mod-pad-r12)) -;; Tests that 0 after other digits becomes padding of ten, not zero flag. + +;; 0 after other digits becomes padding of ten, not zero flag. (formatz-generate-tests ("%10:::z") ("+00 " formatz-mod-pad-r10) ("+00:30 " formatz-mod-pad-r10) @@ -1084,7 +1133,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00") ("+100:00:30")) -;; Padding with one colon adds spaces +;; Padding with one colon adds spaces. (formatz-generate-tests ("%12:z") ("+00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12) ("+00:30 " formatz-mod-pad-r12) @@ -1117,7 +1166,7 @@ the other expected results for hours greater than 99 with non-zero seconds." ("+100:00:00 " formatz-mod-add-colon00 formatz-mod-pad-r12) ("+100:00:30 " formatz-mod-pad-r12)) -;;; Illegal %z formats +;;; Test illegal %z formats. (ert-deftest formatz-illegal-options () "Test that illegal/nonsensical/ambiguous %z formats don't produce output." commit ebd8feef1491907ebf4648a3aa38ddaa7fbf1dd2 Author: Robert Pluim Date: Tue Dec 10 09:42:11 2024 +0100 Move ns-specific event setup to term/ns-win.el (Bug#74619) * lisp/term/ns-win.el (ns-setup-special-keys): New function, contains event setup code previously in term/common-win.el. Call it at top-level. * lisp/term/common-win.el (x-setup-function-keys): Call 'ns-setup-special-keys'. diff --git a/lisp/term/common-win.el b/lisp/term/common-win.el index 181dcc8e6d9..68c3b2d56e3 100644 --- a/lisp/term/common-win.el +++ b/lisp/term/common-win.el @@ -45,6 +45,8 @@ map) "Keymap of possible alternative meanings for some keys.") +(declare-function ns-setup-special-keys "term/ns-win" ()) + (defun x-setup-function-keys (frame) "Set up `function-key-map' on the graphical frame FRAME." ;; Don't do this twice on the same display, or it would break @@ -56,22 +58,7 @@ (set-keymap-parent map (keymap-parent local-function-key-map)) (set-keymap-parent local-function-key-map map)) (when (featurep 'ns) - (setq system-key-alist - (list - ;; These are special "keys" used to pass events from C to lisp. - (cons 1 (make-non-key-event 'ns-power-off)) - (cons 2 (make-non-key-event 'ns-open-file)) - (cons 3 (make-non-key-event 'ns-open-temp-file)) - (cons 4 (make-non-key-event 'ns-drag-file)) - (cons 5 (make-non-key-event 'ns-drag-color)) - (cons 6 (make-non-key-event 'ns-drag-text)) - (cons 8 (make-non-key-event 'ns-open-file-line)) -;;; (cons 9 (make-non-key-event 'ns-insert-working-text)) -;;; (cons 10 (make-non-key-event 'ns-delete-working-text)) - (cons 11 (make-non-key-event 'ns-spi-service-call)) - (cons 12 (make-non-key-event 'ns-new-frame)) - (cons 13 (make-non-key-event 'ns-toggle-toolbar)) - (cons 14 (make-non-key-event 'ns-show-prefs)))))) + (ns-setup-special-keys))) (set-terminal-parameter frame 'x-setup-function-keys t))) (defvar x-invocation-args) diff --git a/lisp/term/ns-win.el b/lisp/term/ns-win.el index 2a29457133e..2188aa67e54 100644 --- a/lisp/term/ns-win.el +++ b/lisp/term/ns-win.el @@ -168,6 +168,27 @@ The properties returned may include `top', `left', `height', and `width'." (define-key global-map [S-mouse-1] 'mouse-save-then-kill) (global-unset-key [S-down-mouse-1]) +;; Moved here from common-win.el because they need to work in a -nw +;; invocation of a (featurep 'ns) => true build (Bug#74619). +(defun ns-setup-special-keys () + (setq system-key-alist + (list + ;; These are special "keys" used to pass events from C to lisp. + (cons 1 (make-non-key-event 'ns-power-off)) + (cons 2 (make-non-key-event 'ns-open-file)) + (cons 3 (make-non-key-event 'ns-open-temp-file)) + (cons 4 (make-non-key-event 'ns-drag-file)) + (cons 5 (make-non-key-event 'ns-drag-color)) + (cons 6 (make-non-key-event 'ns-drag-text)) + (cons 8 (make-non-key-event 'ns-open-file-line)) +;;; (cons 9 (make-non-key-event 'ns-insert-working-text)) +;;; (cons 10 (make-non-key-event 'ns-delete-working-text)) + (cons 11 (make-non-key-event 'ns-spi-service-call)) + (cons 12 (make-non-key-event 'ns-new-frame)) + (cons 13 (make-non-key-event 'ns-toggle-toolbar)) + (cons 14 (make-non-key-event 'ns-show-prefs))))) +(ns-setup-special-keys) + ;; Special Nextstep-generated events are converted to function keys. Here ;; are the bindings for them. Note, these keys are actually declared in ;; x-setup-function-keys in common-win. commit be51f13491ddb5eb4f281a79fa7e76ef30147cb1 Author: Daniel Mendler Date: Sun Dec 1 11:43:48 2024 +0100 project-recompile: Autoload and run in project root * lisp/progmodes/project.el (project-recompile): Autoload and use project root as `default-directory' (bug#74631). diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index ed6be453274..d4a1832b234 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -1486,15 +1486,14 @@ If non-nil, it overrides `compilation-buffer-name-function' for compilation-buffer-name-function))) (call-interactively #'compile))) +;;;###autoload (defun project-recompile (&optional edit-command) "Run `recompile' with appropriate buffer." (declare (interactive-only recompile)) (interactive "P") - (let ((compilation-buffer-name-function + (let ((default-directory (project-root (project-current t))) + (compilation-buffer-name-function (or project-compilation-buffer-name-function - ;; Should we error instead? When there's no - ;; project-specific naming, there is no point in using - ;; this command. compilation-buffer-name-function))) (recompile edit-command))) commit 4eea545bbc34adac27fbc7668542df0ec3b25f9f Author: Dmitry Gutov Date: Tue Dec 10 03:40:00 2024 +0200 apropos-library: Don't list generic functions as features * lisp/apropos.el (apropos-library): Remove the separate 'cl-defmethod' case (bug#74727). diff --git a/lisp/apropos.el b/lisp/apropos.el index 0655fecd0e8..760e5be08f9 100644 --- a/lisp/apropos.el +++ b/lisp/apropos.el @@ -731,9 +731,8 @@ the output includes key-bindings of commands." ('require (push (cdr x) requires)) ('provide (push (cdr x) provides)) ('t nil) ; Skip "was an autoload" entries. - ;; FIXME: Print information about each individual method: both - ;; its docstring and specializers (bug#21422). - ('cl-defmethod (push (cadr x) provides)) + ;; FIXME: Print information about each method on generic + ;; functions: both the docstring and specializers (bug#21422). ;; FIXME: Add extension point (bug#72616). (_ (let ((sym (or (cdr-safe x) x))) (and sym (symbolp sym) commit b25fba0ef8f38f95a9e65548f9ebb6c92739857e Author: F. Jason Park Date: Sat Dec 7 16:52:12 2024 -0800 ; Mark failing tests in erc-scenarios-match.el as :unstable * test/lisp/erc/erc-scenarios-match.el (erc-scenarios-match--stamp-both-invisible-fill-static) (erc-scenarios-match--stamp-both-invisible-fill-static--nooffset): Tag as :unstable for a `system-type' of `berkeley-unix'. (Bug#74722) diff --git a/test/lisp/erc/erc-scenarios-match.el b/test/lisp/erc/erc-scenarios-match.el index 8600af800f1..81ac5e4c12a 100644 --- a/test/lisp/erc/erc-scenarios-match.el +++ b/test/lisp/erc/erc-scenarios-match.el @@ -510,8 +510,9 @@ (should-not (eq (field-at-pos (1- (pos-eol))) 'erc-timestamp)) (should-not (next-single-property-change (pos-bol) 'invisible)))))) +;; FIXME explain why these next two fail on FreeBSD 14.2 (Bug#74722). (ert-deftest erc-scenarios-match--stamp-both-invisible-fill-static () - :tags '(:expensive-test) + :tags `(:expensive-test ,@(and (eq system-type 'berkeley-unix) '(:unstable))) (erc-scenarios-match--stamp-both-invisible-fill-static (lambda () @@ -527,7 +528,7 @@ (match-end 0))))))) ; pos-eol (ert-deftest erc-scenarios-match--stamp-both-invisible-fill-static--nooffset () - :tags '(:expensive-test) + :tags `(:expensive-test ,@(and (eq system-type 'berkeley-unix) '(:unstable))) (with-suppressed-warnings ((obsolete erc-legacy-invisible-bounds-p)) (should-not erc-legacy-invisible-bounds-p) commit dc7c38ed9ec85e2e7cbe3c9fcb3b6d5dbb5aa206 Author: F. Jason Park Date: Fri Dec 6 19:09:04 2024 -0800 ; Slightly improve test case for erc-parse-modes * lisp/erc/erc.el (erc--merge-local-modes): Look for a symbol's `erc-module' property before examining its name. * test/lisp/erc/erc-tests.el (erc-parse-modes): Expand case to cover alternating plus and minus mode changes. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index ad279a0ff66..7f753e34d03 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -2519,9 +2519,9 @@ nil." (if old-vars (let ((out (list (reverse new-modes)))) (pcase-dolist (`(,k . ,v) old-vars) - (when (and (string-prefix-p "erc-" (symbol-name k)) - (string-suffix-p "-mode" (symbol-name k)) - (get k 'erc-module)) + (when (and (get k 'erc-module) + (string-prefix-p "erc-" (symbol-name k)) + (string-suffix-p "-mode" (symbol-name k))) (if v (cl-pushnew k (car out)) (setf (car out) (delq k (car out))) diff --git a/test/lisp/erc/erc-tests.el b/test/lisp/erc/erc-tests.el index d77d8588dad..eaff5640aa0 100644 --- a/test/lisp/erc/erc-tests.el +++ b/test/lisp/erc/erc-tests.el @@ -825,8 +825,11 @@ (should (equal (erc-parse-modes "-o bob") '(nil nil (("o" off "bob"))))) (should (equal (erc-parse-modes "+uo bob") '(("u") nil (("o" on "bob"))))) (should (equal (erc-parse-modes "+o-u bob") '(nil ("u") (("o" on "bob"))))) + (should (equal (erc-parse-modes "+uo-tv bob alice") '(("u") ("t") (("o" on "bob") ("v" off "alice"))))) + (should (equal (erc-parse-modes "+u-t+o-v bob alice") + '(("u") ("t") (("o" on "bob") ("v" off "alice"))))) (ert-info ("Modes of type B are always grouped as unary") (should (equal (erc-parse-modes "+k h2") '(nil nil (("k" on "h2"))))) commit d719a8140917e3b1dd6889f064ffb8e8b0621c7d Author: Gerd Möllmann Date: Mon Dec 9 15:08:01 2024 +0100 Support menu separator types in tty menus (bug#74740) * src/xdisp.c (display_tty_menu_item): Display "--" for all menu separator types. diff --git a/src/xdisp.c b/src/xdisp.c index 0fa3c34c314..7b0e2644078 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -27340,6 +27340,17 @@ display_tty_menu_item (const char *item_text, int width, int face_id, display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0, FRAME_COLS (f) - 1, -1); } + else if (menu_separator_name_p (item_text)) + { + /* FIXME: This is only a "good enough for now" implementation of + menu separators as described in the Elisp info manual. We + should probably ignore menu separators when computing the width + of a menu. Secondly, we could draw actual horizontal lines of + different styles on ttys, maybe optionally using Unicode + characters via display table entries. Patches very welcome. */ + display_string ("--", Qnil, Qnil, 0, 0, &it, width, 0, + FRAME_COLS (f) - 1, -1); + } else display_string (item_text, Qnil, Qnil, 0, 0, &it, width, 0, FRAME_COLS (f) - 1, -1); commit b8ee67b6963a913d2842d69686f92f690c78cc50 Author: Gerd Möllmann Date: Mon Dec 9 06:41:09 2024 +0100 ; Add an autoload cookie for native-compile-prune-cache * lisp/emacs-lisp/comp.el (native-compile-prune-cache): Make it autoload. diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index f37bb965ffb..2966ed255ac 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -3739,6 +3739,7 @@ variable \"NATIVE_DISABLED\" is set, only byte compile." (comp--write-bytecode-file eln-file) (setq command-line-args-left (cdr command-line-args-left))))) +;;;###autoload (defun native-compile-prune-cache () "Remove .eln files that aren't applicable to the current Emacs invocation." (interactive) commit cb288fbcd97deeeb993a7a3de97bdbf5b7dced75 Author: Pip Cet Date: Mon Dec 9 12:48:54 2024 +0000 Fix occasional crash in lwlib due to uninitialized data Crash observed on cfarm's cfarm210 machine, which is a Solaris 10 zone on an M3000 server. * lwlib/xlwmenu.c (XlwMenuInitialize): Initialize menu.font. diff --git a/lwlib/ChangeLog.1 b/lwlib/ChangeLog.1 index a033a797387..efec2392ffa 100644 --- a/lwlib/ChangeLog.1 +++ b/lwlib/ChangeLog.1 @@ -1,3 +1,7 @@ +2024-12-09 Pip Cet + + * lwlib/xlwmenu.c (XlwMenuInitialize): Initialize menu.font. + 2015-03-18 Stefan Monnier * xlwmenu.c (pop_up_menu): Remove debugging code. diff --git a/lwlib/xlwmenu.c b/lwlib/xlwmenu.c index 33f3fa27033..1198045fe40 100644 --- a/lwlib/xlwmenu.c +++ b/lwlib/xlwmenu.c @@ -2120,7 +2120,7 @@ XlwMenuInitialize (Widget request, Widget w, ArgList args, Cardinal *num_args) #if defined USE_CAIRO || defined HAVE_XFT if (openXftFont (mw)) - ; + mw->menu.font = NULL; else #endif { commit 6df535788a20c9047d33dd8a0c62258597632647 Author: Jim Porter Date: Sun Dec 8 20:23:46 2024 -0800 Fix usage reporting for Eshell commands * lisp/eshell/esh-cmd.el (eshell-exec-lisp): Call 'elisp-get-fnsym-args-string'; the old function was renamed to this. diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index 7a146944145..eb922b59a31 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -1501,11 +1501,13 @@ case." (when (memq eshell-in-pipeline-p '(nil last)) (eshell-set-exit-info 1)) (let ((msg (error-message-string err))) - (if (and (not form-p) - (string-match "^Wrong number of arguments" msg) - (fboundp 'eldoc-get-fnsym-args-string)) - (let ((func-doc (eldoc-get-fnsym-args-string func-or-form))) - (setq msg (format "usage: %s" func-doc)))) + (unless form-p + (let ((prog-name (string-trim-left (symbol-name func-or-form) + "eshell/"))) + (if (eq (car err) 'wrong-number-of-arguments) + (setq msg (format "%s usage: %s" prog-name + (elisp-get-fnsym-args-string func-or-form))) + (setq msg (format "%s: %s" prog-name msg))))) (funcall errprint msg)) nil))) commit b6c91cdf54168eef260e28a7866486a4d68bfc9e Author: Jim Porter Date: Sun Dec 8 20:21:31 2024 -0800 Return non-zero exit status when Eshell's "which" fails to find a command * lisp/eshell/esh-cmd.el (eshell/which): Set exit status to 1 if we couldn't find any of the commands (bug#74739). diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index c0015745ad5..7a146944145 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -1381,19 +1381,22 @@ have been replaced by constants." (defun eshell/which (command &rest names) "Identify the COMMAND, and where it is located." - (dolist (name (cons command names)) - (condition-case error - (eshell-printn - (catch 'found - (run-hook-wrapped - 'eshell-named-command-hook - (lambda (hook) - (when-let* (((symbolp hook)) - (which-func (get hook 'eshell-which-function)) - (result (funcall which-func command))) - (throw 'found result)))) - (eshell-plain-command--which name))) - (error (eshell-error (format "which: %s\n" (cadr error))))))) + (let (not-found) + (dolist (name (cons command names)) + (condition-case error + (eshell-printn + (catch 'found + (run-hook-wrapped + 'eshell-named-command-hook + (lambda (hook) + (when-let* (((symbolp hook)) + (which-func (get hook 'eshell-which-function)) + (result (funcall which-func command))) + (throw 'found result)))) + (eshell-plain-command--which name))) + (error (eshell-error (format "which: %s\n" (cadr error))) + (setq not-found t)))) + (when not-found (eshell-set-exit-info 1)))) (put 'eshell/which 'eshell-no-numeric-conversions t) commit 1098ae2896f458507c01afd04cb2e242227c6724 Author: Stefan Kangas Date: Mon Dec 9 04:14:47 2024 +0100 ; * etc/symbol-releases.eld: Add and-let*. (Bug#74712) diff --git a/etc/symbol-releases.eld b/etc/symbol-releases.eld index 3febf0a10bb..de1eaad6bd1 100644 --- a/etc/symbol-releases.eld +++ b/etc/symbol-releases.eld @@ -11,6 +11,7 @@ ( ("28.1" fun always) ("26.1" fun when-let*) + ("26.1" fun and-let*) ("26.1" fun if-let*) ("24.4" fun set-transient-map) ("22.1" fun version=) commit 9b4af418ddc3328c8756f3ca21ba25f161c65b65 Author: Stefan Kangas Date: Mon Dec 9 04:01:44 2024 +0100 Make setting tex-dvi-view-command to an sexp obsolete This is more in line with how we generally handle user options for commands to call. Later, we can get rid of the 'eval' call. * lisp/textmodes/tex-mode.el (tex-view): Warn if tex-dvi-view-command is set to an sexp instead of a string; say that this use is obsolete. (tex-dvi-view-command): Change the default value to a string. Update docstring to reflect the above obsoletion. diff --git a/lisp/textmodes/tex-mode.el b/lisp/textmodes/tex-mode.el index 06a45112719..c82e589632e 100644 --- a/lisp/textmodes/tex-mode.el +++ b/lisp/textmodes/tex-mode.el @@ -199,17 +199,17 @@ use." ;;;###autoload (defcustom tex-dvi-view-command - `(cond - ((eq window-system 'x) ,(purecopy "xdvi")) - ((eq window-system 'w32) ,(purecopy "yap")) - (t ,(purecopy "dvi2tty * | cat -s"))) + (cond ((eq window-system 'x) (purecopy "xdvi")) + ((eq window-system 'w32) (purecopy "yap")) + (t (purecopy "dvi2tty * | cat -s"))) "Command used by \\[tex-view] to display a `.dvi' file. -If it is a string, that specifies the command directly. If this string contains an asterisk (`*'), that is replaced by the file name; otherwise, the file name, preceded by a space, is added at the end. -If the value is a form, it is evaluated to get the command to use." - :type '(choice (const nil) string sexp) +For backwards-compatibility, the value can also be a form, in which case +it is evaluated to get the command to use. This is now obsolete, and +will lead to a warning. Set it to a string instead." + :type '(choice (const nil) string) :risky t :group 'tex-view) @@ -2804,6 +2804,7 @@ Runs the shell command defined by `tex-alt-dvi-print-command'." (interactive) (tex-print t)) +(defvar tex-view--warned-once nil) (defun tex-view () "Preview the last `.dvi' file made by running TeX under Emacs. This means, made using \\[tex-region], \\[tex-buffer] or \\[tex-file]. @@ -2816,7 +2817,14 @@ because there is no standard value that would generally work." ;; Restart the TeX shell if necessary. (or (tex-shell-running) (tex-start-shell)) - (let ((tex-dvi-print-command (eval tex-dvi-view-command t))) + (let ((tex-dvi-print-command + (if (stringp tex-dvi-view-command) + tex-dvi-view-command + (unless tex-view--warned-once + (warn (concat "Setting `tex-dvi-view-command' to an S-expression" + " is obsolete since Emacs " "31.1")) + (setq tex-view--warned-once t)) + (eval tex-dvi-view-command t)))) (tex-print))) (defun tex-append (file-name suffix) commit 4960af1c963ada0185dd216c906ef52a6f05edab Author: Michael Albinus Date: Sun Dec 8 18:22:17 2024 +0100 Fix calling processes inside ffap * lisp/ffap.el (ffap--url-file-handler): Handle also `unhandled-file-name-directory'. (Bug#74208) diff --git a/lisp/ffap.el b/lisp/ffap.el index 6a4915fb5a3..180fe408104 100644 --- a/lisp/ffap.el +++ b/lisp/ffap.el @@ -1512,6 +1512,7 @@ which may actually result in an URL rather than a filename." ;; We mainly just want to disable these bits: (substitute-in-file-name (car args)) (expand-file-name (car args)) + (unhandled-file-name-directory temporary-file-directory) (otherwise (apply operation args))))) commit 9a0e26b88616946d2512680859166caa2675b30a Author: Eli Zaretskii Date: Sun Dec 8 14:10:33 2024 +0200 ; * doc/lispref/modes.texi (Parser-based Font Lock): Fix markup. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index 43282c7cd30..4838a4d8ebb 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -4412,10 +4412,11 @@ ignored. @end defun @c FIXME: Cross-ref treesit-font-lock-level to user manual. +@vindex treesit-font-lock-level @defvar treesit-font-lock-feature-list This is a list of lists of feature symbols. Each element of the list is a list that represents a decoration level. -@var{treesit-font-lock-level} controls which levels are +The @code{treesit-font-lock-level} user option controls which levels are activated. Each element of the list is a list of the form @w{@code{(@var{feature} commit b953bcb17047998c9e41cede7c5e5ffec22209b2 Author: Yuan Fu Date: Sat Dec 7 23:18:53 2024 -0800 Allow treesit--font-lock-level-setter to be an alist * lisp/treesit.el (treesit-font-lock-level): Allow the value to be an alist mapping major modes to font lock levels. (treesit--font-lock-level-setter): Rewrite. (treesit--compute-font-lock-level): New function. (treesit-font-lock-recompute-features): Use new function. * doc/lispref/modes.texi (Parser-based Font Lock): Minor fix. diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi index ed7cc141cd5..43282c7cd30 100644 --- a/doc/lispref/modes.texi +++ b/doc/lispref/modes.texi @@ -4415,7 +4415,7 @@ ignored. @defvar treesit-font-lock-feature-list This is a list of lists of feature symbols. Each element of the list is a list that represents a decoration level. -@code{treesit-font-lock-level} controls which levels are +@var{treesit-font-lock-level} controls which levels are activated. Each element of the list is a list of the form @w{@code{(@var{feature} diff --git a/lisp/treesit.el b/lisp/treesit.el index db3a706f016..db8f7a7595d 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -898,29 +898,22 @@ t, nil, append, prepend, keep. See more in (setf (nth 1 new-setting) t) new-setting)) -;; FIXME: Rewrite this in more readable fashion. (defun treesit--font-lock-level-setter (sym val) "Custom setter for `treesit-font-lock-level'. Set the default value of SYM to VAL, recompute fontification features and refontify for every buffer where tree-sitter-based fontification is enabled." (set-default sym val) - (and (treesit-available-p) - (named-let loop ((res nil) - (buffers (buffer-list))) - (if (null buffers) - (mapc (lambda (b) - (with-current-buffer b - (setq-local treesit-font-lock-level val) - (treesit-font-lock-recompute-features) - (treesit-font-lock-fontify-region (point-min) - (point-max)))) - res) - (let ((buffer (car buffers))) - (with-current-buffer buffer - (if treesit-font-lock-settings - (loop (append res (list buffer)) (cdr buffers)) - (loop res (cdr buffers))))))))) + (when (treesit-available-p) + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + ;; FIXME: This doesn't re-run major mode hooks, meaning any + ;; customization done in major mode hooks (e.g., with + ;; `treesit-font-lock-recompute-features') is lost. + (when treesit-font-lock-settings + (treesit-font-lock-recompute-features) + (treesit-font-lock-fontify-region + (point-min) (point-max))))))) (defcustom treesit-font-lock-level 3 "Decoration level to be used by tree-sitter fontifications. @@ -937,6 +930,15 @@ Level 4 adds everything else that can be fontified: delimiters, operators, brackets, punctuation, all functions, properties, variables, etc. +The value of this variable can be either a number representing a level, +or an alist of (MAJOR-MODE . LEVEL), where MAJOR-MODE is major mode +symbols, or t (meaning the default), and LEVEL is the font-lock level +for that mode. For example, + + ((c-ts-mode . 3) (c++-ts-mode . 4) (t . 3)) + +Major mode is checked with `derived-mode-p'. + In addition to the decoration level, individual features can be turned on/off by calling `treesit-font-lock-recompute-features'. Changing the decoration level requires calling @@ -1123,6 +1125,23 @@ name, it is ignored." (defvar treesit--font-lock-verbose nil "If non-nil, print debug messages when fontifying.") +(defun treesit--compute-font-lock-level (level) + "Compute the font-lock level for the current major mode. + +LEVEL should be the value of `treesit-font-lock-level'. Return a number +representing the font-lock level for the current major mode. If there's +no match, return 3." + (if (numberp level) + level + (catch 'found + (dolist (config level) + (let ((mode (car config)) + (num (cdr config))) + (when (derived-mode-p mode) + (throw 'found num)))) + (or (alist-get t level) + 3)))) + (defun treesit-font-lock-recompute-features (&optional add-list remove-list language) "Enable/disable font-lock features. @@ -1147,7 +1166,8 @@ and leave settings for other languages unchanged." (signal 'treesit-font-lock-error (list "ADD-LIST and REMOVE-LIST contain the same feature" intersection))) - (let* ((level treesit-font-lock-level) + (let* ((level (treesit--compute-font-lock-level + treesit-font-lock-level)) (base-features (cl-loop for idx = 0 then (1+ idx) for features in treesit-font-lock-feature-list commit 6f6b641975e4828f96913b29b1476c6323c952d8 Merge: 0ece0e68ee5 4f2a21cc2a3 Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 Merge from origin/emacs-30 4f2a21cc2a3 Don't restrict 'lua-ts-send-file' to 'lua-ts-mode' commit 0ece0e68ee57e893ea2575d9c0fad19d7e17ae0d Merge: 284b6647d21 84fc77f34f0 Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 ; Merge from origin/emacs-30 The following commit was skipped: 84fc77f34f0 Remove unnecessary function call from 'php-ts-mode' commit 284b6647d215e6d0b773f5100b61849d4b80885c Merge: be5218138fc 3cf177442cc Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 Merge from origin/emacs-30 3cf177442cc ; * lisp/help-at-pt.el (display-local-help): Fix last cha... 02c53b9aab0 ; * lisp/help-at-pt.el (display-local-help): Doc fix. 130c2a13dc7 ; * doc/emacs/building.texi (Compilation Mode): Fix last ... df7f02a7954 Add tags to 'compilation-transform-file-match-alist' cust... 7c50e4cc8cc Improve 'compilation-transform-file-match-alist' document... a73d08bb67a Improve 'compilation-hidden-output' docstring d50293b0f10 ; Improve documentation of 'epa-mail-verify' commit be5218138fc760a4216a8badf6b67c2cc1a25fc8 Merge: 66263417b75 c7d9ffcf829 Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 ; Merge from origin/emacs-30 The following commit was skipped: c7d9ffcf829 Improve docstrings of functions for moving to message hea... commit 66263417b754ebf7b588ea8d1dddad584741e363 Merge: 15a4022e051 7b8d12e95de Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 Merge from origin/emacs-30 7b8d12e95de Fix the latest dabbrev-expand test fix commit 15a4022e051dbb9bb245e43b8c7fa292b23e9436 Merge: 3993dcca823 e618d5ae941 Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 ; Merge from origin/emacs-30 The following commit was skipped: e618d5ae941 Fix password prompt in comint (don't merge) commit 3993dcca823753237800dee598386ca6c14746a9 Merge: 69191aeefdb f65de1019dc Author: Eli Zaretskii Date: Sat Dec 7 09:16:18 2024 -0500 Merge from origin/emacs-30 f65de1019dc Fix the version of librsvg API change 43c4a06ffcc ; Fix grammar in Emacs user manual 6bca138d60e Fix latest test for dabbrev-expand commit 69191aeefdb0fec0722dbbe29a72ad2af9053f87 Author: Michael Albinus Date: Sat Dec 7 15:14:00 2024 +0100 * test/lisp/wdired-tests.el (wdired-test-bug34915): Fix for *BSD. (Bug#74721) diff --git a/test/lisp/wdired-tests.el b/test/lisp/wdired-tests.el index 7c7026354b8..30622700939 100644 --- a/test/lisp/wdired-tests.el +++ b/test/lisp/wdired-tests.el @@ -142,7 +142,8 @@ wdired-get-filename before and after editing." (ert-with-temp-directory test-dir (let* ((dired-listing-switches "-Fl") (dired-ls-F-marks-symlinks - (or (eq system-type 'darwin) + (or (and (memq system-type '(berkeley-unix darwin)) + (not (string= insert-directory-program "gls"))) (featurep 'ls-lisp))) (buf (find-file-noselect test-dir)) proc) commit 4f2a21cc2a369341b91bb3657e851bdc75e5e053 Author: john muhl Date: Mon Dec 2 09:20:01 2024 -0600 Don't restrict 'lua-ts-send-file' to 'lua-ts-mode' * lisp/progmodes/lua-ts-mode.el (lua-ts-send-file): Remove restriction on interactive use. Unlike related send-* commands it can be useful to send a file to the Lua interpreter outside of a 'lua-ts-mode' buffer. (Bug#74705) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index d2ac67a9230..9d06517a97d 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -694,7 +694,7 @@ Calls REPORT-FN directly." (defun lua-ts-send-file (file) "Send contents of FILE to the inferior Lua process." - (interactive "f" lua-ts-mode) + (interactive "f") (with-temp-buffer (insert-file-contents-literally file) (lua-ts-send-region (point-min) (point-max)))) commit 84fc77f34f0c942860c2fd4d3080504e9509dd2b Author: Vincenzo Pupillo Date: Wed Dec 4 15:06:54 2024 +0100 Remove unnecessary function call from 'php-ts-mode' * lisp/progmodes/php-ts-mode.el (php-ts-mode): Remove unnecessary function call 'treesit-font-lock-recompute-features'. (Bug#74688) (cherry picked from commit c87c5b95e1309b59b6cb07d07a20234a74a73f35) diff --git a/lisp/progmodes/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index 6052c79ccf3..975d6c89be5 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el @@ -1557,7 +1557,6 @@ Depends on `c-ts-common-comment-setup'." ;; should be the last one (setq-local treesit-primary-parser (treesit-parser-create 'php)) - (treesit-font-lock-recompute-features) (treesit-major-mode-setup) (add-hook 'flymake-diagnostic-functions #'php-ts-mode-flymake-php nil 'local))) commit c87c5b95e1309b59b6cb07d07a20234a74a73f35 Author: Vincenzo Pupillo Date: Wed Dec 4 15:06:54 2024 +0100 Remove unnecessary function call from 'php-ts-mode' * lisp/progmodes/php-ts-mode.el (php-ts-mode): Remove unnecessary function call 'treesit-font-lock-recompute-features'. (Bug#74688) diff --git a/lisp/progmodes/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index b6fe17f7d41..10f290d24ea 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el @@ -1557,7 +1557,6 @@ Depends on `c-ts-common-comment-setup'." ;; should be the last one (setq-local treesit-primary-parser (treesit-parser-create 'php)) - (treesit-font-lock-recompute-features) (treesit-major-mode-setup) (add-hook 'flymake-diagnostic-functions #'php-ts-mode-flymake-php nil 'local))) commit e7fdf6b68ce7aeba9f3b503a1c5b8bf1a61800c1 Author: Daniel Mendler Date: Wed Mar 1 19:27:38 2023 +0100 progmodes/js: Use 'completing-read' instead of 'ido-completing-read' * lisp/progmodes/js.el (js--read-symbol): Don't use Ido. (Bug#74615) diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index 57889338650..dbf721e8d0f 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -58,11 +58,8 @@ (eval-when-compile (require 'cl-lib) - (require 'ido) (require 'rx)) -(defvar ido-cur-list) -(declare-function ido-mode "ido" (&optional arg)) (declare-function treesit-parser-create "treesit.c") (declare-function treesit-induce-sparse-tree "treesit.c") (declare-function treesit-search-subtree "treesit.c") @@ -3288,11 +3285,7 @@ one from `js--get-all-known-symbols', using prompt PROMPT and initial input INITIAL-INPUT. Return a cons of (SYMBOL-NAME . LOCATION), where SYMBOL-NAME is a string and LOCATION is a marker." - (unless ido-mode - (ido-mode 1) - (ido-mode -1)) - - (let ((choice (ido-completing-read + (let ((choice (completing-read prompt (cl-loop for key being the hash-keys of symbols-table collect key) commit 8c3e10b5756a72d5d17f8166c0241f933305abe9 Author: Eli Zaretskii Date: Sat Dec 7 14:43:34 2024 +0200 ; Fix last change * lisp/progmodes/flymake-cc.el (flymake-cc-command): Fix doc string and customization tags. (Bug#74378) diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el index 79557c9fbe4..0cf6b68012c 100644 --- a/lisp/progmodes/flymake-cc.el +++ b/lisp/progmodes/flymake-cc.el @@ -30,16 +30,17 @@ (defcustom flymake-cc-command #'flymake-cc-use-special-make-target "Command used by the `flymake-cc' backend. -A list of strings, or a function that produces one such list when called -with no arguments in the buffer where the variable `flymake-mode' is -active. +The value should be a list of strings, or a function that produces +such a list when called with no arguments in the buffer where `flymake-mode' +is active. The list of strings should be suitable for the `:command' +keyword of `make-process'. The command should invoke a GNU-style compiler that checks the syntax of a (Obj)C(++) program passed to it via its standard input and prints the result on its standard output." :type '(choice - (function :tag "Function") - (repeat :tag "Command(s)" string)) + (function :tag "Function to produce compilation command") + (repeat :tag "Compilation command and its options" string)) :version "27.1" :group 'flymake-cc) commit bf976ca7436b620ac33f00fa12317038ab387e00 Author: Pengji Zhang Date: Sat Nov 16 11:26:41 2024 +0800 Allow lambdas for 'flymake-cc-command' * lisp/progmodes/flymake-cc.el (flymake-cc-command): Use customization type 'function' instead of 'symbol' to allow other callable objects in addition to named functions, and update the doc string accordingly. (flymake-cc): Use 'functionp' to check if 'flymake-cc-command' is callable. (Bug#74378) diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el index 60e7da5d617..79557c9fbe4 100644 --- a/lisp/progmodes/flymake-cc.el +++ b/lisp/progmodes/flymake-cc.el @@ -28,17 +28,17 @@ (require 'cl-lib) -(defcustom flymake-cc-command 'flymake-cc-use-special-make-target +(defcustom flymake-cc-command #'flymake-cc-use-special-make-target "Command used by the `flymake-cc' backend. -A list of strings, or a symbol naming a function that produces one -such list when called with no arguments in the buffer where the -variable `flymake-mode' is active. +A list of strings, or a function that produces one such list when called +with no arguments in the buffer where the variable `flymake-mode' is +active. The command should invoke a GNU-style compiler that checks the syntax of a (Obj)C(++) program passed to it via its standard input and prints the result on its standard output." :type '(choice - (symbol :tag "Function") + (function :tag "Function") (repeat :tag "Command(s)" string)) :version "27.1" :group 'flymake-cc) @@ -128,7 +128,7 @@ REPORT-FN is Flymake's callback." (make-process :name "gcc-flymake" :buffer (generate-new-buffer "*gcc-flymake*") - :command (if (symbolp flymake-cc-command) + :command (if (functionp flymake-cc-command) (funcall flymake-cc-command) flymake-cc-command) :noquery t :connection-type 'pipe commit d84c5c24b58b124f79b2a61e58e46c501d8ec52a Author: Eli Zaretskii Date: Sat Dec 7 06:50:27 2024 -0500 ; * lisp/dired-aux.el (shell-command-guess-open): Fix :type (bug#74720). diff --git a/lisp/dired-aux.el b/lisp/dired-aux.el index 7fe67eed1e0..3390f9b83d1 100644 --- a/lisp/dired-aux.el +++ b/lisp/dired-aux.el @@ -1440,7 +1440,7 @@ This excludes `dired-guess-shell-alist-user' and ((executable-find "run-mailcap") "run-mailcap")) "A shell command to open a file externally." - :type 'string + :type '(choice (const :tag "None" nil) string) :group 'dired :version "30.1") commit d185d901905e11cf9120f5cea680ae04eae2809f Author: Eli Zaretskii Date: Sat Dec 7 11:04:44 2024 +0200 Update info-lookup's support for 'latex-mode' * lisp/info-look.el (latex-mode): Update URLs of LaTeX manuals and the corresponding names of the index nodes. diff --git a/lisp/info-look.el b/lisp/info-look.el index b3db9bfdecc..d51a59f7ac6 100644 --- a/lisp/info-look.el +++ b/lisp/info-look.el @@ -995,9 +995,11 @@ Return nil if there is nothing appropriate in the buffer near point." :mode 'latex-mode :regexp "\\\\\\([a-zA-Z]+\\|[^a-zA-Z]\\)" :doc-spec `((,(if (Info-find-file "latex2e" t) - ;; From http://home.gna.org/latexrefman - "(latex2e)Command Index" - "(latex)Command Index") + ;; From CTAN's https://ctan.org/pkg/latex2e-help-texinfo + ;; and https://puszcza.gnu.org.ua/projects/latexrefman/ + "(latex2e)Index" + ;; From https://savannah.nongnu.org/projects/latex-manual/ + "(latex-manual)Command Index") ;; \frac{NUM}{DEN} etc can have more than one {xx} argument. ;; \sqrt[ROOT]{num} and others can have square brackets. nil "[`'‘]" "\\({[^}]*}|\\[[^]]*\\]\\)*['’]"))) commit 9ddec89e422d0dd6e9069731b8f2dd2c90aa5607 Author: Michael Albinus Date: Fri Dec 6 11:56:05 2024 +0100 Better handling of "%" in Tramp user or host names * lisp/net/tramp.el (tramp-format-spec): New defun. (tramp-dissect-file-name, tramp-compute-multi-hops) (tramp-expand-args): * lisp/net/tramp-cmds.el (tramp-default-rename-file): Use it. diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 3a66030c9d0..d38250d4e09 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -368,7 +368,7 @@ function returns nil" (when (string-match-p (or (eval (car item) t) "") string) (setq tdra nil result - (format-spec + (tramp-format-spec (cdr item) (format-spec-make ?m method ?u user ?h host))))) result))) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 12ad14e0900..c23eed0bc1b 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1826,14 +1826,9 @@ default values are used." user (tramp-find-user method user host) host (tramp-find-host method user host)) (when hop - ;; Replace placeholders. The hop could contain "%" - ;; which is not intended as format character, for - ;; example in USER%DOMAIN or POD%NAMESPACE. - (setq hop - (replace-regexp-in-string - (rx "%" (group (= 2 alnum))) "%%\\1" hop) - hop - (format-spec hop (format-spec-make ?h host ?u user)))))) + ;; Replace placeholders. + (setq + hop (tramp-format-spec hop (format-spec-make ?h host ?u user)))))) ;; Return result. (prog1 @@ -2233,6 +2228,14 @@ letter into the file name. This function removes it." (rx (regexp tramp-volume-letter-regexp) "/") "/" result)) (if quoted (file-name-quote result 'top) result)))) +(defun tramp-format-spec (format specification) + "Implement `format-spec' in Tramp. +FORMAT could contain \"%\" which is not intended as format character, +for example in USER%DOMAIN or POD%NAMESPACE." + (format-spec + (replace-regexp-in-string (rx "%" (group (= 2 alnum))) "%%\\1" format) + specification)) + ;;; Config Manipulation Functions: (defconst tramp-dns-sd-service-regexp @@ -5033,7 +5036,7 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.") (setq choices nil) ;; Replace placeholders. (setq proxy - (format-spec + (tramp-format-spec proxy (format-spec-make ?u (or (tramp-file-name-user (car target-alist)) "") @@ -5108,7 +5111,7 @@ a connection-local variable." (flatten-tree (mapcar (lambda (x) - (setq x (mapcar (lambda (y) (format-spec y spec)) x)) + (setq x (mapcar (lambda (y) (tramp-format-spec y spec)) x)) (unless (member "" x) x)) args)))) commit 61d06762975fb203ae06a57d30397d699164ebc1 Author: Juri Linkov Date: Thu Dec 5 20:15:12 2024 +0200 * lisp/emacs-lisp/lisp-mode.el (lisp-fdefs): Fix font-lock (bug#74307). Move '(not "\\")' inside the group to not exclude the last character for "\\<>" and similar constructs. diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el index 99980a44ddf..4b89eb91387 100644 --- a/lisp/emacs-lisp/lisp-mode.el +++ b/lisp/emacs-lisp/lisp-mode.el @@ -491,16 +491,16 @@ This will generate compile-time constants from BINDINGS." ;; Words inside \\[], \\<>, \\{} or \\`' tend to be for ;; `substitute-command-keys'. (,(rx "\\\\" (or (seq "[" - (group-n 1 lisp-mode-symbol) (not "\\") "]") + (group-n 1 (seq lisp-mode-symbol (not "\\"))) "]") (seq "`" (group-n 1 ;; allow multiple words, e.g. "C-x a" lisp-mode-symbol (* " " lisp-mode-symbol)) "'"))) (1 font-lock-constant-face prepend)) (,(rx "\\\\" (or (seq "<" - (group-n 1 lisp-mode-symbol) (not "\\") ">") + (group-n 1 (seq lisp-mode-symbol (not "\\"))) ">") (seq "{" - (group-n 1 lisp-mode-symbol) (not "\\") "}"))) + (group-n 1 (seq lisp-mode-symbol (not "\\"))) "}"))) (1 font-lock-variable-name-face prepend)) ;; Ineffective backslashes (typically in need of doubling). ("\\(\\\\\\)\\([^\"\\]\\)" commit 3cf177442ccd08f7b92b3e08c41899ba34699355 Author: Robert Pluim Date: Thu Dec 5 11:19:41 2024 +0100 ; * lisp/help-at-pt.el (display-local-help): Fix last change. diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el index dcad09ef6ea..1ad353ee655 100644 --- a/lisp/help-at-pt.el +++ b/lisp/help-at-pt.el @@ -95,8 +95,8 @@ is displayed instead. The string is passed through `substitute-command-keys' before it is displayed. -If INHIBIT-WARNING is non-nil, this prevents display of the warning -message in case there is no help properties at point. +If INHIBIT-WARNING is non-nil, do not display a warning message when +there is no help property at point. If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and there's a button/widget at point, pop up a buffer describing that commit ed9eaaa9964f46ef5f9a9c084a1cb8f1ae1926a3 Author: Yuan Fu Date: Mon Dec 2 20:47:38 2024 -0800 Validate font-lock rules when setting up tree-sitter major mode When tree-sitter grammar make breaking changes, major modes breaks completely: no highlighting is shown. This new function will run in treesit-major-mode-setup, validate each font-lock features, and disable the ones that are not compatible with the new grammar, so that the rest of the features still work. It also displays a warning explaining the situation, which looks like this: Warning (treesit-font-lock-rules-mismatch): Emacs cannot compile every font-lock rules because a mismatch between the grammar and the rules. This is most likely due to a mismatch between the font-lock rules defined by the major mode and the tree-sitter grammar. This error can be fixed by either downgrading the grammar (tree-sitter-c) on your system, or upgrading the major mode package. The following are the temporarily disabled features: - `preprocessor' for c. * lisp/treesit.el (treesit-validate-font-lock-rules): New function. (treesit-major-mode-setup): Validate font-lock rules. diff --git a/lisp/treesit.el b/lisp/treesit.el index 6bebb31ee18..db3a706f016 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1214,6 +1214,48 @@ docstring of `treesit-font-lock-rules' for what is a feature." (append rules (nthcdr feature-idx treesit-font-lock-settings))))))) +(defun treesit-validate-font-lock-rules (settings) + "Validate font-lock rules in SETTINGS before major mode starts. + +If the tree-sitter grammar currently installed on the system is +incompatible with the major mode's font-lock rules, this procedure will +detect the problematic rule, disable it temporarily, and notify the +user." + (let ((faulty-features ())) + (dolist (setting settings) + (let* ((query (treesit-font-lock-setting-query setting)) + (lang (treesit-query-language query)) + (enabled (treesit-font-lock-setting-enable setting))) + (when (and enabled + (condition-case nil + (progn + (treesit-query-compile lang query 'eager) + nil) + (treesit-query-error t))) + (push (cons (treesit-font-lock-setting-feature setting) + lang) + faulty-features)))) + (when faulty-features + (treesit-font-lock-recompute-features + nil (mapcar #'car faulty-features)) + (let* ((languages + (string-join + (delete-dups (mapcar (lambda (feat) + (format "tree-sitter-%s" (cdr feat))) + faulty-features)) + ", ")) + (features (string-join + (mapcar + (lambda (feat) + (format "- `%s' for %s" + (car feat) (cdr feat))) + faulty-features) + ",\n"))) + (display-warning + 'treesit-font-lock-rules-mismatch + (format "Emacs cannot compile every font-lock rules because a mismatch between the grammar and the rules. This is most likely due to a mismatch between the font-lock rules defined by the major mode and the tree-sitter grammar.\n\nThis error can be fixed by either downgrading the grammar (%s) on your system, or upgrading the major mode package. The following are the temporarily disabled features:\n\n%s." + languages features)))))) + (defun treesit-fontify-with-override (start end face override &optional bound-start bound-end) "Apply FACE to the region between START and END. @@ -3142,7 +3184,8 @@ before calling this function." (add-hook 'pre-redisplay-functions #'treesit--pre-redisplay 0 t) (when treesit-primary-parser (treesit-parser-add-notifier - treesit-primary-parser #'treesit--font-lock-mark-ranges-to-fontify))) + treesit-primary-parser #'treesit--font-lock-mark-ranges-to-fontify)) + (treesit-validate-font-lock-rules treesit-font-lock-settings)) ;; Syntax (add-hook 'syntax-propertize-extend-region-functions #'treesit--pre-syntax-ppss 0 t) commit 4ecd1639b19345786020c0f7a5f3672129dae466 Author: Yuan Fu Date: Mon Dec 2 20:14:55 2024 -0800 Make treesit-query-compile compile compiled-query eagerly * src/treesit.c (treesit_ensure_query_compiled_signal): Extrat out into a function. (Ftreesit_query_compile): If EAGER is non-nil and QUERY is a lazily compiled query, compile it eagerily. diff --git a/src/treesit.c b/src/treesit.c index 2372944e166..28c94f307c0 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -1516,6 +1516,20 @@ treesit_ensure_query_compiled (Lisp_Object query, Lisp_Object *signal_symbol, return treesit_query; } +/* Bsically treesit_ensure_query_compiled but can signal. */ +static +void treesit_ensure_query_compiled_signal (Lisp_Object lisp_query) +{ + Lisp_Object signal_symbol = Qnil; + Lisp_Object signal_data = Qnil; + TSQuery *treesit_query = treesit_ensure_query_compiled (lisp_query, + &signal_symbol, + &signal_data); + + if (treesit_query == NULL) + xsignal (signal_symbol, signal_data); +} + /* Resolve language symbol LANG according to treesit-language-remap-alist. */ static @@ -3051,6 +3065,8 @@ DEFUN ("treesit-query-compile", doc: /* Compile QUERY to a compiled query. Querying with a compiled query is much faster than an uncompiled one. +So it's a good idea to use compiled query in tight loops, etc. + LANGUAGE is the language this query is for. If EAGER is non-nil, immediately load LANGUAGE and compile the query. @@ -3064,11 +3080,17 @@ You can use `treesit-query-validate' to validate and debug a query. */) if (NILP (Ftreesit_query_p (query))) wrong_type_argument (Qtreesit_query_p, query); CHECK_SYMBOL (language); - if (TS_COMPILED_QUERY_P (query)) - return query; treesit_initialize (); + if (TS_COMPILED_QUERY_P (query)) + { + if (NILP (eager)) + return query; + treesit_ensure_query_compiled_signal (query); + return query; + } + Lisp_Object lisp_query = make_treesit_query (query, language); /* Maybe actually compile. */ @@ -3076,15 +3098,7 @@ You can use `treesit-query-validate' to validate and debug a query. */) return lisp_query; else { - Lisp_Object signal_symbol = Qnil; - Lisp_Object signal_data = Qnil; - TSQuery *treesit_query = treesit_ensure_query_compiled (lisp_query, - &signal_symbol, - &signal_data); - - if (treesit_query == NULL) - xsignal (signal_symbol, signal_data); - + treesit_ensure_query_compiled_signal (lisp_query); return lisp_query; } } commit 5d535334f30b874ebb8e2c286c1e059d86ccd41f Author: Yuan Fu Date: Mon Dec 2 19:39:10 2024 -0800 ; Use cpp instead of c++ for c-ts-mode--simple-indent-rules * lisp/progmodes/c-ts-mode.el (c-ts-mode--simple-indent-rules): Use cpp to be more inline with other functions in c-ts-mode.el. diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 710160ea472..dec9411b87c 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -441,7 +441,7 @@ NODE and PARENT are the same as other indent rules." "Return the indent rules for MODE and STYLE. The returned value can be set to `treesit-simple-indent-rules'. -MODE can be `c' or `c++'. STYLE can be `gnu', `k&r', `linux', `bsd'." +MODE can be `c' or `cpp'. STYLE can be `gnu', `k&r', `linux', `bsd'." (let ((rules `((c-ts-mode--for-each-tail-body-matcher prev-line c-ts-mode-indent-offset) @@ -513,7 +513,7 @@ MODE can be `c' or `c++'. STYLE can be `gnu', `k&r', `linux', `bsd'." ,@rules)))) (pcase mode ('c `((c . ,rules))) - ('c++ `((cpp . ,rules)))))) + ('cpp `((cpp . ,rules)))))) (defun c-ts-mode--parenthesized-expression-indent-rule (_node parent &rest _) "Indent rule that indents aprenthesized expression. @@ -1451,7 +1451,7 @@ recommended to enable `electric-pair-mode' with this mode." ;; Indent. (setq-local treesit-simple-indent-rules (c-ts-mode--simple-indent-rules - 'c++ c-ts-mode-indent-style)) + 'cpp c-ts-mode-indent-style)) ;; Font-lock. (setq-local treesit-font-lock-settings commit 10b4d3045e1b856009c5ac1e1a1ca257f2d4493f Author: Yuan Fu Date: Mon Dec 2 17:23:08 2024 -0800 Make tree-sitter-explorer support selecting local parser Now treesit-explore-mode will prompt the user to select a parser to explore, rather than a language. It'll also include the local parsers at point for selection. * lisp/treesit.el (treesit--explorer-language): Change to treesit--explorer-parser. (treesit--explorer--nodes-to-highlight): (treesit--explorer-refresh): Change to use parser. (treesit--explorer-generate-parser-alist): New function. (treesit-explorer-switch-parser): New command. (treesit-explore-mode): Use switch-parser to setup. * doc/lispref/parsing.texi (Language Grammar): Mention treesit-explorer-switch-parser. diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi index 5ef29f558ef..7fbb8e61ce1 100644 --- a/doc/lispref/parsing.texi +++ b/doc/lispref/parsing.texi @@ -240,12 +240,15 @@ which displays the syntax tree of the source in the current buffer in real time. Emacs also comes with an ``inspect mode'', which displays information of the nodes at point in the mode-line. +@findex treesit-explorer-switch-parser @deffn Command treesit-explore This command pops up a window displaying the syntax tree of the source in the current buffer. Selecting text in the source buffer highlights the corresponding nodes in the syntax tree display. Clicking on nodes in the syntax tree highlights the corresponding text in the source buffer. + +To switch to another parser, use @code{treesit-explorer-switch-parser}. @end deffn @deffn Command treesit-inspect-mode diff --git a/lisp/treesit.el b/lisp/treesit.el index 2acb46ab105..6bebb31ee18 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -3347,7 +3347,7 @@ to the offending pattern and highlight the pattern." (defvar-local treesit--explorer-source-buffer nil "Source buffer corresponding to the playground buffer.") -(defvar-local treesit--explorer-language nil +(defvar-local treesit--explorer-parser nil "The language used in the playground.") (defvar-local treesit--explorer-refresh-timer nil @@ -3361,8 +3361,8 @@ to the offending pattern and highlight the pattern." (defvar treesit-explore-mode) -(defun treesit--explorer--nodes-to-highlight (language) - "Return nodes for LANGUAGE covered in region. +(defun treesit--explorer--nodes-to-highlight (parser) + "Return nodes for PARSER covered in region. This function tries to return the largest node possible. If the region covers exactly one node, that node is returned (in a list). If the region covers more than one node, two nodes are @@ -3370,7 +3370,7 @@ returned: the very first one in the region and the very last one in the region." (let* ((beg (region-beginning)) (end (region-end)) - (node (treesit-node-on beg end language)) + (node (treesit-node-on beg end parser)) (node (or (treesit-parent-while node (lambda (n) @@ -3394,7 +3394,7 @@ in the region." (when (and treesit-explore-mode (buffer-live-p treesit--explorer-buffer)) (let* ((root (treesit-node-on - (window-start) (window-end) treesit--explorer-language)) + (window-start) (window-end) treesit--explorer-parser)) ;; Only highlight the current top-level construct. ;; Highlighting the whole buffer is slow and unnecessary. ;; But if the buffer is small (ie, used in playground @@ -3411,7 +3411,7 @@ in the region." (nodes-hl (when (region-active-p) (treesit--explorer--nodes-to-highlight - treesit--explorer-language))) + treesit--explorer-parser))) ;; If we didn't edit the buffer nor change the top-level ;; node, don't redraw the whole syntax tree. (highlight-only (treesit-node-eq @@ -3589,11 +3589,56 @@ leaves point at the end of the last line of NODE." (when (buffer-live-p treesit--explorer-buffer) (kill-buffer treesit--explorer-buffer))) +(defun treesit--explorer-generate-parser-alist () + "Return an alist of (PARSER-NAME . PARSER) for relevant parsers. +Relevant parsers include all global parsers and local parsers that +covers point. PARSER-NAME are unique." + (let* ((local-parsers (treesit-parser-list nil nil 'embedded)) + (local-parsers-at-point + (treesit-local-parsers-at (point))) + res) + (dolist (parser (treesit-parser-list nil nil t)) + ;; Exclude local parsers that doesn't cover point. + (when (or (memq parser local-parsers-at-point) + (not (memq parser local-parsers))) + (push (cons (concat (format "%s" parser) + (if (treesit-parser-tag parser) + (format " tag=%s" + (treesit-parser-tag + parser)) + "") + (if (memq parser + local-parsers-at-point) + " (local)" + "") + (propertize (format " %s" (gensym)) + 'invisible t)) + parser) + res))) + (nreverse res))) + (define-derived-mode treesit--explorer-tree-mode special-mode "TS Explorer" "Mode for displaying syntax trees for `treesit-explore-mode'." nil) +(defun treesit-explorer-switch-parser (parser) + "Switch explorer to use PARSER." + (interactive + (list (let* ((parser-alist + (treesit--explorer-generate-parser-alist)) + (parser-name (completing-read + "Parser: " (mapcar #'car parser-alist)))) + (alist-get parser-name parser-alist + nil nil #'equal)))) + (unless treesit-explore-mode + (user-error "Not in `treesit-explore-mode'")) + (setq-local treesit--explorer-parser parser) + (display-buffer treesit--explorer-buffer + (cons nil '((inhibit-same-window . t)))) + (setq-local treesit--explorer-last-node nil) + (treesit--explorer-refresh)) + (define-minor-mode treesit-explore-mode "Enable exploring the current buffer's syntax tree. Pops up a window showing the syntax tree of the source in the @@ -3602,40 +3647,28 @@ the text in the active region is highlighted in the explorer window." :lighter " TSexplore" (if treesit-explore-mode - (let ((language - (intern (completing-read - "Language: " - (cl-remove-duplicates - (mapcar #'treesit-parser-language - (treesit-parser-list nil nil t))))))) - (if (not (treesit-language-available-p language)) - (user-error "Cannot find tree-sitter grammar for %s: %s" - language (cdr (treesit-language-available-p - language t))) - ;; Create explorer buffer. - (unless (buffer-live-p treesit--explorer-buffer) - (setq-local treesit--explorer-buffer - (get-buffer-create - (format "*tree-sitter explorer for %s*" - (buffer-name)))) - (setq-local treesit--explorer-language language) - (with-current-buffer treesit--explorer-buffer - (treesit--explorer-tree-mode))) - (display-buffer treesit--explorer-buffer - (cons nil '((inhibit-same-window . t)))) - (setq-local treesit--explorer-last-node nil) - (treesit--explorer-refresh) - ;; Set up variables and hooks. - (add-hook 'post-command-hook - #'treesit--explorer-post-command 0 t) - (add-hook 'kill-buffer-hook - #'treesit--explorer-kill-explorer-buffer 0 t) - ;; Tell `desktop-save' to not save explorer buffers. - (when (boundp 'desktop-modes-not-to-save) - (unless (memq 'treesit--explorer-tree-mode - desktop-modes-not-to-save) - (push 'treesit--explorer-tree-mode - desktop-modes-not-to-save))))) + (progn + ;; Create explorer buffer. + (unless (buffer-live-p treesit--explorer-buffer) + (setq-local treesit--explorer-buffer + (get-buffer-create + (format "*tree-sitter explorer for %s*" + (buffer-name)))) + (with-current-buffer treesit--explorer-buffer + (treesit--explorer-tree-mode))) + ;; Select parser. + (call-interactively #'treesit-explorer-switch-parser) + ;; Set up variables and hooks. + (add-hook 'post-command-hook + #'treesit--explorer-post-command 0 t) + (add-hook 'kill-buffer-hook + #'treesit--explorer-kill-explorer-buffer 0 t) + ;; Tell `desktop-save' to not save explorer buffers. + (when (boundp 'desktop-modes-not-to-save) + (unless (memq 'treesit--explorer-tree-mode + desktop-modes-not-to-save) + (push 'treesit--explorer-tree-mode + desktop-modes-not-to-save)))) ;; Turn off explore mode. (remove-hook 'post-command-hook #'treesit--explorer-post-command t) commit 25b4bf7fcd75564f23b2e60e29e8ff7354186371 Author: Juri Linkov Date: Wed Dec 4 20:38:41 2024 +0200 * lisp/tab-line.el (tab-line-tabs-fixed-window-buffers): More optimizations. Use :size arg of 'make-hash-table' as a hint how many buffers the table will have. Add ':in-place t' to 'sort'. diff --git a/lisp/tab-line.el b/lisp/tab-line.el index 3c83a02739a..3bf42431ac0 100644 --- a/lisp/tab-line.el +++ b/lisp/tab-line.el @@ -555,12 +555,15 @@ This means that switching to a buffer previously shown in the same window will keep the same order of tabs that was before switching. And newly displayed buffers are added to the end of the tab line." (let* ((old-buffers (window-parameter nil 'tab-line-buffers)) - (buffer-positions (let ((index-table (make-hash-table :test 'eq))) + (buffer-positions (let ((index-table (make-hash-table + :size (length old-buffers) + :test #'eq))) (seq-do-indexed (lambda (buf idx) (puthash buf idx index-table)) old-buffers) index-table)) (new-buffers (sort (tab-line-tabs-window-buffers) + :in-place t :key (lambda (buffer) (gethash buffer buffer-positions most-positive-fixnum))))) commit 02c53b9aab0f255e7fac39660febbbbfbc59ba25 Author: Eli Zaretskii Date: Wed Dec 4 19:51:31 2024 +0200 ; * lisp/help-at-pt.el (display-local-help): Doc fix. diff --git a/lisp/help-at-pt.el b/lisp/help-at-pt.el index 95d0fafc544..dcad09ef6ea 100644 --- a/lisp/help-at-pt.el +++ b/lisp/help-at-pt.el @@ -86,20 +86,20 @@ If this produces no string either, return nil." ;;;###autoload (defun display-local-help (&optional inhibit-warning describe-button) - "Display local help in the echo area. -This command, by default, displays a short help message, namely -the string produced by the `kbd-help' property at point. If -`kbd-help' does not produce a string, but the `help-echo' -property does, then that string is printed instead. + "Display in the echo area `kbd-help' or `help-echo' text at point. +This command displays the help message which is the string produced +by the `kbd-help' property at point. If `kbd-help' at point does not +produce a string, but the `help-echo' property does, then that string +is displayed instead. The string is passed through `substitute-command-keys' before it is displayed. -If INHIBIT-WARNING is non-nil, this prevents display of a message -in case there is no help. +If INHIBIT-WARNING is non-nil, this prevents display of the warning +message in case there is no help properties at point. If DESCRIBE-BUTTON in non-nil (interactively, the prefix arg), and -there's a button/widget at point, pop a buffer describing that +there's a button/widget at point, pop up a buffer describing that button/widget instead." (interactive (list nil current-prefix-arg)) (let ((help (help-at-pt-kbd-string))) commit 130c2a13dc72fca1677a986d3131398e908e58df Author: Eli Zaretskii Date: Wed Dec 4 18:21:19 2024 +0200 ; * doc/emacs/building.texi (Compilation Mode): Fix last change. diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 3a3dd1d4461..bebf410f919 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -316,7 +316,8 @@ to parse output from a @code{grep} command (@pxref{Grep Searching}). Sometimes @code{compilation-error-regexp-alist} doesn't correctly determine the filename that is the source of the error. Use user option @code{compilation-transform-file-match-alist} to make any necessary -adjustments, such as adding or changing a directory component. +adjustments, such as adding or changing a directory component, or even +considering certain compiler messages not error messages at all. @findex compilation-next-error @findex compilation-previous-error commit df7f02a7954c652896dcaae590caf9dc0c4dc6a1 Author: Robert Pluim Date: Wed Dec 4 17:00:16 2024 +0100 Add tags to 'compilation-transform-file-match-alist' custom type * lisp/progmodes/compile.el (compilation-filter-start): Add some more meaningful tags, and switch to using 'radio' instead of 'choice'. diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index ee7fc6aaecb..241b29c65b0 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -77,8 +77,10 @@ an entry matching \"\\\\=`\" and a replacement regexp of \"bar/\", i.e.: Similarly, to remove a prefix \"bar/\", use: (\"\\\\=`bar/\" \"\")" - :type '(repeat (list regexp (choice (const :tag "No replacement" nil) - string))) + :type '(repeat (list (regexp :tag "Filename that matches") + (radio :tag "Action" + (const :tag "Do not consider as error" nil) + (string :tag "Replace matched filename with")))) :version "27.1") (defvar compilation-filter-hook nil commit 7c50e4cc8cc19ad1ab10121ece894409a72a8af9 Author: Robert Pluim Date: Tue Dec 3 15:20:04 2024 +0100 Improve 'compilation-transform-file-match-alist' documentation * doc/emacs/building.texi (Compilation Mode): Document 'compilation-transform-file-match-alist'. * lisp/progmodes/compile.el (compilation-transform-file-match-alist): Expand docstring and add some examples. diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index bb03d8cf325..3a3dd1d4461 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -310,6 +310,14 @@ error message formats and tells Emacs how to extract the locus from each. A similar variable, @code{grep-regexp-alist}, tells Emacs how to parse output from a @code{grep} command (@pxref{Grep Searching}). +@vindex compilation-transform-file-match-alist +@cindex compilation transform file +@cindex compilation find file + Sometimes @code{compilation-error-regexp-alist} doesn't correctly +determine the filename that is the source of the error. Use user option +@code{compilation-transform-file-match-alist} to make any necessary +adjustments, such as adding or changing a directory component. + @findex compilation-next-error @findex compilation-previous-error @findex compilation-next-file diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index 95dce7a430f..ee7fc6aaecb 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -62,9 +62,21 @@ If nil, use Emacs default." (defcustom compilation-transform-file-match-alist '(("/bin/[a-z]*sh\\'" nil)) "Alist of regexp/replacements to alter file names in compilation errors. -If the replacement is nil, the file will not be considered an -error after all. If not nil, it should be a regexp replacement -string." +If the replacement is nil, the file will not be considered an error +after all. If not nil, it should be a regexp replacement string. + +When a replacement regexp is specified, the value of the file name used +to locate the error is changed, but the compilation buffer still +displays the original value. + +For example, to prepend a subdirectory \"bar/\" to all file names, add +an entry matching \"\\\\=`\" and a replacement regexp of \"bar/\", i.e.: + + (\"\\\\=`\" \"bar/\") + +Similarly, to remove a prefix \"bar/\", use: + + (\"\\\\=`bar/\" \"\")" :type '(repeat (list regexp (choice (const :tag "No replacement" nil) string))) :version "27.1") commit a73d08bb67a3562da42ea929df01eb1fb0c17b99 Author: Robert Pluim Date: Mon Dec 2 19:27:48 2024 +0100 Improve 'compilation-hidden-output' docstring * lisp/progmodes/compile.el (compilation-hidden-output): Escape the newline so the example value is more suitable for copying. diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index d2e74aa44a6..95dce7a430f 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -95,8 +95,8 @@ like. For instance, to hide the verbose output from recursive makefiles, you can say something like: - (setq compilation-hidden-output - \\='(\"^make[^\n]+\n\"))" + (setopt compilation-hidden-output + \\='(\"^make[^\\n]+\\n\"))" :type '(choice regexp (repeat regexp)) :version "29.1") commit d50293b0f108ff85796dc56312a1c46c8db4f8a1 Author: Eli Zaretskii Date: Wed Dec 4 15:21:13 2024 +0200 ; Improve documentation of 'epa-mail-verify' * doc/misc/epa.texi (Mail-mode integration): * lisp/epa-mail.el (epa-mail-verify): Improve documentation of 'epa-mail-verify'. (Bug#74630) diff --git a/doc/misc/epa.texi b/doc/misc/epa.texi index f450b9cbdd9..58c2a111348 100644 --- a/doc/misc/epa.texi +++ b/doc/misc/epa.texi @@ -398,7 +398,8 @@ Decrypt OpenPGP armors in the current buffer. @kindex C-c C-e C-v @kindex C-c C-e v @findex epa-mail-verify -Verify OpenPGP cleartext signed messages in the current buffer. +Verify OpenPGP cleartext signed messages in the current buffer. If +verification fails for some reason, this command signals an error. @item C-c C-e C-s and C-c C-e s @kindex C-c C-e C-s diff --git a/lisp/epa-mail.el b/lisp/epa-mail.el index 0c93b18eea1..47529b02d22 100644 --- a/lisp/epa-mail.el +++ b/lisp/epa-mail.el @@ -90,7 +90,9 @@ The buffer is expected to contain a mail message." ;;;###autoload (defun epa-mail-verify () "Verify OpenPGP cleartext signed messages in the current buffer. -The buffer is expected to contain a mail message." +The buffer is expected to contain a mail message. + +If the verification fails, signal an error." (declare (interactive-only t)) (interactive) (with-suppressed-warnings ((interactive-only epa-verify-cleartext-in-region)) commit c7d9ffcf82954027929e3ca05e2a6455a453ae60 Author: Robert Pluim Date: Tue Dec 3 15:41:48 2024 +0100 Improve docstrings of functions for moving to message headers * lisp/gnus/message.el (message-goto-to, message-goto-from, message-goto-subject, message-goto-cc, message-goto-bcc, message-goto-fcc, message-goto-reply-to, message-goto-newsgroups, message-goto-distribution, message-goto-followup-to, message-goto-mail-followup-to, message-goto-keywords, message-goto-summary): Mention that these will insert an empty header if the header is not found. (message-position-on-field): Explain that this inserts an empty header if the header is missing, and that insertion is done after the headers mentioned in AFTERS. (cherry picked from commit 9f266e2d7cde41f5872304bae0b6d2415655f1c8) diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index 98f63571389..6e9a7e8f72a 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -3253,79 +3253,79 @@ Like `text-mode', but with these additional commands: ;;; Movement commands (defun message-goto-to () - "Move point to the To header." + "Move point to the To header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "To")) (defun message-goto-from () - "Move point to the From header." + "Move point to the From header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "From")) (defun message-goto-subject () - "Move point to the Subject header." + "Move point to the Subject header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Subject")) (defun message-goto-cc () - "Move point to the Cc header." + "Move point to the Cc header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Cc" "To")) (defun message-goto-bcc () - "Move point to the Bcc header." + "Move point to the Bcc header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Bcc" "Cc" "To")) (defun message-goto-fcc () - "Move point to the Fcc header." + "Move point to the Fcc header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Fcc" "To" "Newsgroups")) (defun message-goto-reply-to () - "Move point to the Reply-To header." + "Move point to the Reply-To header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Reply-To" "Subject")) (defun message-goto-newsgroups () - "Move point to the Newsgroups header." + "Move point to the Newsgroups header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Newsgroups")) (defun message-goto-distribution () - "Move point to the Distribution header." + "Move point to the Distribution header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Distribution")) (defun message-goto-followup-to () - "Move point to the Followup-To header." + "Move point to the Followup-To header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Followup-To" "Newsgroups")) (defun message-goto-mail-followup-to () - "Move point to the Mail-Followup-To header." + "Move point to the Mail-Followup-To header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Mail-Followup-To" "To")) (defun message-goto-keywords () - "Move point to the Keywords header." + "Move point to the Keywords header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Keywords" "Subject")) (defun message-goto-summary () - "Move point to the Summary header." + "Move point to the Summary header or insert an empty one." (interactive nil message-mode) (push-mark) (message-position-on-field "Summary" "Subject")) @@ -4249,6 +4249,10 @@ This function strips off the signature from the original message." (newline))) (defun message-position-on-field (header &rest afters) + "Move point to header HEADER or insert it if not found. + +If HEADER is not present, insert it with an empty value, after any +headers specified in AFTERS." (let ((case-fold-search t)) (save-restriction (narrow-to-region commit 7b8d12e95de6e6b5239c538ad6f5af96dc3e1c2a Author: Stephen Berman Date: Tue Dec 3 10:38:26 2024 +0100 Fix the latest dabbrev-expand test fix * test/lisp/dabbrev-tests.el (dabbrev-expand-after-killing-buffer): In batch runs of this file, the user-error message contains curved quotes, but grave quotes when running `make check' (so here was evidently not passed to `substitute-command-keys'), so use grave quotes so the test succeeds in both modes of execution. diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el index 3e84024698f..fb8715924d1 100644 --- a/test/lisp/dabbrev-tests.el +++ b/test/lisp/dabbrev-tests.el @@ -294,9 +294,14 @@ leaving the unexpanded string in the buffer." ; See bug#74090. (should (string= (buffer-string) "abc abd")) (kill-buffer "foo") (erase-buffer) - (let ((msg (cadr (should-error (execute-kbd-macro (kbd "abc SPC ab M-/ M-/")) + ;; In batch runs of this file, the user-error message contains curved + ;; quotes, but grave quotes when running `make check' (so here was + ;; evidently not passed to `substitute-command-keys'), so use grave + ;; quotes so the test succeeds in both modes of execution. + (let* ((text-quoting-style 'grave) + (msg (cadr (should-error (execute-kbd-macro (kbd "abc SPC ab M-/ M-/")) :type 'user-error)))) (should (string= (buffer-string) "abc ab")) - (should (string= msg "No further dynamic expansion for ‘ab’ found"))))) + (should (string= msg "No further dynamic expansion for `ab' found"))))) ;;; dabbrev-tests.el ends here commit e618d5ae941d005e9da6d5d5cba68cc0ecade0e5 Author: Michael Albinus Date: Mon Dec 2 19:21:54 2024 +0100 Fix password prompt in comint (don't merge) * lisp/comint.el (comint-watch-for-password-prompt): Use whole string for setting the prompt. (Bug#74626) diff --git a/lisp/comint.el b/lisp/comint.el index 8860b3edb11..d52090911b9 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -2573,8 +2573,7 @@ This function could be in the list `comint-output-filter-functions'." (when (let ((case-fold-search t)) (string-match comint-password-prompt-regexp (string-replace "\r" "" string))) - (setq prompt (string-trim (match-string 0 string) - "[ \n\r\t\v\f\b\a]+" "\n+")) + (setq prompt (string-trim string "[ \n\r\t\v\f\b\a]+" "\n+")) ;; Use `run-at-time' in order not to pause execution of the ;; process filter with a minibuffer (run-at-time commit f65de1019dca6398097751abefcad7e1a4637551 Author: Manuel Giraud Date: Mon Dec 2 15:11:52 2024 +0100 Fix the version of librsvg API change * src/image.c (init_svg_functions, svg_load_image): The first official version that introduces 'rsvg_handle_get_pixbuf_and_error' is 2.59.0 not 2.58.0. (Bug#74606) diff --git a/src/image.c b/src/image.c index ed680be54dd..8f505026021 100644 --- a/src/image.c +++ b/src/image.c @@ -11655,7 +11655,7 @@ DEF_DLL_FN (void, rsvg_handle_get_dimensions, DEF_DLL_FN (gboolean, rsvg_handle_set_stylesheet, (RsvgHandle *, const guint8 *, gsize, GError **)); # endif -# if LIBRSVG_CHECK_VERSION (2, 58, 0) +# if LIBRSVG_CHECK_VERSION (2, 59, 0) DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf_and_error, (RsvgHandle *, GError **)); # else DEF_DLL_FN (GdkPixbuf *, rsvg_handle_get_pixbuf, (RsvgHandle *)); @@ -11718,7 +11718,7 @@ init_svg_functions (void) #if LIBRSVG_CHECK_VERSION (2, 48, 0) LOAD_DLL_FN (library, rsvg_handle_set_stylesheet); #endif -#if LIBRSVG_CHECK_VERSION (2, 58, 0) +#if LIBRSVG_CHECK_VERSION (2, 59, 0) LOAD_DLL_FN (library, rsvg_handle_get_pixbuf_and_error); #else LOAD_DLL_FN (library, rsvg_handle_get_pixbuf); @@ -11767,7 +11767,7 @@ init_svg_functions (void) # if LIBRSVG_CHECK_VERSION (2, 48, 0) # undef rsvg_handle_set_stylesheet # endif -# if LIBRSVG_CHECK_VERSION (2, 58, 0) +# if LIBRSVG_CHECK_VERSION (2, 59, 0) # undef rsvg_handle_get_pixbuf_and_error # else # undef rsvg_handle_get_pixbuf @@ -11812,7 +11812,7 @@ init_svg_functions (void) # if LIBRSVG_CHECK_VERSION (2, 48, 0) # define rsvg_handle_set_stylesheet fn_rsvg_handle_set_stylesheet # endif -# if LIBRSVG_CHECK_VERSION (2, 58, 0) +# if LIBRSVG_CHECK_VERSION (2, 59, 0) # define rsvg_handle_get_pixbuf_and_error fn_rsvg_handle_get_pixbuf_and_error # else # define rsvg_handle_get_pixbuf fn_rsvg_handle_get_pixbuf @@ -12321,7 +12321,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, /* We can now get a valid pixel buffer from the svg file, if all went ok. */ -#if LIBRSVG_CHECK_VERSION (2, 58, 0) +#if LIBRSVG_CHECK_VERSION (2, 59, 0) pixbuf = rsvg_handle_get_pixbuf_and_error (rsvg_handle, &err); if (err) goto rsvg_error; #else commit 43c4a06ffcc8dd39a3fb743aca5aa9a71e74189c Author: Eli Zaretskii Date: Mon Dec 2 14:33:52 2024 +0200 ; Fix grammar in Emacs user manual * doc/emacs/trouble.texi (Sending Patches): Fix wording. Reported by Daniel Martín . (Bug#74638) diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi index 2e2ee2dc961..f867943a8a0 100644 --- a/doc/emacs/trouble.texi +++ b/doc/emacs/trouble.texi @@ -1255,7 +1255,7 @@ Send them @emph{individually}. If you make two changes for separate reasons, then we might not want to install them both. We might want to install just one, or install -each one in a different versions of Emacs. If you send them all +them separately in different versions of Emacs. If you send them all jumbled together in a single set of diffs, we have to do extra work to disentangle them---to figure out which parts of the change serve which purpose. If we don't have time for this, we might have to postpone commit 6bca138d60e47d0fbab4faf8e83c5b9b319f260d Author: Stephen Berman Date: Mon Dec 2 13:13:39 2024 +0100 Fix latest test for dabbrev-expand * test/lisp/dabbrev-tests.el (dabbrev-expand-after-killing-buffer): Fix typo in a 'should' test, use part of return value of 'should-error' test, and remove mistaken and unfounded FIXME comment. diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el index b5737373875..3e84024698f 100644 --- a/test/lisp/dabbrev-tests.el +++ b/test/lisp/dabbrev-tests.el @@ -278,12 +278,8 @@ minibuffer was entered, the replacement should found in another buffer." (ert-deftest dabbrev-expand-after-killing-buffer () "Test expansion after killing buffer containing first expansion. Finding successive expansions in another live buffer should succeed, but -after killing the buffer, expansion should fail with a user-error." - ;; FIXME? The message shown by the user-error is in *Messages* but - ;; since the test finishes on hitting the user-error, we cannot test - ;; further, either for the content of the message or the content of - ;; the current buffer, so apparently cannot reproduce what a user - ;; entering these commands manually sees. +after killing the buffer, expansion should fail with a user-error, +leaving the unexpanded string in the buffer." ; See bug#74090. (with-dabbrev-test (with-current-buffer (get-buffer-create "foo") (insert "abc abd")) @@ -298,13 +294,9 @@ after killing the buffer, expansion should fail with a user-error." (should (string= (buffer-string) "abc abd")) (kill-buffer "foo") (erase-buffer) - (should-error (execute-kbd-macro (kbd "abc SPC ab M-/ M-/")) - :type 'user-error) - ;; (should (string= (buffer-string) "abc abc")) - ;; (with-current-buffer "*Messages*" - ;; (goto-char (point-max)) - ;; (should (string= (buffer-substring (pos-bol) (pos-eol)) - ;; "No further dynamic expansion for ‘ab’ found"))) - )) + (let ((msg (cadr (should-error (execute-kbd-macro (kbd "abc SPC ab M-/ M-/")) + :type 'user-error)))) + (should (string= (buffer-string) "abc ab")) + (should (string= msg "No further dynamic expansion for ‘ab’ found"))))) ;;; dabbrev-tests.el ends here