commit d1b67b4a1c75e0d94892babc30da8ffd689f9d9e (HEAD, refs/remotes/origin/master) Author: Stefan Kangas Date: Sun Nov 3 04:18:29 2024 +0100 * etc/symbol-releases.eld: Add 'set-transient-map'. diff --git a/etc/symbol-releases.eld b/etc/symbol-releases.eld index 85bc05ac2ef..4931be2fb7d 100644 --- a/etc/symbol-releases.eld +++ b/etc/symbol-releases.eld @@ -18,6 +18,7 @@ ;; damaged. See ;; https://github.com/larsbrinkhoff/emacs-history/tree/sources/decuslib.com/decus/vax85b/gnuemax + ("24.4" fun set-transient-map) ("19.7" fun defsubst) ("19.34" fun make-directory) ("18.59" fun mark) commit 2a41f4ae766cf0b150cc8ec054b30e60e1a438d4 Author: Stefan Kangas Date: Sun Nov 3 04:14:56 2024 +0100 Remove Emacs 24.4 compat code from which-key * lisp/which-key.el (which-key--show-page): Remove Emacs 24.4 compatibility code. diff --git a/lisp/which-key.el b/lisp/which-key.el index 1da9a25090f..1039f2427df 100644 --- a/lisp/which-key.el +++ b/lisp/which-key.el @@ -2346,10 +2346,7 @@ enough space based on your settings and frame size." prefix-keys) (when (cdr page-echo) (funcall (cdr page-echo))) (which-key--show-popup (cons height width))))) ;; used for paging at top-level - (if (fboundp 'set-transient-map) - (set-transient-map (which-key--get-popup-map)) - (with-no-warnings - (set-temporary-overlay-map (which-key--get-popup-map)))))) + (set-transient-map (which-key--get-popup-map)))) ;;; Paging functions commit d245fb3964dcb404dc35a6f985c473f1ca879b33 Author: Stephen Gildea Date: Sat Nov 2 09:42:25 2024 -0700 Expand manual section on Time Stamps * doc/emacs/files.texi (Time Stamps): Add examples of enabling time stamping with add-hook and setting time-stamp-pattern as a file-local variable. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index 86b85f16d69..e732911b98f 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -411,7 +411,7 @@ that was visited in the buffer. * Interlocking:: How Emacs protects against simultaneous editing of one file by two users. * Shadowing: File Shadowing. Copying files to ``shadows'' automatically. -* Time Stamps:: Emacs can update time stamps on saved files. +* Time Stamps:: Emacs can update time stamps when a file is saved. @end menu @node Save Commands @@ -997,33 +997,90 @@ File Shadowing is not available on MS Windows. @subsection Updating Time Stamps Automatically @cindex time stamps @cindex modification dates -@cindex locale, date format +@cindex last modified time -You can arrange to put a time stamp in a file, so that it is updated -automatically each time you edit and save the file. The time stamp -must be in the first eight lines of the file, and you should insert it -like this: +You can arrange to have a time stamp in a file be updated +automatically each time you save the file. +(A time stamp may also be called a date stamp or a last modified time.) +Having a time stamp in the text of a file ensures that the time the file +was written will be preserved even if the file is copied or transformed +in a way that loses the file system's modification time. + +There are two steps to setting up automatic time stamping. +First, you need to have a time stamp template +somewhere in the first eight lines of the file. +The template looks like this: @example Time-stamp: <> @end example @noindent -or like this: +or (your choice) like this: @example Time-stamp: " " @end example +@noindent +When time-stamping, Emacs will write the current time, date, and/or +other info between the brackets or quotes. + @findex time-stamp - Then add the function @code{time-stamp} to the hook -@code{before-save-hook} (@pxref{Hooks}). When you save the file, this -function then automatically updates the time stamp with the current -date and time. You can also use the command @kbd{M-x time-stamp} to -update the time stamp manually. By default the time stamp is +Second, add the function @code{time-stamp} +to @code{before-save-hook} (@pxref{Hooks}). +To do this, either customize the option @code{before-save-hook} +(with @kbd{M-x customize-option}, @pxref{Specific Customization}) +or edit your init file adding this line: + +@example +(add-hook 'before-save-hook 'time-stamp) +@end example + +To enable automatic time-stamping for only a specific file, add the +following line to a local variables list +(@pxref{Specifying File Variables}) near the end of the file: + +@example +eval: (add-hook 'before-save-hook 'time-stamp nil t) +@end example + +To update the current buffer's time stamp once +immediately, use the command @kbd{M-x time-stamp}. + +@vindex time-stamp-pattern +To customize the time stamp in a particular file, set the +variable @code{time-stamp-pattern} in that file's local variables list. +You can change where the time stamp starts and ends and how the dynamic +information is to be formatted; see the variable's built-in +documentation for details. +As a simple example, if this line occurs near the top of a file: + +@example +\newcommand@{\yearpublished@}@{@} +@end example + +@noindent +then the following at the end of the file tells @code{time-stamp} how to +identify and update that custom template: + +@example +@group +%% Local variables: +%% time-stamp-pattern: "@{.yearpublished@}@{%Y@}" +%% End: +@end group +@end example + +@vindex time-stamp-format +By default the time stamp is formatted according to your locale setting (@pxref{Environment}) and time zone (@pxref{Time of Day,,, elisp, The Emacs Lisp Reference -Manual}). For customizations, see the Custom group @code{time-stamp}. +Manual}). +See the built-in documentation for the variable @code{time-stamp-format} +for specifics and other variables that affect the formatting. + +For customizations, see the Custom group @code{time-stamp}. @node Reverting @section Reverting a Buffer commit 435d7d4292e6803405c1ea65c73693f20eea2a58 Author: Eli Zaretskii Date: Sat Nov 2 18:15:25 2024 +0200 Fix color-lightening and darkening calculations * lisp/color.el (color-lighten-hsl): Fix calculations (bug#74055). * test/lisp/color-tests.el (color-tests-lighten-hsl) (color-tests-lighten-name, color-tests-darken-hsl) (color-tests-darken-name): Adjust test results. diff --git a/lisp/color.el b/lisp/color.el index 186f1bd9f9a..007504043cc 100644 --- a/lisp/color.el +++ b/lisp/color.el @@ -446,7 +446,11 @@ See `color-desaturate-hsl'." Given a color defined in terms of hue, saturation, and luminance \(arguments H, S, and L), return a color that is PERCENT lighter. Returns a list (HUE SATURATION LUMINANCE)." - (list H S (color-clamp (+ L (/ percent 100.0))))) + (let ((p (/ percent 100.0))) + (if (> p 0.0) + (setq L (* L (- 1.0 p))) + (setq p (- (* L (abs p))))) + (list H S (color-clamp (+ L p))))) (defun color-lighten-name (name percent) "Make a color with a specified NAME lighter by PERCENT. diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el index bc897edc702..63cb024bb8d 100644 --- a/test/lisp/color-tests.el +++ b/test/lisp/color-tests.el @@ -220,32 +220,29 @@ (ert-deftest color-tests-lighten-hsl () (should (equal (color-lighten-hsl 360 0.5 0.5 0) '(360 0.5 0.5))) - (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.4))) + (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.45))) (should (equal (color-lighten-hsl 360 0.5 0.5 -500) '(360 0.5 0.0))) - (should - (color-tests--approx-equal - (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.85))) - (should - (equal (color-lighten-hsl 120 0.5 0.8 500) '(120 0.5 1.0)))) + (should (equal (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.81))) + (should (equal (color-lighten-hsl 120 0.5 0.8 500) '(120 0.5 1.0)))) (ert-deftest color-tests-lighten-name () (should (equal (color-lighten-name "black" 100) "#ffffffffffff")) (should (equal (color-lighten-name "white" 100) "#ffffffffffff")) (should (equal (color-lighten-name "red" 0) "#ffff00000000")) - (should (equal (color-lighten-name "red" 10) "#ffff33323332"))) + (should (equal (color-lighten-name "red" 10) "#ffff19991999"))) (ert-deftest color-tests-darken-hsl () (should (equal (color-darken-hsl 360 0.5 0.5 0) '(360 0.5 0.5))) - (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.6))) + (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.55))) (should (equal (color-darken-hsl 360 0.5 0.5 -500) '(360 0.5 1.0))) - (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.75))) + (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.76))) (should (equal (color-darken-hsl 120 0.5 0.8 500) '(120 0.5 0.0)))) (ert-deftest color-tests-darken-name () (should (equal (color-darken-name "black" 100) "#000000000000")) (should (equal (color-darken-name "white" 100) "#000000000000")) (should (equal (color-darken-name "red" 0) "#ffff00000000")) - (should (equal (color-darken-name "red" 10) "#cccc00000000"))) + (should (equal (color-darken-name "red" 10) "#e66500000000"))) (ert-deftest color-tests-oklab-to-xyz () (should (color-tests--approx-equal (color-oklab-to-xyz 0 0 0) '(0.0 0.0 0.0))) commit 99650746d916335bbe480c462af83009037632df Author: Eli Zaretskii Date: Sat Nov 2 17:36:02 2024 +0200 Revert "Fix color-lighten-hsl logic" This reverts commit 656c2dd66e77a5fbeb99d358017e8327401fae05. That commit was mistaken, see bug#74055. diff --git a/lisp/color.el b/lisp/color.el index 79dced4e3d7..186f1bd9f9a 100644 --- a/lisp/color.el +++ b/lisp/color.el @@ -446,7 +446,7 @@ See `color-desaturate-hsl'." Given a color defined in terms of hue, saturation, and luminance \(arguments H, S, and L), return a color that is PERCENT lighter. Returns a list (HUE SATURATION LUMINANCE)." - (list H S (color-clamp (+ L (* L (/ percent 100.0)))))) + (list H S (color-clamp (+ L (/ percent 100.0))))) (defun color-lighten-name (name percent) "Make a color with a specified NAME lighter by PERCENT. diff --git a/test/lisp/color-tests.el b/test/lisp/color-tests.el index 0f53e4332a4..bc897edc702 100644 --- a/test/lisp/color-tests.el +++ b/test/lisp/color-tests.el @@ -220,32 +220,32 @@ (ert-deftest color-tests-lighten-hsl () (should (equal (color-lighten-hsl 360 0.5 0.5 0) '(360 0.5 0.5))) - (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.45))) + (should (equal (color-lighten-hsl 360 0.5 0.5 -10) '(360 0.5 0.4))) (should (equal (color-lighten-hsl 360 0.5 0.5 -500) '(360 0.5 0.0))) (should (color-tests--approx-equal - (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.84))) + (color-lighten-hsl 120 0.5 0.8 5) '(120 0.5 0.85))) (should (equal (color-lighten-hsl 120 0.5 0.8 500) '(120 0.5 1.0)))) (ert-deftest color-tests-lighten-name () - (should (equal (color-lighten-name "black" 100) "#000000000000")) + (should (equal (color-lighten-name "black" 100) "#ffffffffffff")) (should (equal (color-lighten-name "white" 100) "#ffffffffffff")) (should (equal (color-lighten-name "red" 0) "#ffff00000000")) - (should (equal (color-lighten-name "red" 10) "#ffff19991999"))) + (should (equal (color-lighten-name "red" 10) "#ffff33323332"))) (ert-deftest color-tests-darken-hsl () (should (equal (color-darken-hsl 360 0.5 0.5 0) '(360 0.5 0.5))) - (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.55))) + (should (equal (color-darken-hsl 360 0.5 0.5 -10) '(360 0.5 0.6))) (should (equal (color-darken-hsl 360 0.5 0.5 -500) '(360 0.5 1.0))) - (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.76))) + (should (equal (color-darken-hsl 120 0.5 0.8 5) '(120 0.5 0.75))) (should (equal (color-darken-hsl 120 0.5 0.8 500) '(120 0.5 0.0)))) (ert-deftest color-tests-darken-name () (should (equal (color-darken-name "black" 100) "#000000000000")) (should (equal (color-darken-name "white" 100) "#000000000000")) (should (equal (color-darken-name "red" 0) "#ffff00000000")) - (should (equal (color-darken-name "red" 10) "#e66500000000"))) + (should (equal (color-darken-name "red" 10) "#cccc00000000"))) (ert-deftest color-tests-oklab-to-xyz () (should (color-tests--approx-equal (color-oklab-to-xyz 0 0 0) '(0.0 0.0 0.0))) commit 021c0ba116e00d20cb006e7441c20d21315ec202 Author: Eli Zaretskii Date: Sat Nov 2 08:42:35 2024 -0400 ; * lisp/progmodes/c-ts-common.el: Fix merging snafu. diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 5c7909ae858..d05b5248cc2 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -336,7 +336,7 @@ and /* */ comments. SOFT works the same as in (delete-horizontal-space) (if soft (insert-and-inherit ?\n) - (newline (if allow-auto-fill nil 1)))))) + (newline 1))))) (cond ;; Line starts with //, or ///, or ////... ;; Or //! (used in rust). commit aac4a939f905575b1194aead62ed7b73fbe23055 Merge: 1c7110dade8 f7b85fe986e Author: Eli Zaretskii Date: Sat Nov 2 08:38:11 2024 -0400 Merge from origin/emacs-30 f7b85fe986e Improve documentation of letter-case conversions commit 1c7110dade82ef598d8f7bad5ef25d002a2a2b1f Merge: a88863d32fc 0f9d48e99ce Author: Eli Zaretskii Date: Sat Nov 2 08:38:11 2024 -0400 ; Merge from origin/emacs-30 The following commits were skipped: 0f9d48e99ce project-tests: Add test assertion for bug#73801 b4b0d5a8532 project-try-vc: Fix the "sometimes wrong cache" issue 8113b5c562b Fix bugs in dabbrev-expand (bug#74090) 3101c5031e6 Fix undefined variable in previous commit (bug#73900) commit a88863d32fcaf0a2d06ad97403ddbaa7713b8ae2 Merge: 244b1ade496 e6a8492fabc Author: Eli Zaretskii Date: Sat Nov 2 08:37:53 2024 -0400 Merge from origin/emacs-30 e6a8492fabc Fix c-ts-common-comment-indent-new-line (bug#73900) # Conflicts: # lisp/progmodes/c-ts-common.el commit 244b1ade4965ebc666b37806833824de6eddc0c9 Merge: 9bc6362d6e4 df5ac0daf0f Author: Eli Zaretskii Date: Sat Nov 2 08:34:43 2024 -0400 ; Merge from origin/emacs-30 The following commits were skipped: df5ac0daf0f Fix the call to treesit-thing-defined-p 7a3c10dcb56 Backport: Call tab-bar-tab-post-open-functions during tab... commit 9bc6362d6e43e99cfe2dea8748e29e63c65985c0 Merge: 74d3232522f 98796f95fa5 Author: Eli Zaretskii Date: Sat Nov 2 08:34:42 2024 -0400 Merge from origin/emacs-30 98796f95fa5 Work on proced-tests.el 8a4d13e370c ; * doc/lispref/frames.texi (Yanking Media): Add index en... 0aae02a3741 * lisp/files.el (require-with-check): Be a bit more lenie... cc6a11f4832 (with-peg-rules): Fix references to rulesets (bug#74018) 70f084db2ff ; * etc/NEWS: Fix typo (bug#74066). 9e1abf11fc1 Tweak doc w.r.t to "void function" (bug#73886) 7a8ca202c5e Fix flakey proced refine tests (Bug#73441) 55a8cec013e Another 'void' update commit 74d3232522f762742e9acaf9e62b9fd6d63ae380 Author: Eli Zaretskii Date: Sat Nov 2 13:33:36 2024 +0200 ; * lisp/net/eww.el (eww--html buffer-list): Fix comment style. diff --git a/lisp/net/eww.el b/lisp/net/eww.el index ec2f4e494e4..2d351dff88f 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -664,8 +664,8 @@ HEADERS is unused." (let ((case-fold-search t)) (save-excursion (goto-char (point-min)) - ;; match basic and also legacy variants as - ;; specified in link above - being purposely lax about it + ;; Match basic "" and also legacy variants as + ;; specified in link above -- being purposely lax about it. (when (search-forward " Date: Thu Oct 24 13:09:11 2024 -0400 More lax doctype check in EWW (bug#73133) The regexp to match doctype tags was simplified and will match more legacy entries; also correct binding of 'case-fold-search'. * lisp/net/eww.el (eww--html buffer-list): Update function. diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 7bbbeadaedd..ec2f4e494e4 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -660,15 +660,14 @@ valid Content-Type header. If none of the functions can guess, return "Return \"text/html\" if RESPONSE-BUFFER has an HTML doctype declaration. HEADERS is unused." ;; https://html.spec.whatwg.org/multipage/syntax.html#the-doctype - (let ((case-fold-search t) - (target - "\\|system +\\(\\\"\\|'\\)+about:legacy-compat\\)")) - (with-current-buffer response-buffer - (goto-char (point-min)) - ;; match basic and also legacy variants as - ;; specified in link above - (when (re-search-forward target nil t) - "text/html")))) + (with-current-buffer response-buffer + (let ((case-fold-search t)) + (save-excursion + (goto-char (point-min)) + ;; match basic and also legacy variants as + ;; specified in link above - being purposely lax about it + (when (search-forward " Date: Sat Nov 2 13:16:41 2024 +0200 ; * src/nsterm.m (ns_draw_fringe_bitmap): Fix coding style. diff --git a/src/nsterm.m b/src/nsterm.m index ad3b8ba8487..8862a74f129 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2962,12 +2962,12 @@ Hide the window (X11 semantics) p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh); /* Clear screen unless overlay. */ - if ( !p->overlay_p ) + if (!p->overlay_p) { /* Work out the rectangle we will need to clear. */ clearRect = NSMakeRect (p->x, p->y, p->wd, p->h); - if ( p->bx >= 0 ) + if (p->bx >= 0) clearRect = NSUnionRect (clearRect, NSMakeRect (p->bx, p->by, p->nx, p->ny)); /* Handle partially visible rows. */ @@ -2976,7 +2976,7 @@ Hide the window (X11 semantics) /* The visible portion of imageRect will always be contained within clearRect. */ ns_focus (f, &clearRect, 1); - if ( !NSIsEmptyRect (clearRect) ) + if (!NSIsEmptyRect (clearRect)) { NSTRACE_RECT ("clearRect", clearRect); commit 87358e94047c7f86af1f1ac9d9469553dcd6a6e1 Author: Daniel Pettersson Date: Mon Jun 24 23:16:59 2024 +0200 Fix inconsistency in bitmap overlay drawing for macOS * src/nsterm.m (ns_draw_fringe_bitmap): Respect 'overlay_p', by not clearing fringe if set, as its done in xterm. (Bug#71763) diff --git a/src/nsterm.m b/src/nsterm.m index f68a22d9fbc..ad3b8ba8487 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -2961,24 +2961,28 @@ Hide the window (X11 semantics) NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d", p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh); - /* Work out the rectangle we will need to clear. */ - clearRect = NSMakeRect (p->x, p->y, p->wd, p->h); + /* Clear screen unless overlay. */ + if ( !p->overlay_p ) + { + /* Work out the rectangle we will need to clear. */ + clearRect = NSMakeRect (p->x, p->y, p->wd, p->h); - if (p->bx >= 0 && !p->overlay_p) - clearRect = NSUnionRect (clearRect, NSMakeRect (p->bx, p->by, p->nx, p->ny)); + if ( p->bx >= 0 ) + clearRect = NSUnionRect (clearRect, NSMakeRect (p->bx, p->by, p->nx, p->ny)); - /* Handle partially visible rows. */ - clearRect = NSIntersectionRect (clearRect, rowRect); + /* Handle partially visible rows. */ + clearRect = NSIntersectionRect (clearRect, rowRect); - /* The visible portion of imageRect will always be contained within - clearRect. */ - ns_focus (f, &clearRect, 1); - if (! NSIsEmptyRect (clearRect)) - { - NSTRACE_RECT ("clearRect", clearRect); + /* The visible portion of imageRect will always be contained + within clearRect. */ + ns_focus (f, &clearRect, 1); + if ( !NSIsEmptyRect (clearRect) ) + { + NSTRACE_RECT ("clearRect", clearRect); - [[NSColor colorWithUnsignedLong:face->background] set]; - NSRectFill (clearRect); + [[NSColor colorWithUnsignedLong:face->background] set]; + NSRectFill (clearRect); + } } NSBezierPath *bmp = [fringe_bmp objectForKey:[NSNumber numberWithInt:p->which]]; commit f7b85fe986e74b649f8148ee407cf7a2327ff4a9 (refs/remotes/origin/emacs-30) Author: Eli Zaretskii Date: Fri Nov 1 16:39:39 2024 +0200 Improve documentation of letter-case conversions * doc/lispref/nonascii.texi (Character Properties): * doc/lispref/strings.texi (Case Conversion, Case Tables): Document that special-casing rules override the case-table conversions. (Bug#74155) diff --git a/doc/lispref/nonascii.texi b/doc/lispref/nonascii.texi index e5d552815e0..c55e5a67693 100644 --- a/doc/lispref/nonascii.texi +++ b/doc/lispref/nonascii.texi @@ -632,8 +632,10 @@ is @code{nil}, which means the character itself. Corresponds to Unicode language- and context-independent special upper-casing rules. The value of this property is a string (which may be empty). For example mapping for U+00DF @sc{latin small letter sharp s} is -@code{"SS"}. For characters with no special mapping, the value is @code{nil} -which means @code{uppercase} property needs to be consulted instead. +@code{"SS"}. This mapping overrides the @code{uppercase} property, and +thus the current case table. For characters with no special mapping, +the value is @code{nil}, which means @code{uppercase} property needs to +be consulted instead. @item special-lowercase Corresponds to Unicode language- and context-independent special @@ -641,16 +643,19 @@ lower-casing rules. The value of this property is a string (which may be empty). For example mapping for U+0130 @sc{latin capital letter i with dot above} the value is @code{"i\u0307"} (i.e. 2-character string consisting of @sc{latin small letter i} followed by U+0307 -@sc{combining dot above}). For characters with no special mapping, -the value is @code{nil} which means @code{lowercase} property needs to -be consulted instead. +@sc{combining dot above}). This mapping overrides the @code{lowercase} +property, and thus the current case table. For characters with no +special mapping, the value is @code{nil}, which means @code{lowercase} +property needs to be consulted instead. @item special-titlecase Corresponds to Unicode unconditional special title-casing rules. The value of this property is a string (which may be empty). For example mapping for -U+FB01 @sc{latin small ligature fi} the value is @code{"Fi"}. For -characters with no special mapping, the value is @code{nil} which means -@code{titlecase} property needs to be consulted instead. +U+FB01 @sc{latin small ligature fi} the value is @code{"Fi"}. This +mapping overrides the @code{titlecase} property, and thus the current +case table. For characters with no special mapping, the value is +@code{nil}, which means @code{titlecase} property needs to be consulted +instead. @end table @defun get-char-code-property char propname diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index c459c719d7a..09f5bdc803b 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -1591,9 +1591,12 @@ using @code{string} function, before being passed to one of the casing functions. Of course, no assumptions on the length of the result may be made. - Mapping for such special cases are taken from -@code{special-uppercase}, @code{special-lowercase} and -@code{special-titlecase} @xref{Character Properties}. + Other characters can also have special case-conversion rules. They +all have non-@code{nil} character properties @code{special-uppercase}, +@code{special-lowercase} or @code{special-titlecase} (@pxref{Character +Properties}) defined by the Unicode Standard. These properties define +special case-conversion rules which override the current case table +(@pxref{Case Tables}). @xref{Text Comparison}, for functions that compare strings; some of them ignore case differences, or can optionally ignore case differences. @@ -1634,14 +1637,32 @@ correspondence. There may be two different lower case letters with the same upper case equivalent. In these cases, you need to specify the maps for both lower case and upper case. - The extra table @var{canonicalize} maps each character to a canonical + Some characters have special case-conversion rules defined for them, +which by default override the current case table. These characters have +non-@code{nil} character properties @code{special-uppercase}, +@code{special-lowercase} or @code{special-titlecase} (@pxref{Character +Properties}) defined by the Unicode Standard. An example is U+00DF +LATIN SMALL LETTER SHARP S, @ss{}, which by default up-cases to the +string @code{"SS"}, not to U+1E9E LATIN CAPITAL LETTER SHARP S@. To +force these characters follow the case-table conversions, set the +corresponding Unicode property to @code{nil}: + +@example + (upcase "@ss{}") + => "SS" + (put-char-code-property ?@ss{} 'special-uppercase nil) + (upcase "@ss{}") + => "ẞ" +@end example + + The extra slot @var{canonicalize} of a case table maps each character to a canonical equivalent; any two characters that are related by case-conversion have the same canonical equivalent character. For example, since @samp{a} and @samp{A} are related by case-conversion, they should have the same canonical equivalent character (which should be either @samp{a} for both of them, or @samp{A} for both of them). - The extra table @var{equivalences} is a map that cyclically permutes + The extra slot @var{equivalences} is a map that cyclically permutes each equivalence class (of characters with the same canonical equivalent). (For ordinary @acronym{ASCII}, this would map @samp{a} into @samp{A} and @samp{A} into @samp{a}, and likewise for each set of commit 0f9d48e99ce10e92e19e20ea9d2872a176ea6f8f Author: Dmitry Gutov Date: Fri Nov 1 02:32:10 2024 +0200 project-tests: Add test assertion for bug#73801 * test/lisp/progmodes/project-tests.el (project-vc-extra-root-markers-supports-wildcards): End with a check that we didn't cache a wrong value for parent (bug#73801). (cherry picked from commit 94a9e40e82d4180563d7bddfa0cc6c8990824f8d) diff --git a/test/lisp/progmodes/project-tests.el b/test/lisp/progmodes/project-tests.el index 93943cef43b..1583732016b 100644 --- a/test/lisp/progmodes/project-tests.el +++ b/test/lisp/progmodes/project-tests.el @@ -138,7 +138,11 @@ When `project-ignores' includes a name matching project dir." (project (project-current nil dir))) (should-not (null project)) (should (nth 1 project)) - (should (string-match-p "/test/lisp/\\'" (project-root project))))) + (should (string-match-p "/test/lisp/\\'" (project-root project))) + ;; bug#73801 + (should (equal + project + (project-current nil (project-root project)))))) (ert-deftest project-vc-supports-project-in-different-dir () "Check that it picks up dir-locals settings from somewhere else." commit b4b0d5a8532a4e519835b68b8fb7048c9de51000 Author: Dmitry Gutov Date: Mon Oct 28 05:53:16 2024 +0200 project-try-vc: Fix the "sometimes wrong cache" issue * lisp/progmodes/project.el (project-try-vc--search): Extract from 'project-try-vc'. (project-try-vc): Use it. (project-try-vc--search): Call itself recursively directly, to avoid creating invalid cache entry (bug#73801). (cherry picked from commit 29b30eb49f8bd8bad4f9e24dd56f32d62bf70121) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index 78f5c127900..fdcaa2c7ddc 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -543,61 +543,64 @@ project backend implementation of `project-external-roots'.") See `project-vc-extra-root-markers' for the marker value format.") (defun project-try-vc (dir) - ;; FIXME: Learn to invalidate when the value of - ;; `project-vc-merge-submodules' or `project-vc-extra-root-markers' - ;; changes. + ;; FIXME: Learn to invalidate when the value changes: + ;; `project-vc-merge-submodules' or `project-vc-extra-root-markers'. (or (vc-file-getprop dir 'project-vc) - (let* ((backend-markers - (delete - nil - (mapcar - (lambda (b) (assoc-default b project-vc-backend-markers-alist)) - vc-handled-backends))) - (marker-re - (concat - "\\`" - (mapconcat - (lambda (m) (format "\\(%s\\)" (wildcard-to-regexp m))) - (append backend-markers - (project--value-in-dir 'project-vc-extra-root-markers dir)) - "\\|") - "\\'")) - (locate-dominating-stop-dir-regexp - (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)) - last-matches - (root - (locate-dominating-file - dir - (lambda (d) - ;; Maybe limit count to 100 when we can drop Emacs < 28. - (setq last-matches - (condition-case nil - (directory-files d nil marker-re t) - (file-missing nil)))))) - (backend - (cl-find-if - (lambda (b) - (member (assoc-default b project-vc-backend-markers-alist) - last-matches)) - vc-handled-backends)) - project) - (when (and - (eq backend 'Git) - (project--vc-merge-submodules-p root) - (project--submodule-p root)) - (let* ((parent (file-name-directory (directory-file-name root)))) - (setq root (vc-call-backend 'Git 'root parent)))) - (when root - (when (not backend) - (let* ((project-vc-extra-root-markers nil) - ;; Avoid submodules scan. - (enable-dir-local-variables nil) - (parent (project-try-vc root))) - (and parent (setq backend (nth 1 parent))))) - (setq project (list 'vc backend root)) - ;; FIXME: Cache for a shorter time. - (vc-file-setprop dir 'project-vc project) - project)))) + ;; FIXME: Cache for a shorter time. + (let ((res (project-try-vc--search dir))) + (and res (vc-file-setprop dir 'project-vc res)) + res))) + +(defun project-try-vc--search (dir) + (let* ((backend-markers + (delete + nil + (mapcar + (lambda (b) (assoc-default b project-vc-backend-markers-alist)) + vc-handled-backends))) + (marker-re + (concat + "\\`" + (mapconcat + (lambda (m) (format "\\(%s\\)" (wildcard-to-regexp m))) + (append backend-markers + (project--value-in-dir 'project-vc-extra-root-markers dir)) + "\\|") + "\\'")) + (locate-dominating-stop-dir-regexp + (or vc-ignore-dir-regexp locate-dominating-stop-dir-regexp)) + last-matches + (root + (locate-dominating-file + dir + (lambda (d) + ;; Maybe limit count to 100 when we can drop Emacs < 28. + (setq last-matches + (condition-case nil + (directory-files d nil marker-re t) + (file-missing nil)))))) + (backend + (cl-find-if + (lambda (b) + (member (assoc-default b project-vc-backend-markers-alist) + last-matches)) + vc-handled-backends)) + project) + (when (and + (eq backend 'Git) + (project--vc-merge-submodules-p root) + (project--submodule-p root)) + (let* ((parent (file-name-directory (directory-file-name root)))) + (setq root (vc-call-backend 'Git 'root parent)))) + (when root + (when (not backend) + (let* ((project-vc-extra-root-markers nil) + ;; Avoid submodules scan. + (enable-dir-local-variables nil) + (parent (project-try-vc--search root))) + (and parent (setq backend (nth 1 parent))))) + (setq project (list 'vc backend root)) + project))) (defun project--submodule-p (root) ;; XXX: We only support Git submodules for now. commit 8113b5c562b88d4981231b0e332ced9fc20dc0b9 Author: Stephen Berman Date: Thu Oct 31 10:46:27 2024 +0100 Fix bugs in dabbrev-expand (bug#74090) * lisp/dabbrev.el (dabbrev-expand): Use the buffer where the expansion was found when setting the internal variables used to determine the next expansion or a replacement expansion. * test/lisp/dabbrev-tests.el (ert-x): Require for 'ert-with-temp-directory', 'ert-resource-directory' and 'ert-resource-file'. (with-dabbrev-test): New macro. (dabbrev-expand-test-same-buffer-{1,2,3,4}) (dabbrev-expand-test-other-buffer-{1,2,3,4}) (dabbrev-expand-test-minibuffer-{1,2,3,4}): New tests. * test/lisp/dabbrev-resources/dabbrev-expand.el: * test/lisp/dabbrev-resources/INSTALL_BEGIN: New test resources. (cherry picked from commit f6c359cb66a0e9b851e3467b1ba9cab7efa8f744) diff --git a/lisp/dabbrev.el b/lisp/dabbrev.el index 7b6cbb78cef..bbe6a64b626 100644 --- a/lisp/dabbrev.el +++ b/lisp/dabbrev.el @@ -464,8 +464,21 @@ direction of search to backward if set non-nil. See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (interactive "*P") - (let (abbrev record-case-pattern - expansion old direction (orig-point (point))) + ;; There are three possible sources of the expansion, which we need to + ;; check in a specific order: + (let ((buf (cond ((window-minibuffer-p) + ;; If we invoked dabbrev-expand in the minibuffer, + ;; this is the buffer from which we entered the + ;; minibuffer. + (window-buffer (get-mru-window))) + ;; Otherwise, if we found the expansion in another + ;; buffer, use that buffer for further expansions. + (dabbrev--last-buffer-found dabbrev--last-buffer-found) + ;; Otherwise, use the buffer where we invoked + ;; dabbrev-expand. + (t (current-buffer)))) + abbrev record-case-pattern expansion old direction + (orig-point (point))) ;; abbrev -- the abbrev to expand ;; expansion -- the expansion found (eventually) or nil until then ;; old -- the text currently in the buffer @@ -480,6 +493,7 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (point))))) ;; Find a different expansion for the same abbrev as last time. (progn + (setq dabbrev--last-buffer-found nil) (setq abbrev dabbrev--last-abbreviation) (setq old dabbrev--last-expansion) (setq direction dabbrev--last-direction)) @@ -488,7 +502,14 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (if (and (eq (preceding-char) ?\s) (markerp dabbrev--last-abbrev-location) (marker-position dabbrev--last-abbrev-location) - (= (point) (1+ dabbrev--last-abbrev-location))) + ;; Comparing with point only makes sense in the buffer + ;; where we called dabbrev-expand, but if that differs + ;; from the buffer containing the expansion, we want to + ;; get the next word in the latter buffer, so we skip + ;; the comparison. + (if (eq buf (current-buffer)) + (= (point) (1+ dabbrev--last-abbrev-location)) + t)) (progn ;; The "abbrev" to expand is just the space. (setq abbrev " ") @@ -549,29 +570,43 @@ See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." (if old " further" "") abbrev)) (t (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found) - (minibuffer-window-active-p (selected-window)))) + ;; If we are in the minibuffer and an expansion has + ;; been found but dabbrev--last-buffer-found is not + ;; yet set, we need to set it now. + (and dabbrev--last-buffer-found + (minibuffer-window-active-p (selected-window))))) (progn (when (buffer-name dabbrev--last-buffer) (message "Expansion found in `%s'" (buffer-name dabbrev--last-buffer))) (setq dabbrev--last-buffer-found dabbrev--last-buffer)) (message nil)) - (if (and (or (eq (current-buffer) dabbrev--last-buffer) - (null dabbrev--last-buffer) - (buffer-live-p dabbrev--last-buffer)) - (numberp dabbrev--last-expansion-location) - (and (> dabbrev--last-expansion-location (point)))) - (setq dabbrev--last-expansion-location - (copy-marker dabbrev--last-expansion-location))) + ;; To get correct further expansions we have to be sure to use the + ;; buffer containing the already found expansions. + (when dabbrev--last-buffer-found + (setq buf dabbrev--last-buffer-found)) + ;; If the buffer where we called dabbrev-expand differs from the + ;; buffer containing the expansion, make sure copy-marker is + ;; called in the latter buffer. + (with-current-buffer buf + (if (and (or (eq (current-buffer) dabbrev--last-buffer) + (null dabbrev--last-buffer) + (buffer-live-p dabbrev--last-buffer)) + (numberp dabbrev--last-expansion-location) + (and (> dabbrev--last-expansion-location (point)))) + (setq dabbrev--last-expansion-location + (copy-marker dabbrev--last-expansion-location)))) ;; Success: stick it in and return. (setq buffer-undo-list (cons orig-point buffer-undo-list)) (setq expansion (dabbrev--substitute-expansion old abbrev expansion record-case-pattern)) - ;; Save state for re-expand. - (setq dabbrev--last-expansion expansion) - (setq dabbrev--last-abbreviation abbrev) - (setq dabbrev--last-abbrev-location (point-marker)))))) + ;; Save state for re-expand (making sure it's the state of the + ;; buffer containing the already found expansions). + (with-current-buffer buf + (setq dabbrev--last-expansion expansion) + (setq dabbrev--last-abbreviation abbrev) + (setq dabbrev--last-abbrev-location (point-marker))))))) ;;---------------------------------------------------------------- ;; Local functions diff --git a/test/lisp/dabbrev-resources/INSTALL_BEGIN b/test/lisp/dabbrev-resources/INSTALL_BEGIN new file mode 100644 index 00000000000..6309419dccf --- /dev/null +++ b/test/lisp/dabbrev-resources/INSTALL_BEGIN @@ -0,0 +1,153 @@ +GNU Emacs Installation Guide +Copyright (C) 1992, 1994, 1996-1997, 2000-2024 Free Software Foundation, +Inc. +See the end of the file for license conditions. + + +This file contains general information on building GNU Emacs. If you +are building an Emacs release tarball on a Unix or a GNU system, the +instructions in this file should be sufficient. For other +configurations, we have additional specialized files: + + . INSTALL.REPO if you build from a Git checkout + . nt/INSTALL if you build for MS-Windows + . nextstep/INSTALL if you build for GNUstep/macOS + . java/INSTALL if you build for Android + . msdos/INSTALL if you build for MS-DOS + + +BASIC INSTALLATION + +On most Unix systems, you build Emacs by first running the 'configure' +shell script. This attempts to deduce the correct values for +various system-dependent variables and features, and find the +directories where certain system headers and libraries are kept. +In a few cases, you may need to explicitly tell configure where to +find some things, or what options to use. + +'configure' creates a 'Makefile' in several subdirectories, and a +'src/config.h' file containing system-dependent definitions. +Running the 'make' utility then builds the package for your system. + +Building Emacs requires GNU make, . +On most systems that Emacs supports, this is the default 'make' program. + +Here's the procedure to build Emacs using 'configure' on systems which +are supported by it. In some cases, if the simplified procedure fails, +you might need to use various non-default options, and maybe perform +some of the steps manually. The more detailed description in the other +sections of this guide will help you do that, so please refer to those +sections if you need to. + + 1. Obtain and unpack the Emacs release, with commands like this: + + wget https://ftp.gnu.org/gnu/emacs/emacs-VERSION.tar.xz + tar -xf emacs-VERSION.tar.xz + + where VERSION is the Emacs version number. + + 2a. 'cd' to the directory where you unpacked Emacs and invoke the + 'configure' script: + + ./configure + + 2b. Alternatively, create a separate directory, outside the source + directory, where you want to build Emacs, and invoke 'configure' + from there: + + SOURCE-DIR/configure + + where SOURCE-DIR is the top-level Emacs source directory. + + 2c. If you don't have write access to the default directory where + Emacs and its data files will be installed, specify an alternative + installation directory: + + ./configure --prefix=/SOME/OTHER/DIRECTORY + + where /SOME/OTHER/DIRECTORY is a directory writable by your user, + for example, a subdirectory of your home directory. + + 3. When 'configure' finishes, it prints several lines of details + about the system configuration. Read those details carefully + looking for anything suspicious, such as wrong CPU and operating + system names, wrong places for headers or libraries, missing + libraries that you know are installed on your system, etc. + + If you find anything wrong, you may have to pass to 'configure' + one or more options specifying the explicit machine configuration + name, where to find various headers and libraries, etc. + Refer to the section DETAILED BUILDING AND INSTALLATION below. + + If 'configure' didn't find some image support libraries, such as + Xpm and jpeg, refer to "Image support libraries" below. + + If the details printed by 'configure' don't make any sense to + you, but there are no obvious errors, assume that 'configure' did + its job and proceed. + + 4. Invoke the 'make' program: + + make + + 5. If 'make' succeeds, it will build an executable program 'emacs' + in the 'src' directory. You can try this program, to make sure + it works: + + src/emacs -Q + + To test Emacs further (intended mostly to help developers): + + make check + + 6. Assuming that the program 'src/emacs' starts and displays its + opening screen, you can install the program and its auxiliary + files into their installation directories: + + make install + + You are now ready to use Emacs. If you wish to conserve space, + you may remove the program binaries and object files from the + directory where you built Emacs: + + make clean + + You can delete the entire build directory if you do not plan to + build Emacs again, but it can be useful to keep for debugging. + If you want to build Emacs again with different configure options, + first clean the source directories: + + make distclean + + Note that the install automatically saves space by compressing + (provided you have the 'gzip' program) those installed Lisp source (.el) + files that have corresponding .elc versions, as well as the Info files. + + You can read a brief summary about common make targets: + + make help + + +ADDITIONAL DISTRIBUTION FILES + +* Complex Text Layout support libraries + +On GNU and Unix systems, Emacs needs optional libraries to correctly +display such complex scripts as Indic and Khmer, and also for scripts +that require Arabic shaping support (Arabic and Farsi). If the +HarfBuzz library is installed, Emacs will build with it and use it for +this purpose. HarfBuzz is the preferred shaping engine, both on Posix +hosts and on MS-Windows, so we recommend installing it before building +Emacs. The alternative for GNU/Linux and Posix systems is to use the +"m17n-db", "libm17n-flt", and "libotf" libraries. (On some systems, +particularly GNU/Linux, these libraries may be already present or +available as additional packages.) Note that if there is a separate +'dev' or 'devel' package, for use at compilation time rather than run +time, you will need that as well as the corresponding run time +package; typically the dev package will contain header files and a +library archive. On MS-Windows, if HarfBuzz is not available, Emacs +will use the Uniscribe shaping engine that is part of the OS. + +Note that Emacs cannot support complex scripts on a TTY, unless the +terminal includes such a support. However, most modern terminal +emulators, such as xterm, do support such scripts. diff --git a/test/lisp/dabbrev-resources/dabbrev-expand.el b/test/lisp/dabbrev-resources/dabbrev-expand.el new file mode 100644 index 00000000000..c986b0ed633 --- /dev/null +++ b/test/lisp/dabbrev-resources/dabbrev-expand.el @@ -0,0 +1,132 @@ +(defun dabbrev-expand (arg) + "Expand previous word \"dynamically\". + +Expands to the most recent, preceding word for which this is a prefix. +If no suitable preceding word is found, words following point are +considered. If still no suitable word is found, then look in the +buffers accepted by the function pointed out by variable +`dabbrev-friend-buffer-function', if `dabbrev-check-other-buffers' +says so. Then, if `dabbrev-check-all-buffers' is non-nil, look in +all the other buffers, subject to constraints specified +by `dabbrev-ignored-buffer-names' and `dabbrev-ignored-buffer-regexps'. + +A positive prefix argument, N, says to take the Nth backward *distinct* +possibility. A negative argument says search forward. + +If the cursor has not moved from the end of the previous expansion and +no argument is given, replace the previously-made expansion +with the next possible expansion not yet tried. + +The variable `dabbrev-backward-only' may be used to limit the +direction of search to backward if set non-nil. + +See also `dabbrev-abbrev-char-regexp' and \\[dabbrev-completion]." + (interactive "*P") + (let (abbrev record-case-pattern + expansion old direction (orig-point (point))) + ;; abbrev -- the abbrev to expand + ;; expansion -- the expansion found (eventually) or nil until then + ;; old -- the text currently in the buffer + ;; (the abbrev, or the previously-made expansion) + (save-excursion + (if (and (null arg) + (markerp dabbrev--last-abbrev-location) + (marker-position dabbrev--last-abbrev-location) + (or (eq last-command this-command) + (and (window-minibuffer-p) + (= dabbrev--last-abbrev-location + (point))))) + ;; Find a different expansion for the same abbrev as last time. + (progn + (setq abbrev dabbrev--last-abbreviation) + (setq old dabbrev--last-expansion) + (setq direction dabbrev--last-direction)) + ;; If the user inserts a space after expanding + ;; and then asks to expand again, always fetch the next word. + (if (and (eq (preceding-char) ?\s) + (markerp dabbrev--last-abbrev-location) + (marker-position dabbrev--last-abbrev-location) + (= (point) (1+ dabbrev--last-abbrev-location))) + (progn + ;; The "abbrev" to expand is just the space. + (setq abbrev " ") + (save-excursion + (save-restriction + (widen) + (if (buffer-live-p dabbrev--last-buffer) + (set-buffer dabbrev--last-buffer)) + ;; Find the end of the last "expansion" word. + (if (or (eq dabbrev--last-direction 1) + (and (eq dabbrev--last-direction 0) + (< dabbrev--last-expansion-location (point)))) + (setq dabbrev--last-expansion-location + (+ dabbrev--last-expansion-location + (length dabbrev--last-expansion)))) + (goto-char dabbrev--last-expansion-location) + ;; Take the following word, with intermediate separators, + ;; as our expansion this time. + (re-search-forward + (concat "\\(?:" dabbrev--abbrev-char-regexp "\\)+")) + (setq expansion (buffer-substring-no-properties + dabbrev--last-expansion-location (point))) + + ;; Record the end of this expansion, in case we repeat this. + (setq dabbrev--last-expansion-location (point)))) + ;; Indicate that dabbrev--last-expansion-location is + ;; at the end of the expansion. + (setq dabbrev--last-direction -1)) + + ;; We have a different abbrev to expand. + (dabbrev--reset-global-variables) + (setq direction (if (null arg) + (if dabbrev-backward-only 1 0) + (prefix-numeric-value arg))) + (setq abbrev (dabbrev--abbrev-at-point)) + (setq record-case-pattern t) + (setq old nil))) + + ;;-------------------------------- + ;; Find the expansion + ;;-------------------------------- + (or expansion + (setq expansion + (dabbrev--find-expansion + abbrev direction + (dabbrev--ignore-case-p abbrev))))) + (cond + ((not expansion) + (dabbrev--reset-global-variables) + (if old + (save-excursion + (setq buffer-undo-list (cons orig-point buffer-undo-list)) + ;; Put back the original abbrev with its original case pattern. + (search-backward old) + (insert abbrev) + (delete-region (point) (+ (point) (length old))))) + (user-error "No%s dynamic expansion for `%s' found" + (if old " further" "") abbrev)) + (t + (if (not (or (eq dabbrev--last-buffer dabbrev--last-buffer-found) + (minibuffer-window-active-p (selected-window)))) + (progn + (when (buffer-name dabbrev--last-buffer) + (message "Expansion found in `%s'" + (buffer-name dabbrev--last-buffer))) + (setq dabbrev--last-buffer-found dabbrev--last-buffer)) + (message nil)) + (if (and (or (eq (current-buffer) dabbrev--last-buffer) + (null dabbrev--last-buffer) + (buffer-live-p dabbrev--last-buffer)) + (numberp dabbrev--last-expansion-location) + (and (> dabbrev--last-expansion-location (point)))) + (setq dabbrev--last-expansion-location + (copy-marker dabbrev--last-expansion-location))) + ;; Success: stick it in and return. + (setq buffer-undo-list (cons orig-point buffer-undo-list)) + (setq expansion (dabbrev--substitute-expansion old abbrev expansion + record-case-pattern)) + + ;; Save state for re-expand. + (setq dabbrev--last-expansion expansion) + (setq dabbrev--last-abbreviation abbrev) + (setq dabbrev--last-abbrev-location (point-marker)))))) diff --git a/test/lisp/dabbrev-tests.el b/test/lisp/dabbrev-tests.el index c7574403949..987106aa5af 100644 --- a/test/lisp/dabbrev-tests.el +++ b/test/lisp/dabbrev-tests.el @@ -25,6 +25,7 @@ ;;; Code: (require 'ert) +(require 'ert-x) (require 'dabbrev) (ert-deftest dabbrev-expand-test () @@ -68,4 +69,210 @@ multiple expansions." (execute-kbd-macro (kbd "C-u C-u C-M-/"))) (should (string= (buffer-string) "abc\na"))))) +(defmacro with-dabbrev-test (&rest body) + "Set up an isolated `dabbrev' test environment." + (declare (debug (body))) + `(ert-with-temp-directory dabbrev-test-home + (let* (;; Since we change HOME, clear this to avoid a conflict + ;; e.g. if Emacs runs within the user's home directory. + (abbreviated-home-dir nil) + (process-environment (cons (format "HOME=%s" dabbrev-test-home) + process-environment)) + (dabbrev-directory (ert-resource-directory))) + (unwind-protect + (progn ,@body) + ;; Restore pre-test-run state of test files. + (dolist (f (directory-files dabbrev-directory)) + (let ((buf (get-file-buffer f))) + (when buf + (with-current-buffer buf + (restore-buffer-modified-p nil) + (kill-buffer))))) + (dabbrev--reset-global-variables))))) + +(ert-deftest dabbrev-expand-test-same-buffer-1 () + "Test expanding a string twice within a single buffer. +The first expansion should expand the input (a prefix-string) to a +string in the buffer containing no whitespace character, the second +expansion, after adding a space to the first expansion, should extend +the string with the following string in the buffer up to the next +whitespace character." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-max)) + (terpri) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")))) + +(ert-deftest dabbrev-expand-test-same-buffer-2 () + "Test expanding a string plus space twice within a single buffer. +Each expansion should extend the string with the following string in the +buffer up to the next whitespace character." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-max)) + (terpri) + (execute-kbd-macro (kbd "Indic SPC M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and Khmer")))) + +(ert-deftest dabbrev-expand-test-same-buffer-3 () + "Test replacing an expansion within a single buffer." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-max)) + (terpri) + (insert-file-contents (ert-resource-file "dabbrev-expand.el")) + (goto-char (point-max)) + (terpri) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indicate")) + (kill-whole-line) + (execute-kbd-macro (kbd "Ind M-/ M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and")))) + +(ert-deftest dabbrev-expand-test-same-buffer-4 () + "Test expanding a string in a narrowed-region." + (with-dabbrev-test + (let (disabled-command-function) ; Enable narrow-to-region. + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-min)) + (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n")) + (goto-char (point-max)) + (terpri) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-substring (pos-bol) (pos-eol)) "Indic and"))))) + +(ert-deftest dabbrev-expand-test-other-buffer-1 () + "Test expanding a prefix string to a string from another buffer." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (switch-to-buffer (get-buffer-create "a" t)) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-string) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-string) "Indic and")) + (kill-buffer "a"))) + +(ert-deftest dabbrev-expand-test-other-buffer-2 () + "Test expanding a string + space to a string from another buffer." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (switch-to-buffer (get-buffer-create "a" t)) + (execute-kbd-macro (kbd "Indic SPC M-/")) + (should (string= (buffer-string) "Indic and")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-string) "Indic and Khmer")) + (kill-buffer "a"))) + +(ert-deftest dabbrev-expand-test-other-buffer-3 () + "Test replacing an expansion with three different buffers. +A prefix string in a buffer should find the first expansion in a +different buffer and then find a replacement expansion is yet another +buffer." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (find-file (ert-resource-file "dabbrev-expand.el")) + (switch-to-buffer (get-buffer-create "a" t)) + (emacs-lisp-mode) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-string) "Indicate")) + (erase-buffer) + (execute-kbd-macro (kbd "Ind M-/ M-/")) + (should (string= (buffer-string) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-string) "Indic and")) + (kill-buffer "a"))) + +(ert-deftest dabbrev-expand-test-other-buffer-4 () + "Test expanding a string using another narrowed buffer." + (with-dabbrev-test + (let (disabled-command-function) ; Enable narrow-to-region. + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-min)) + (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n")) + (switch-to-buffer (get-buffer-create "a" t)) + (execute-kbd-macro (kbd "Ind M-/")) + (should (string= (buffer-string) "Indic")) + (execute-kbd-macro (kbd "SPC M-/")) + (should (string= (buffer-string) "Indic and")) + (kill-buffer "a")))) + +(ert-deftest dabbrev-expand-test-minibuffer-1 () + "Test expanding a prefix string twice in the minibuffer. +Both expansions should come from the buffer from which the minibuffer +was entered." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (with-selected-window (minibuffer-window) + (insert "Ind") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic")) + (insert " ") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic and")) + (delete-minibuffer-contents)))) + +(ert-deftest dabbrev-expand-test-minibuffer-2 () + "Test expanding a string + space in the minibuffer. +The expansions should come from the buffer from which the minibuffer was +entered." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (with-selected-window (minibuffer-window) + (insert "Indic ") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic and")) + (insert " ") + (dabbrev-expand nil) + (should (string= (buffer-string) "Indic and Khmer")) + (delete-minibuffer-contents)))) + +;; FIXME: Why is dabbrev--reset-global-variables needed here? +(ert-deftest dabbrev-expand-test-minibuffer-3 () + "Test replacing an expansion in the minibuffer using two buffers. +The first expansion should befound in the buffer from which the +minibuffer was entered, the replacement should found in another buffer." + (with-dabbrev-test + (find-file (ert-resource-file "INSTALL_BEGIN")) + (find-file (ert-resource-file "dabbrev-expand.el")) + (with-selected-window (minibuffer-window) + (insert "Ind") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indicate")) + (kill-whole-line) + (dabbrev--reset-global-variables) + (insert "Ind") + (dabbrev-expand nil) + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic")) + (dabbrev--reset-global-variables) + (insert " ") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic and")) + (delete-minibuffer-contents)))) + +(ert-deftest dabbrev-expand-test-minibuffer-4 () + "Test expansion in the minibuffer using another narrowed buffer." + (with-dabbrev-test + (let (disabled-command-function) ; Enable narrow-to-region. + (find-file (ert-resource-file "INSTALL_BEGIN")) + (goto-char (point-min)) + (execute-kbd-macro (kbd "C-s Ind M-a C-SPC M-} C-x n n"))) + (with-selected-window (minibuffer-window) + (insert "Ind") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic")) + (insert " ") + (dabbrev-expand nil) + (should (string= (minibuffer-contents) "Indic and")) + (delete-minibuffer-contents)))) + ;;; dabbrev-tests.el ends here commit 3101c5031e6eae31ac64392f312091ffa9bbd777 Author: Yuan Fu Date: Wed Oct 30 18:18:50 2024 -0700 Fix undefined variable in previous commit (bug#73900) I somehow thought allow-auto-fill is a global variable that's used by cc. But it's not. It's just a function param used by c-indent-new-comment-line. * lisp/progmodes/c-ts-common.el: (c-ts-common-comment-indent-new-line): Remove reference to allow-auto-fill. diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 6972cfa8904..8630598708d 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -307,7 +307,7 @@ and /* */ comments. SOFT works the same as in (delete-horizontal-space) (if soft (insert-and-inherit ?\n) - (newline (if allow-auto-fill nil 1)))))) + (newline 1))))) (cond ;; Line starts with //, or ///, or ////... ;; Or //! (used in rust). commit e6a8492fabc1e7065983fbf6506a2790c137cd9f Author: Yuan Fu Date: Tue Oct 29 00:27:34 2024 -0700 Fix c-ts-common-comment-indent-new-line (bug#73900) * lisp/progmodes/c-ts-common.el: (c-ts-common-comment-indent-new-line): Delete trailing whitespace before inserting newline. The insert-line-break function is the same as in c-indent-new-comment-line. diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el index 2ee150748c5..6972cfa8904 100644 --- a/lisp/progmodes/c-ts-common.el +++ b/lisp/progmodes/c-ts-common.el @@ -302,55 +302,61 @@ and /* */ comments. SOFT works the same as in ;; is a // comment, insert a newline and a // prefix; if the current ;; line is in a /* comment, insert a newline and a * prefix. No ;; auto-fill or other smart features. - (cond - ;; Line starts with //, or ///, or ////... - ;; Or //! (used in rust). - ((save-excursion - (beginning-of-line) - (re-search-forward - (rx "//" (group (* (any "/!")) (* " "))) - (line-end-position) - t nil)) - (let ((offset (- (match-beginning 0) (line-beginning-position))) - (whitespaces (match-string 1))) - (if soft (insert-and-inherit ?\n) (newline 1)) - (delete-region (line-beginning-position) (point)) - (insert (make-string offset ?\s) "//" whitespaces))) - - ;; Line starts with /* or /**. - ((save-excursion - (beginning-of-line) - (re-search-forward - (rx "/*" (group (? "*") (* " "))) - (line-end-position) - t nil)) - (let ((offset (- (match-beginning 0) (line-beginning-position))) - (whitespace-and-star-len (length (match-string 1)))) - (if soft (insert-and-inherit ?\n) (newline 1)) - (delete-region (line-beginning-position) (point)) - (insert - (make-string offset ?\s) - " *" - (make-string whitespace-and-star-len ?\s)))) - - ;; Line starts with *. - ((save-excursion - (beginning-of-line) - (looking-at (rx (group (* " ") (any "*|") (* " "))))) - (let ((prefix (match-string 1))) - (if soft (insert-and-inherit ?\n) (newline 1)) - (delete-region (line-beginning-position) (point)) - (insert prefix))) - - ;; Line starts with whitespaces or no space. This is basically the - ;; default case since (rx (* " ")) matches anything. - ((save-excursion - (beginning-of-line) - (looking-at (rx (* " ")))) - (let ((whitespaces (match-string 0))) - (if soft (insert-and-inherit ?\n) (newline 1)) - (delete-region (line-beginning-position) (point)) - (insert whitespaces))))) + (let ((insert-line-break + (lambda () + (delete-horizontal-space) + (if soft + (insert-and-inherit ?\n) + (newline (if allow-auto-fill nil 1)))))) + (cond + ;; Line starts with //, or ///, or ////... + ;; Or //! (used in rust). + ((save-excursion + (beginning-of-line) + (re-search-forward + (rx "//" (group (* (any "/!")) (* " "))) + (line-end-position) + t nil)) + (let ((offset (- (match-beginning 0) (line-beginning-position))) + (whitespaces (match-string 1))) + (funcall insert-line-break) + (delete-region (line-beginning-position) (point)) + (insert (make-string offset ?\s) "//" whitespaces))) + + ;; Line starts with /* or /**. + ((save-excursion + (beginning-of-line) + (re-search-forward + (rx "/*" (group (? "*") (* " "))) + (line-end-position) + t nil)) + (let ((offset (- (match-beginning 0) (line-beginning-position))) + (whitespace-and-star-len (length (match-string 1)))) + (funcall insert-line-break) + (delete-region (line-beginning-position) (point)) + (insert + (make-string offset ?\s) + " *" + (make-string whitespace-and-star-len ?\s)))) + + ;; Line starts with *. + ((save-excursion + (beginning-of-line) + (looking-at (rx (group (* " ") (any "*|") (* " "))))) + (let ((prefix (match-string 1))) + (funcall insert-line-break) + (delete-region (line-beginning-position) (point)) + (insert prefix))) + + ;; Line starts with whitespaces or no space. This is basically the + ;; default case since (rx (* " ")) matches anything. + ((save-excursion + (beginning-of-line) + (looking-at (rx (* " ")))) + (let ((whitespaces (match-string 0))) + (funcall insert-line-break) + (delete-region (line-beginning-position) (point)) + (insert whitespaces)))))) ;;; Statement indent commit df5ac0daf0fde7766ce607bd4c52a16650f3ac0f Author: Yuan Fu Date: Mon Oct 28 19:30:52 2024 -0700 Fix the call to treesit-thing-defined-p * lisp/treesit.el (treesit-defun-at-point): Add the necessary 2nd argument. diff --git a/lisp/treesit.el b/lisp/treesit.el index 9ac470691d6..2518204ce93 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -2823,7 +2823,9 @@ is `nested'. Return nil if `treesit-defun-type-regexp' isn't set and `defun' isn't defined in `treesit-thing-settings'." - (when (or treesit-defun-type-regexp (treesit-thing-defined-p 'defun)) + (when (or treesit-defun-type-regexp + (treesit-thing-defined-p + 'defun (treesit-language-at (point)))) (treesit-thing-at-point (or treesit-defun-type-regexp 'defun) treesit-defun-tactic))) commit 7a3c10dcb56f7287158d155edba04bf80316fbe6 Author: Juri Linkov Date: Wed Oct 30 20:32:28 2024 +0200 Backport: Call tab-bar-tab-post-open-functions during tabs initialization * lisp/tab-bar.el (tab-bar-tabs): Run the hook 'tab-bar-tab-post-open-functions' after creating the first tab in the selected frame's tab-bar list of tabs (bug#74087). Suggested by Ship Mints . (cherry picked from commit 2c062dfdf50970766db179ccbad7ce71c541cd72) diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el index ea36a924c78..e8c6b7f3bcc 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -803,7 +803,9 @@ Return its existing value or a new value." (funcall tab-bar-tab-name-function)))) ;; Create default tabs (setq tabs (list (tab-bar--current-tab-make))) - (tab-bar-tabs-set tabs frame)) + (tab-bar-tabs-set tabs frame) + (run-hook-with-args 'tab-bar-tab-post-open-functions + (car tabs))) tabs)) (defun tab-bar-tabs-set (tabs &optional frame) commit 98796f95fa5ce7c38074429517c477cd01b0be37 Author: Laurence Warne Date: Wed Oct 30 15:12:13 2024 +0100 Work on proced-tests.el * test/lisp/proced-tests.el (proced--assert-process-valid-cpu-refinement-explainer): New function for explaining refinement test failures in greater detail. diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el index b612e172ffb..9036c15271c 100644 --- a/test/lisp/proced-tests.el +++ b/test/lisp/proced-tests.el @@ -50,7 +50,24 @@ (defun proced--assert-process-valid-cpu-refinement (cpu) "Fail unless the process at point could be present after a refinement using CPU." (proced--move-to-column "%CPU") - (should (>= (thing-at-point 'number) cpu))) + (>= (thing-at-point 'number) cpu)) + +(defun proced--assert-process-valid-cpu-refinement-explainer (cpu) + "Explain the result of `proced--assert-process-valid-cpu-refinement'. + +CPU is as in `proced--assert-process-valid-cpu-refinement'." + `(unexpected-refinement + (header-line + ,(substring-no-properties + (string-replace "%%" "%" (cadr (proced-header-line))))) + (process ,(thing-at-point 'line t)) + (refined-value ,cpu) + (process-value + ,(save-excursion + (proced--move-to-column "%CPU") (thing-at-point 'number))))) + +(put #'proced--assert-process-valid-cpu-refinement 'ert-explainer + #'proced--assert-process-valid-cpu-refinement-explainer) (ert-deftest proced-format-test () (dolist (format '(short medium long verbose)) @@ -90,7 +107,7 @@ (let ((cpu (thing-at-point 'number))) (proced-refine) (while (not (eobp)) - (proced--assert-process-valid-cpu-refinement cpu) + (should (proced--assert-process-valid-cpu-refinement cpu)) (forward-line))))) (ert-deftest proced-refine-with-update-test () @@ -106,7 +123,7 @@ ;; processes again, causing the test to fail. (proced-update) (while (not (eobp)) - (proced--assert-process-valid-cpu-refinement cpu) + (should (proced--assert-process-valid-cpu-refinement cpu)) (forward-line))))) (ert-deftest proced-update-preserves-pid-at-point-test () commit 8a4d13e370cb816438816a4af77f70f4d0de9618 Author: Eli Zaretskii Date: Tue Oct 29 16:27:51 2024 +0200 ; * doc/lispref/frames.texi (Yanking Media): Add index entry. diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index fccc40d4ccc..996399fb19a 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -4720,6 +4720,7 @@ to encoding or decoding by any coding system. @node Yanking Media @section Yanking Media +@cindex yank media from window-system selections Data saved within window system selections is not restricted to plain text. It is possible for selection data to encompass images or commit 0aae02a3741c397d6952e3128d434827aca0f912 Author: Stefan Monnier Date: Mon Oct 28 22:40:15 2024 -0400 * lisp/files.el (require-with-check): Be a bit more lenient (bug74040) diff --git a/lisp/files.el b/lisp/files.el index a81f742bbb4..c3fce9f15f9 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -1277,10 +1277,27 @@ NOERROR is equal to `reload'), or otherwise emit a warning." ;; file, so we're done. (when (eq lh load-history) ;; If `require' did nothing, we need to make sure that was warranted. - (let ((fn (locate-file (or filename (symbol-name feature)) - load-path (get-load-suffixes)))) + (let* ((fn (locate-file (or filename (symbol-name feature)) + load-path (get-load-suffixes) nil + )) ;; load-prefer-newer + ;; We used to look for `fn' in `load-history' with `assoc' + ;; which works in most cases, but in some cases (e.g. when + ;; `load-prefer-newer' is set) `locate-file' can return a + ;; different file than the file that `require' would load, + ;; so the file won't be found in `load-history' even though + ;; we did load "it". (bug#74040) + ;; So use a "permissive" search which doesn't pay attention to + ;; differences between file extensions. + (prefix (if (string-match + (concat (regexp-opt (get-load-suffixes)) "\\'") fn) + (concat (substring fn 0 (match-beginning 0)) ".") + fn)) + (lh load-history)) + (while (and lh (let ((file (car-safe (car lh)))) + (not (and file (string-prefix-p prefix file))))) + (setq lh (cdr lh))) (cond - ((assoc fn load-history) nil) ;We loaded the right file. + (lh nil) ;We loaded the right file. ((eq noerror 'reload) (load fn nil 'nomessage)) ((and fn (memq feature features)) (funcall (if noerror #'warn #'error) commit cc6a11f4832076acb7c0b5301eb1add026fabe4b Author: Stefan Monnier Date: Mon Oct 28 22:14:10 2024 -0400 (with-peg-rules): Fix references to rulesets (bug#74018) PEG rules get "compiled" to functions with name `peg-rule `. `define-peg-ruleset` instead defines it PEG rules with name `peg-rule `, so that they can be made visible by `with-peg-rules` simply by adding local aliases from `peg-rule ` to `peg-rule `. Apparently when I added `define-peg-ruleset` I somehow failed to install some of the corresponding code in `with-peg-rules`, so the aliases were not installed, making it "impossible" to use rulesets. [ I still have no idea how this happened and/or where the missing code went, so I "recreated" it. ] * lisp/progmodes/peg.el (with-peg-rules): Install the aliases for the rulesets. (peg--translate-rule-body): Try and preserve location info when emitting a warning. * test/lisp/progmodes/peg-tests.el (peg-test-myrules): New ruleset. (peg-test-ruleset): New test. diff --git a/lisp/progmodes/peg.el b/lisp/progmodes/peg.el index 96334162195..0b069e95563 100644 --- a/lisp/progmodes/peg.el +++ b/lisp/progmodes/peg.el @@ -412,6 +412,7 @@ sequencing `and' operator of PEG grammars." (full-rname (format "%s %s" name rname))) (push `(define-peg-rule ,full-rname . ,(cdr rule)) defs) (push `(,(peg--rule-id rname) #',(peg--rule-id full-rname)) aliases))) + (require 'cl-lib) `(cl-flet ,aliases ,@defs (eval-and-compile (put ',name 'peg--rules ',aliases))))) @@ -432,7 +433,8 @@ rulesets defined previously with `define-peg-ruleset'." (progn (push rule rulesets) nil) (cons (car rule) (peg-normalize `(and . ,(cdr rule)))))) rules))) - (ctx (assq :peg-rules macroexpand-all-environment))) + (ctx (assq :peg-rules macroexpand-all-environment)) + (body (macroexpand-all `(cl-labels ,(mapcar (lambda (rule) @@ -444,6 +446,15 @@ rulesets defined previously with `define-peg-ruleset'." ,@body) `((:peg-rules ,@(append rules (cdr ctx))) ,@macroexpand-all-environment)))) + (if (null rulesets) + body + `(cl-flet ,(mapcan (lambda (ruleset) + (let ((aliases (get ruleset 'peg--rules))) + (unless aliases + (message "Unknown PEG ruleset: %S" ruleset)) + (copy-sequence aliases))) + rulesets) + ,body)))) ;;;;; Old entry points @@ -645,7 +656,7 @@ rulesets defined previously with `define-peg-ruleset'." (code (peg-translate-exp exp))) (cond ((null msg) code) - (t (macroexp-warn-and-return msg code))))) + (t (macroexp-warn-and-return msg code 'peg nil exp))))) ;; This is the main translation function. (defun peg-translate-exp (exp) diff --git a/test/lisp/progmodes/peg-tests.el b/test/lisp/progmodes/peg-tests.el index 8fab549bcab..b9e9c47ab7c 100644 --- a/test/lisp/progmodes/peg-tests.el +++ b/test/lisp/progmodes/peg-tests.el @@ -180,6 +180,20 @@ resp. succeeded instead of signaling an error." (should (eobp))) ) +(define-peg-ruleset peg-test-myrules + (sign () (or "+" "-" "")) + (digit () [0-9]) + (nat () digit (* digit)) + (int () sign digit (* digit)) + (float () int "." nat)) + +(ert-deftest peg-test-ruleset () + (with-peg-rules + (peg-test-myrules + (complex float "+i" float)) + (should (peg-parse-string nat "123" t)) + (should (not (peg-parse-string nat "home" t))))) + ;;; Examples: ;; peg-ex-recognize-int recognizes integers. An integer begins with a commit 70f084db2ff36be2eb183a5c7f6aa88a44ff0d5e Author: Eli Zaretskii Date: Mon Oct 28 21:11:50 2024 +0200 ; * etc/NEWS: Fix typo (bug#74066). diff --git a/etc/NEWS b/etc/NEWS index c72a87787f3..ebb9d49d560 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -57,10 +57,10 @@ operating systems instead. --- ** New configuration option '--disable-gc-mark-trace'. -This disables the GC mark trace buffer for about 5 % better garbage +This disables the GC mark trace buffer for about 5% better garbage collection performance. Doing so may make it more difficult for Emacs developers to help finding GC-related bugs that you run into, which is -why it the mark trace buffer is enabled by default. +why the mark trace buffer is enabled by default. * Startup Changes in Emacs 30.1 commit 9e1abf11fc1c3285cfa631ec71f3836d54e2c8d8 Author: Stefan Monnier Date: Sun Oct 27 14:52:25 2024 -0400 Tweak doc w.r.t to "void function" (bug#73886) * doc/lispref/functions.texi (Function Cells): Avoid talking about the function cell being void. * src/data.c (Fboundp, Ffmakunbound, Fsymbol_function): Don't suggest that "void" can be considered as a kind of value. diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index bfb8789d05b..7fb9fb37c0a 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -1510,10 +1510,7 @@ indirect-function}. @kindex void-function This returns the object in the function cell of @var{symbol}. It does not check that the returned object is a legitimate function. - -If the function cell is void, the return value is @code{nil}. It is -impossible to distinguish between a function cell that is void and one -set to @code{nil}. +If the function is void, the return value is @code{nil}. @example @group @@ -1533,9 +1530,9 @@ set to @code{nil}. @end defun @cindex void function cell - If you have never given a symbol any function definition, we say -that that symbol's function cell is @dfn{void}. In other words, the -function cell does not have any Lisp object in it. If you try to call + If you have never given a symbol any function definition, its function +cell contains the default value @code{nil} and we say +that that function is @dfn{void}. If you try to call the symbol as a function, Emacs signals a @code{void-function} error. Unlike with void variables (@pxref{Void Variables}), a symbol's diff --git a/src/data.c b/src/data.c index bf83755bff3..904eaf35c1a 100644 --- a/src/data.c +++ b/src/data.c @@ -756,7 +756,7 @@ global value outside of any lexical scope. */) breaking backward compatibility, as some users of fboundp may expect t in particular, rather than any true value. */ DEFUN ("fboundp", Ffboundp, Sfboundp, 1, 1, 0, - doc: /* Return t if SYMBOL's function definition is neither void nor nil. */) + doc: /* Return t if SYMBOL's function definition is not nil. */) (Lisp_Object symbol) { CHECK_SYMBOL (symbol); @@ -785,7 +785,7 @@ DEFUN ("fmakunbound", Ffmakunbound, Sfmakunbound, 1, 1, 0, doc: /* Make SYMBOL's function definition be nil. Return SYMBOL. -If a function definition is nil or void, trying to call a function by +If a function definition is nil, trying to call a function by that name will cause a `void-function' error. For more details, see Info node `(elisp) Function Cells'. @@ -800,7 +800,7 @@ See also `makunbound'. */) } DEFUN ("symbol-function", Fsymbol_function, Ssymbol_function, 1, 1, 0, - doc: /* Return SYMBOL's function definition, or nil if that is void or nil. */) + doc: /* Return SYMBOL's function definition. */) (Lisp_Object symbol) { CHECK_SYMBOL (symbol); commit 7a8ca202c5eeb810e5f86510c3ea46d3ec519222 Author: Laurence Warne Date: Sun Oct 27 16:50:20 2024 +0100 Fix flakey proced refine tests (Bug#73441) * test/lisp/proced-tests.el (proced-refine-test) (proced-refine-with-update-test): Use the much simpler CPU refinement for testing 'proced-refine'. The previous tests made the incorrect assumption that refining on the PID of process A only filtered the buffer to contain process A and its children, whereas in actuality the children of process A's children, their children, and so on will also be shown. (proced-update-preserves-pid-at-point-test): Mark as unstable. diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el index 6f16a241146..b612e172ffb 100644 --- a/test/lisp/proced-tests.el +++ b/test/lisp/proced-tests.el @@ -43,18 +43,14 @@ (defun proced--move-to-column (attribute) "Move to the column under ATTRIBUTE in the current proced buffer." - (move-to-column (string-match attribute proced-header-line))) - -(defun proced--assert-process-valid-pid-refinement (pid) - "Fail unless the process at point could be present after a refinement using PID." - (proced--move-to-column "PID") - (let ((pid-equal (string= pid (word-at-point)))) - (should - (or pid-equal - ;; Guard against the unlikely event a platform doesn't support PPID - (when (string-match "PPID" proced-header-line) - (proced--move-to-column "PPID") - (string= pid (word-at-point))))))) + (move-to-column (string-match attribute proced-header-line)) + ;; Sometimes the column entry does not fill the whole column. + (while (= (char-after (point)) ?\s) (forward-char))) + +(defun proced--assert-process-valid-cpu-refinement (cpu) + "Fail unless the process at point could be present after a refinement using CPU." + (proced--move-to-column "%CPU") + (should (>= (thing-at-point 'number) cpu))) (ert-deftest proced-format-test () (dolist (format '(short medium long verbose)) @@ -85,26 +81,24 @@ (proced--assert-emacs-pid-in-buffer)))) (ert-deftest proced-refine-test () - ;;(skip-unless (memq system-type '(gnu/linux gnu/kfreebsd darwin))) (proced--within-buffer 'verbose 'user - ;; When refining on PID for process A, a process is kept if and only - ;; if its PID is the same as process A, or its parent process is - ;; process A. - (proced--move-to-column "PID") - (let ((pid (word-at-point))) + ;; When refining on %CPU for process A, a process is kept if and only + ;; if its %CPU is greater than or equal to that of process A. + (proced--move-to-column "%CPU") + (let ((cpu (thing-at-point 'number))) (proced-refine) (while (not (eobp)) - (proced--assert-process-valid-pid-refinement pid) + (proced--assert-process-valid-cpu-refinement cpu) (forward-line))))) (ert-deftest proced-refine-with-update-test () (proced--within-buffer 'verbose 'user - (proced--move-to-column "PID") - (let ((pid (word-at-point))) + (proced--move-to-column "%CPU") + (let ((cpu (thing-at-point 'number))) (proced-refine) ;; Don't use (proced-update t) since this will reset `proced-process-alist' ;; and it's possible the process refined on would have exited by that @@ -112,10 +106,13 @@ ;; processes again, causing the test to fail. (proced-update) (while (not (eobp)) - (proced--assert-process-valid-pid-refinement pid) + (proced--assert-process-valid-cpu-refinement cpu) (forward-line))))) (ert-deftest proced-update-preserves-pid-at-point-test () + ;; FIXME: Occasionally the cursor inexplicably changes to the first line which + ;; causes the test to file when the line isn't the Emacs process. + :tags '(:unstable) (proced--within-buffer 'medium 'user @@ -128,7 +125,7 @@ (old-window (get-buffer-window))) (select-window new-window) (with-current-buffer "*Proced*" - (proced-update t t)) + (proced-update)) (select-window old-window) (should (= pid (proced-pid-at-point))))))) commit 55a8cec013e8879da2c79cd8fbe387d8d2822166 Author: Eli Zaretskii Date: Sun Oct 27 16:07:08 2024 +0200 Another 'void' update * doc/lispref/symbols.texi (Symbol Components): Another update due to the change in 'void' function implementation. (Bug#73886) diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi index c76bf3d3820..c3dc08df2df 100644 --- a/doc/lispref/symbols.texi +++ b/doc/lispref/symbols.texi @@ -100,11 +100,11 @@ the contents of a symbol's function cell, use the function property list. To get a symbol's property list, use the function @code{symbol-plist}. @xref{Symbol Properties}. - The function cell or the value cell may be @dfn{void}, which means -that the cell does not reference any object. (This is not the same -thing as holding the symbol @code{void}, nor the same as holding the -symbol @code{nil}.) Examining a function or value cell that is void -results in an error, such as @samp{Symbol's value as variable is void}. + The value cell may be @dfn{void}, which means that the cell does not +reference any object. (This is not the same thing as holding the symbol +@code{void}, nor the same as holding the symbol @code{nil}.) Examining +a value cell that is void results in an error, such as @samp{Symbol's +value as variable is void}. Because each symbol has separate value and function cells, variables names and function names do not conflict. For example, the symbol