aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2023-02-04 19:50:00 +0800
committerPo Lu2023-02-04 19:50:00 +0800
commitbfce0ce57fe0de11a6cbe3ff878a59dd2a0853d4 (patch)
treef2debd564fd963f17ff01f36e88c8276e25248d0
parent9ffb5c0cf3e97a6579b0d07f0d9952e13c0ff605 (diff)
parent0a95a81d8d36722ccf030a6194ecd953fc257a59 (diff)
downloademacs-bfce0ce57fe0de11a6cbe3ff878a59dd2a0853d4.tar.gz
emacs-bfce0ce57fe0de11a6cbe3ff878a59dd2a0853d4.zip
Merge remote-tracking branch 'origin/master' into feature/android
-rw-r--r--admin/notes/tree-sitter/treesit_record_change50
-rw-r--r--doc/emacs/basic.texi49
-rw-r--r--doc/emacs/building.texi46
-rw-r--r--etc/NEWS.2926
-rw-r--r--lisp/bindings.el6
-rw-r--r--lisp/emacs-lisp/byte-opt.el211
-rw-r--r--lisp/emacs-lisp/lisp-mode.el1
-rw-r--r--lisp/eshell/em-cmpl.el43
-rw-r--r--lisp/faces.el11
-rw-r--r--lisp/keymap.el38
-rw-r--r--lisp/progmodes/c-ts-common.el35
-rw-r--r--lisp/progmodes/c-ts-mode.el54
-rw-r--r--lisp/progmodes/cc-engine.el60
-rw-r--r--lisp/progmodes/hideshow.el4
-rw-r--r--lisp/progmodes/ruby-ts-mode.el5
-rw-r--r--lisp/repeat.el48
-rw-r--r--lisp/simple.el22
-rw-r--r--lisp/tab-bar.el4
-rw-r--r--lisp/window.el5
-rw-r--r--src/insdel.c19
-rw-r--r--src/lisp.h3
-rw-r--r--src/search.c5
-rw-r--r--src/sqlite.c10
-rw-r--r--src/treesit.c43
-rw-r--r--src/xfaces.c3
-rw-r--r--test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts6
-rw-r--r--test/lisp/progmodes/c-ts-mode-resources/indent.erts64
27 files changed, 564 insertions, 307 deletions
diff --git a/admin/notes/tree-sitter/treesit_record_change b/admin/notes/tree-sitter/treesit_record_change
new file mode 100644
index 00000000000..bb0f9edc353
--- /dev/null
+++ b/admin/notes/tree-sitter/treesit_record_change
@@ -0,0 +1,50 @@
1NOTES ON TREESIT_RECORD_CHANGE
2
3It is vital that Emacs informs tree-sitter of every change made to the
4buffer, lest tree-sitter's parse tree would be corrupted/out of sync.
5
6All buffer changes in Emacs are made through functions in insdel.c
7(and casefiddle.c), I augmented functions in those files with calls to
8treesit_record_change. Below is a manifest of all the relavent
9functions in insdel.c as of Emacs 29:
10
11Function Calls
12----------------------------------------------------------------------
13copy_text (*1)
14insert insert_1_both
15insert_and_inherit insert_1_both
16insert_char insert
17insert_string insert
18insert_before_markers insert_1_both
19insert_before_markers_and_inherit insert_1_both
20insert_1_both treesit_record_change
21insert_from_string insert_from_string_1
22insert_from_string_before_markers insert_from_string_1
23insert_from_string_1 treesit_record_change
24insert_from_gap_1 treesit_record_change
25insert_from_gap insert_from_gap_1
26insert_from_buffer treesit_record_change
27insert_from_buffer_1 (used by insert_from_buffer) (*2)
28replace_range treesit_record_change
29replace_range_2 (caller needs to call treesit_r_c)
30del_range del_range_1
31del_range_1 del_range_2
32del_range_byte del_range_2
33del_range_both del_range_2
34del_range_2 treesit_record_change
35
36(*1) This functions is used only to copy from string to string when
37used outside of insdel.c, and when used inside insdel.c, the caller
38calls treesit_record_change.
39
40(*2) This function is a static function, and insert_from_buffer is its
41only caller. So it should be fine to call treesit_record_change in
42insert_from_buffer but not insert_from_buffer_1. I also left a
43reminder comment.
44
45
46As for casefiddle.c, do_casify_unibyte_region and
47do_casify_multibyte_region modifies buffer, but they are static
48functions and are called by casify_region, which calls
49treesit_record_change. Other higher-level functions calls
50casify_region to do the work. \ No newline at end of file
diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi
index 2cc45a8805e..a271cb65bdc 100644
--- a/doc/emacs/basic.texi
+++ b/doc/emacs/basic.texi
@@ -887,19 +887,40 @@ z z z}. The first @kbd{C-x z} repeats the command once, and each
887subsequent @kbd{z} repeats it once again. 887subsequent @kbd{z} repeats it once again.
888 888
889@findex repeat-mode 889@findex repeat-mode
890@findex describe-repeat-maps
890@vindex repeat-exit-key 891@vindex repeat-exit-key
891@vindex repeat-exit-timeout 892@vindex repeat-exit-timeout
892 Also you can activate @code{repeat-mode} that temporarily enables a 893 You can also activate @code{repeat-mode} which allows repeating
893transient mode with short keys after a limited number of commands. 894commands bound to sequences of two or more keys by typing a single
894Currently supported shorter key sequences are @kbd{C-x u u} instead of 895character. For example, after typing @w{@kbd{C-x u}} (@code{undo},
895@kbd{C-x u C-x u} to undo many changes, @kbd{C-x o o} instead of 896@pxref{Undo}) to undo the most recent edits, you can undo many more
896@kbd{C-x o C-x o} to switch several windows, @kbd{C-x @{ @{ @} @} ^ ^ 897edits by typing @w{@kbd{u u u@dots{}}}. Similarly, type @w{@kbd{C-x o
897v v} to resize the selected window interactively, @kbd{M-g n n p p} to 898o o@dots{}}} instead of @w{@kbd{C-x o C-x o C-x o@dots{}}} to switch
898navigate @code{next-error} matches, and @kbd{C-x ] ] [ [} to navigate 899to the window several windows away. This works by entering a
899through pages. Any other key exits transient mode and then is 900transient repeating mode after you type the full key sequence that
900executed normally. The user option @code{repeat-exit-key} defines an 901invokes the command; the single-key shortcuts are shown in the echo
901additional key to exit this transient mode. Also it's possible to 902area.
902break the repetition chain automatically after some idle time by 903
903customizing the user option @code{repeat-exit-timeout} to specify the 904Only some commands support repetition in @code{repeat-mode}; type
904idle time in seconds after which this transient mode will be turned 905@w{@kbd{M-x describe-repeat-maps @key{RET}}} to see which ones.
905off. 906
907The single-character shortcuts enabled by the transient repeating mode
908do not need to be identical: for example, after typing @w{@kbd{C-x
909@{}}, either @kbd{@{} or @kbd{@}} or @kbd{^} or @kbd{v}, or any series
910that mixes these characters in any order, will resize the selected
911window in respective ways. Similarly, after @w{@kbd{M-g n}} or
912@kbd{M-g p}, typing any sequence of @kbd{n} and/or @kbd{p} in any mix
913will repeat @code{next-error} and @code{previous-error} to navigate in
914a @file{*compilation*} or @file{*grep*} buffer (@pxref{Compilation
915Mode}).
916
917Typing any key other than those defined to repeat the previous command
918exits the transient repeating mode, and then the key you typed is
919executed normally. You can also define a key which will exit the
920transient repeating mode @emph{without} executing the key which caused
921the exit. To this end, customize the user option
922@code{repeat-exit-key} to name a key; one natural value is @key{RET}.
923Finally, it's possible to break the repetition chain automatically
924after some amount of idle time: customize the user option
925@code{repeat-exit-timeout} to specify the idle time in seconds after
926which this transient repetition mode will be turned off automatically.
diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi
index 98f67ddd9d9..3f6a418de1a 100644
--- a/doc/emacs/building.texi
+++ b/doc/emacs/building.texi
@@ -961,9 +961,7 @@ the fringe of a source buffer to set a breakpoint there.
961@vindex gud-gdb-command-name 961@vindex gud-gdb-command-name
962 To run GDB using just the GUD interaction buffer interface, without 962 To run GDB using just the GUD interaction buffer interface, without
963these additional features, use @kbd{M-x gud-gdb} (@pxref{Starting 963these additional features, use @kbd{M-x gud-gdb} (@pxref{Starting
964GUD}). You must use this if you want to debug multiple programs 964GUD}).
965within one Emacs session, as that is currently unsupported by @kbd{M-x
966gdb}.
967 965
968 Internally, @kbd{M-x gdb} informs GDB that its screen size is 966 Internally, @kbd{M-x gdb} informs GDB that its screen size is
969unlimited; for correct operation, you must not change GDB's screen 967unlimited; for correct operation, you must not change GDB's screen
@@ -1051,9 +1049,9 @@ to restore only when @code{gdb-show-main} is non-@code{nil}.
1051 You may also specify additional GDB-related buffers to display, 1049 You may also specify additional GDB-related buffers to display,
1052either in the same frame or a different one. Select the buffers you 1050either in the same frame or a different one. Select the buffers you
1053want by typing @kbd{M-x gdb-display-@var{buffertype}-buffer} or 1051want by typing @kbd{M-x gdb-display-@var{buffertype}-buffer} or
1054@kbd{M-x gdb-frame-@var{buffertype}-buffer}, where @var{buffertype} 1052@kbd{M-x gdb-frame-@var{buffertype}-buffer}, where @var{buffertype} is
1055is the relevant buffer type, such as @samp{breakpoints}. You can do 1053the relevant buffer type, such as @samp{breakpoints} or @samp{io}.
1056the same with the menu bar, with the @samp{GDB-Windows} and 1054You can do the same from the menu bar, with the @samp{GDB-Windows} and
1057@samp{GDB-Frames} sub-menus of the @samp{GUD} menu. 1055@samp{GDB-Frames} sub-menus of the @samp{GUD} menu.
1058 1056
1059@vindex gdb-max-source-window-count 1057@vindex gdb-max-source-window-count
@@ -1273,10 +1271,14 @@ non-@code{nil} value.
1273@node Other GDB Buffers 1271@node Other GDB Buffers
1274@subsubsection Other GDB Buffers 1272@subsubsection Other GDB Buffers
1275 1273
1274Other buffers provided by @kbd{M-x gdb} whose display you can
1275optionally request include:
1276
1276@table @asis 1277@table @asis
1278@findex gdb-display-locals-buffer
1277@item Locals Buffer 1279@item Locals Buffer
1278This buffer displays the values of local variables of the current 1280This buffer displays the values of local variables of the current
1279frame for simple data types (@pxref{Frame Info, Frame Info, 1281stack frame for simple data types (@pxref{Frame Info, Frame Info,
1280Information on a frame, gdb, The GNU debugger}). Press @key{RET} or 1282Information on a frame, gdb, The GNU debugger}). Press @key{RET} or
1281click @kbd{mouse-2} on the value if you want to edit it. 1283click @kbd{mouse-2} on the value if you want to edit it.
1282 1284
@@ -1286,20 +1288,35 @@ you can examine the value of the local variable at point by typing
1286GDB, use @key{RET} or @kbd{mouse-2} on the type description 1288GDB, use @key{RET} or @kbd{mouse-2} on the type description
1287(@samp{[struct/union]} or @samp{[array]}). @xref{Watch Expressions}. 1289(@samp{[struct/union]} or @samp{[array]}). @xref{Watch Expressions}.
1288 1290
1291To display the Locals buffer, type @kbd{M-x gdb-display-locals-buffer}.
1292
1293@findex gdb-display-io-buffer
1294@item I/O Buffer
1295If the program you are debugging uses standard input and output
1296streams for interaction with the user, or emits a significant amount
1297of output to its standard output, you may wish to separate its I/O
1298from interaction with GDB. Use the command @w{@kbd{M-x
1299gdb-display-io-buffer}} to show a window with a buffer to which Emacs
1300redirects the input and output from the program you are debugging.
1301
1302@findex gdb-display-registers-buffer
1289@item Registers Buffer 1303@item Registers Buffer
1290@findex toggle-gdb-all-registers
1291This buffer displays the values held by the registers 1304This buffer displays the values held by the registers
1292(@pxref{Registers,,, gdb, The GNU debugger}). Press @key{RET} or 1305(@pxref{Registers,,, gdb, The GNU debugger}). Request the display of
1293click @kbd{mouse-2} on a register if you want to edit its value. With 1306this buffer with the command @kbd{M-x gdb-display-registers-buffer}.
1294GDB 6.4 or later, recently changed register values display with 1307Press @key{RET} or click @kbd{mouse-2} on a register if you want to
1295@code{font-lock-warning-face}. 1308edit its value. With GDB 6.4 or later, recently changed register
1309values display with @code{font-lock-warning-face}.
1296 1310
1311@findex gdb-display-disassembly-buffer
1297@item Assembler Buffer 1312@item Assembler Buffer
1298The assembler buffer displays the current frame as machine code. An 1313The assembler buffer displays the current frame as machine code. An
1299arrow points to the current instruction, and you can set and remove 1314arrow points to the current instruction, and you can set and remove
1300breakpoints as in a source buffer. Breakpoint icons also appear in 1315breakpoints as in a source buffer. Breakpoint icons also appear in
1301the fringe or margin. 1316the fringe or margin. To request the display of this buffer, use
1317@kbd{M-x gdb-display-disassembly-buffer}.
1302 1318
1319@findex gdb-display-memory-buffer
1303@item Memory Buffer 1320@item Memory Buffer
1304The memory buffer lets you examine sections of program memory 1321The memory buffer lets you examine sections of program memory
1305(@pxref{Memory, Memory, Examining memory, gdb, The GNU debugger}). 1322(@pxref{Memory, Memory, Examining memory, gdb, The GNU debugger}).
@@ -1307,7 +1324,8 @@ Click @kbd{mouse-1} on the appropriate part of the header line to
1307change the starting address or number of data items that the buffer 1324change the starting address or number of data items that the buffer
1308displays. Alternatively, use @kbd{S} or @kbd{N} respectively. Click 1325displays. Alternatively, use @kbd{S} or @kbd{N} respectively. Click
1309@kbd{mouse-3} on the header line to select the display format or unit 1326@kbd{mouse-3} on the header line to select the display format or unit
1310size for these data items. 1327size for these data items. Use @w{@kbd{M-x
1328gdb-display-memory-buffer}} to request display of this buffer.
1311@end table 1329@end table
1312 1330
1313When @code{gdb-many-windows} is non-@code{nil}, the locals buffer 1331When @code{gdb-many-windows} is non-@code{nil}, the locals buffer
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index fb211f9b7d0..e3cbeb84d30 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -563,6 +563,20 @@ The variable 'font-lock-support-mode' is occasionally useful for
563debugging purposes. It is now a regular variable (instead of a user 563debugging purposes. It is now a regular variable (instead of a user
564option) and can be set to nil to disable Just-in-time Lock mode. 564option) and can be set to nil to disable Just-in-time Lock mode.
565 565
566+++
567** The 'utf-8-auto' coding-system now produces BOM on encoding.
568This is actually a bugfix, since this is how 'utf-8-auto' was
569documented from day one; it just didn't behave according to
570documentation. It turns out some Lisp programs were using this
571coding-system on the wrong assumption that the "auto" part means some
572automagic handling of the end-of-line (EOL) format conversion; those
573program will now start to fail, because BOM signature in UTF-8 encoded
574text is rarely expected. That is the reason we mention this bugfix
575here.
576
577In general, this coding-system should probably never be used for
578encoding, only for decoding.
579
566 580
567* Changes in Emacs 29.1 581* Changes in Emacs 29.1
568 582
@@ -1339,6 +1353,18 @@ dragged.
1339Customize this option to limit the number of entries in the menu 1353Customize this option to limit the number of entries in the menu
1340"Edit → Paste from Kill Menu". The default is 60. 1354"Edit → Paste from Kill Menu". The default is 60.
1341 1355
1356---
1357** New user option 'copy-region-blink-predicate'.
1358By default, when copying a region with 'kill-ring-save', Emacs only
1359blinks point and mark when the region is not denoted visually, that
1360is, when either the region is inactive, or the 'region' face is
1361indistinguishable from the 'default' face.
1362
1363Users who would rather enable blinking unconditionally can now set
1364this user option to 'always'. To disable blinking unconditionally,
1365either set this option to 'ignore', or set 'copy-region-blink-delay'
1366to 0.
1367
1342+++ 1368+++
1343** Performing a pinch gesture on a touchpad now increases the text scale. 1369** Performing a pinch gesture on a touchpad now increases the text scale.
1344 1370
diff --git a/lisp/bindings.el b/lisp/bindings.el
index 99189d2e570..c77b64c05da 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -1011,7 +1011,7 @@ if `inhibit-field-text-motion' is non-nil."
1011;; no idea whereas to bind it. Any suggestion welcome. -stef 1011;; no idea whereas to bind it. Any suggestion welcome. -stef
1012;; (define-key ctl-x-map "U" 'undo-only) 1012;; (define-key ctl-x-map "U" 'undo-only)
1013(defvar-keymap undo-repeat-map 1013(defvar-keymap undo-repeat-map
1014 :doc "Keymap to repeat undo key sequences \\`C-x u u'. Used in `repeat-mode'." 1014 :doc "Keymap to repeat `undo' commands. Used in `repeat-mode'."
1015 :repeat t 1015 :repeat t
1016 "u" #'undo) 1016 "u" #'undo)
1017 1017
@@ -1108,7 +1108,7 @@ if `inhibit-field-text-motion' is non-nil."
1108(define-key ctl-x-map "`" 'next-error) 1108(define-key ctl-x-map "`" 'next-error)
1109 1109
1110(defvar-keymap next-error-repeat-map 1110(defvar-keymap next-error-repeat-map
1111 :doc "Keymap to repeat `next-error' key sequences. Used in `repeat-mode'." 1111 :doc "Keymap to repeat `next-error' and `previous-error'. Used in `repeat-mode'."
1112 :repeat t 1112 :repeat t
1113 "n" #'next-error 1113 "n" #'next-error
1114 "M-n" #'next-error 1114 "M-n" #'next-error
@@ -1470,7 +1470,7 @@ if `inhibit-field-text-motion' is non-nil."
1470(define-key ctl-x-map "]" 'forward-page) 1470(define-key ctl-x-map "]" 'forward-page)
1471 1471
1472(defvar-keymap page-navigation-repeat-map 1472(defvar-keymap page-navigation-repeat-map
1473 :doc "Keymap to repeat page navigation key sequences. Used in `repeat-mode'." 1473 :doc "Keymap to repeat `forward-page' and `backward-page'. Used in `repeat-mode'."
1474 :repeat t 1474 :repeat t
1475 "]" #'forward-page 1475 "]" #'forward-page
1476 "[" #'backward-page) 1476 "[" #'backward-page)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index 4d39e28fc8e..861cf95b1ff 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -72,34 +72,40 @@
72(require 'macroexp) 72(require 'macroexp)
73(eval-when-compile (require 'subr-x)) 73(eval-when-compile (require 'subr-x))
74 74
75(defun bytecomp--log-lap-arg (arg)
76 ;; Convert an argument that may be a LAP operation to something printable.
77 (cond
78 ;; Symbols are just stripped of their -byte prefix if any.
79 ((symbolp arg)
80 (intern (string-remove-prefix "byte-" (symbol-name arg))))
81 ;; Conses are assumed to be LAP ops or tags.
82 ((and (consp arg) (symbolp (car arg)))
83 (let* ((head (car arg))
84 (tail (cdr arg))
85 (op (intern (string-remove-prefix "byte-" (symbol-name head)))))
86 (cond
87 ((eq head 'TAG)
88 (format "%d:" (car tail)))
89 ((memq head byte-goto-ops)
90 (format "(%s %d)" op (cadr tail)))
91 ((memq head byte-constref-ops)
92 (format "(%s %s)"
93 (if (eq op 'constant) 'const op)
94 (if (numberp tail)
95 (format "<V%d>" tail) ; closure var reference
96 (format "%S" (car tail))))) ; actual constant
97 ;; Ops with an immediate argument.
98 ((memq op '( stack-ref stack-set call unbind
99 listN concatN insertN discardN discardN-preserve-tos))
100 (format "(%s %S)" op tail))
101 ;; Without immediate, print just the symbol.
102 (t op))))
103 ;; Anything else is printed as-is.
104 (t arg)))
105
75(defun byte-compile-log-lap-1 (format &rest args) 106(defun byte-compile-log-lap-1 (format &rest args)
76 (byte-compile-log-1 107 (byte-compile-log-1
77 (apply #'format-message format 108 (apply #'format-message format (mapcar #'bytecomp--log-lap-arg args))))
78 (let (c a)
79 (mapcar (lambda (arg)
80 (if (not (consp arg))
81 (if (and (symbolp arg)
82 (string-match "^byte-" (symbol-name arg)))
83 (intern (substring (symbol-name arg) 5))
84 arg)
85 (if (integerp (setq c (car arg)))
86 (error "Non-symbolic byte-op %s" c))
87 (if (eq c 'TAG)
88 (setq c arg)
89 (setq a (cond ((memq c byte-goto-ops)
90 (car (cdr (cdr arg))))
91 ((memq c byte-constref-ops)
92 (car (cdr arg)))
93 (t (cdr arg))))
94 (setq c (symbol-name c))
95 (if (string-match "^byte-." c)
96 (setq c (intern (substring c 5)))))
97 (if (eq c 'constant) (setq c 'const))
98 (if (and (eq (cdr arg) 0)
99 (not (memq c '(unbind call const))))
100 c
101 (format "(%s %s)" c a))))
102 args)))))
103 109
104(defmacro byte-compile-log-lap (format-string &rest args) 110(defmacro byte-compile-log-lap (format-string &rest args)
105 `(and (memq byte-optimize-log '(t byte)) 111 `(and (memq byte-optimize-log '(t byte))
@@ -2036,31 +2042,29 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2036 ;; optimized but sequences like "dup varset TAG1: discard" are not. 2042 ;; optimized but sequences like "dup varset TAG1: discard" are not.
2037 ;; You may be tempted to change this; resist that temptation. 2043 ;; You may be tempted to change this; resist that temptation.
2038 (cond 2044 (cond
2039 ;; <side-effect-free> pop --> <deleted> 2045 ;;
2040 ;; ...including: 2046 ;; PUSH(K) discard(N) --> <deleted> discard(N-K), N>K
2041 ;; const-X pop --> <deleted> 2047 ;; PUSH(K) discard(N) --> <deleted>, N=K
2042 ;; varref-X pop --> <deleted> 2048 ;; where PUSH(K) is a side-effect-free op such as const, varref, dup
2043 ;; dup pop --> <deleted> 2049 ;;
2044 ;; 2050 ((and (memq (car lap1) '(byte-discard byte-discardN))
2045 ((and (eq 'byte-discard (car lap1))
2046 (memq (car lap0) side-effect-free)) 2051 (memq (car lap0) side-effect-free))
2047 (setq keep-going t) 2052 (setq keep-going t)
2048 (setq tmp (aref byte-stack+-info (symbol-value (car lap0)))) 2053 (let* ((pushes (aref byte-stack+-info (symbol-value (car lap0))))
2049 (setq rest (cdr rest)) 2054 (pops (if (eq (car lap1) 'byte-discardN) (cdr lap1) 1))
2050 (cond ((eql tmp 1) 2055 (net-pops (- pops pushes)))
2051 (byte-compile-log-lap 2056 (cond ((= net-pops 0)
2052 " %s discard\t-->\t<deleted>" lap0) 2057 (byte-compile-log-lap " %s %s\t-->\t<deleted>" lap0 lap1)
2053 (setq lap (delq lap0 (delq lap1 lap)))) 2058 (setcdr rest (cddr rest))
2054 ((eql tmp 0) 2059 (setq lap (delq lap0 lap)))
2055 (byte-compile-log-lap 2060 ((> net-pops 0)
2056 " %s discard\t-->\t<deleted> discard" lap0) 2061 (byte-compile-log-lap
2057 (setq lap (delq lap0 lap))) 2062 " %s %s\t-->\t<deleted> discard(%d)" lap0 lap1 net-pops)
2058 ((eql tmp -1) 2063 (setcar rest (if (eql net-pops 1)
2059 (byte-compile-log-lap 2064 (cons 'byte-discard nil)
2060 " %s discard\t-->\tdiscard discard" lap0) 2065 (cons 'byte-discardN net-pops)))
2061 (setcar lap0 'byte-discard) 2066 (setcdr rest (cddr rest)))
2062 (setcdr lap0 0)) 2067 (t (error "Optimizer error: too much on the stack")))))
2063 (t (error "Optimizer error: too much on the stack"))))
2064 ;; 2068 ;;
2065 ;; goto*-X X: --> X: 2069 ;; goto*-X X: --> X:
2066 ;; 2070 ;;
@@ -2073,10 +2077,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2073 (setcar lap0 (setq tmp 'byte-discard)) 2077 (setcar lap0 (setq tmp 'byte-discard))
2074 (setcdr lap0 0)) 2078 (setcdr lap0 0))
2075 ((error "Depth conflict at tag %d" (nth 2 lap0)))) 2079 ((error "Depth conflict at tag %d" (nth 2 lap0))))
2076 (and (memq byte-optimize-log '(t byte)) 2080 (byte-compile-log-lap " %s %s\t-->\t%s %s"
2077 (byte-compile-log " (goto %s) %s:\t-->\t%s %s:" 2081 lap0 lap1 tmp lap1)
2078 (nth 1 lap1) (nth 1 lap1)
2079 tmp (nth 1 lap1)))
2080 (setq keep-going t)) 2082 (setq keep-going t))
2081 ;; 2083 ;;
2082 ;; varset-X varref-X --> dup varset-X 2084 ;; varset-X varref-X --> dup varset-X
@@ -2165,7 +2167,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2165 (eq (cdr lap0) lap2)) ; TAG X 2167 (eq (cdr lap0) lap2)) ; TAG X
2166 (let ((inverse (if (eq 'byte-goto-if-nil (car lap0)) 2168 (let ((inverse (if (eq 'byte-goto-if-nil (car lap0))
2167 'byte-goto-if-not-nil 'byte-goto-if-nil))) 2169 'byte-goto-if-not-nil 'byte-goto-if-nil)))
2168 (byte-compile-log-lap " %s %s %s:\t-->\t%s %s:" 2170 (byte-compile-log-lap " %s %s %s\t-->\t%s %s"
2169 lap0 lap1 lap2 2171 lap0 lap1 lap2
2170 (cons inverse (cdr lap1)) lap2) 2172 (cons inverse (cdr lap1)) lap2)
2171 (setq lap (delq lap0 lap)) 2173 (setq lap (delq lap0 lap))
@@ -2238,9 +2240,8 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2238 ;; 2240 ;;
2239 ((and (eq (car lap0) 'TAG) 2241 ((and (eq (car lap0) 'TAG)
2240 (eq (car lap1) 'TAG)) 2242 (eq (car lap1) 'TAG))
2241 (and (memq byte-optimize-log '(t byte)) 2243 (byte-compile-log-lap " adjacent tags %d and %d merged"
2242 (byte-compile-log " adjacent tags %d and %d merged" 2244 (nth 1 lap1) (nth 1 lap0))
2243 (nth 1 lap1) (nth 1 lap0)))
2244 (setq tmp3 lap) 2245 (setq tmp3 lap)
2245 (while (setq tmp2 (rassq lap0 tmp3)) 2246 (while (setq tmp2 (rassq lap0 tmp3))
2246 (setcdr tmp2 lap1) 2247 (setcdr tmp2 lap1)
@@ -2262,8 +2263,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2262 (cl-loop for table in byte-compile-jump-tables 2263 (cl-loop for table in byte-compile-jump-tables
2263 when (member lap0 (hash-table-values table)) 2264 when (member lap0 (hash-table-values table))
2264 return nil finally return t)) 2265 return nil finally return t))
2265 (and (memq byte-optimize-log '(t byte)) 2266 (byte-compile-log-lap " unused tag %d removed" (nth 1 lap0))
2266 (byte-compile-log " unused tag %d removed" (nth 1 lap0)))
2267 (setq lap (delq lap0 lap) 2267 (setq lap (delq lap0 lap)
2268 keep-going t)) 2268 keep-going t))
2269 ;; 2269 ;;
@@ -2351,6 +2351,40 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2351 (setcar lap0 'byte-return)) 2351 (setcar lap0 'byte-return))
2352 (setcdr lap0 (cdr tmp)) 2352 (setcdr lap0 (cdr tmp))
2353 (setq keep-going t)))) 2353 (setq keep-going t))))
2354
2355 ;;
2356 ;; OP goto(X) Y: OP X: -> Y: OP X:
2357 ;;
2358 ((and (eq (car lap1) 'byte-goto)
2359 (eq (car lap2) 'TAG)
2360 (let ((lap3 (nth 3 rest)))
2361 (and (eq (car lap0) (car lap3))
2362 (eq (cdr lap0) (cdr lap3))
2363 (eq (cdr lap1) (nth 4 rest)))))
2364 (byte-compile-log-lap " %s %s %s %s %s\t-->\t%s %s %s"
2365 lap0 lap1 lap2
2366 (nth 3 rest) (nth 4 rest)
2367 lap2 (nth 3 rest) (nth 4 rest))
2368 (setcdr rest (cddr rest))
2369 (setq lap (delq lap0 lap))
2370 (setq keep-going t))
2371
2372 ;;
2373 ;; OP const return --> const return
2374 ;; where OP is side-effect-free (or mere stack manipulation).
2375 ;;
2376 ((and (eq (car lap1) 'byte-constant)
2377 (eq (car (nth 2 rest)) 'byte-return)
2378 (or (memq (car lap0) '( byte-discard byte-discardN
2379 byte-discardN-preserve-tos
2380 byte-stack-set))
2381 (memq (car lap0) side-effect-free)))
2382 (setq keep-going t)
2383 (setq add-depth 1) ; in case we get rid of too much stack reduction
2384 (setq lap (delq lap0 lap))
2385 (byte-compile-log-lap " %s %s %s\t-->\t%s %s"
2386 lap0 lap1 (nth 2 rest) lap1 (nth 2 rest)))
2387
2354 ;; 2388 ;;
2355 ;; goto-*-else-pop X ... X: goto-if-* --> whatever 2389 ;; goto-*-else-pop X ... X: goto-if-* --> whatever
2356 ;; goto-*-else-pop X ... X: discard --> whatever 2390 ;; goto-*-else-pop X ... X: discard --> whatever
@@ -2459,12 +2493,10 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2459 (memq (car (car tmp)) 2493 (memq (car (car tmp))
2460 '(byte-goto byte-goto-if-nil byte-goto-if-not-nil 2494 '(byte-goto byte-goto-if-nil byte-goto-if-not-nil
2461 byte-goto-if-nil-else-pop))) 2495 byte-goto-if-nil-else-pop)))
2462 ;; (byte-compile-log-lap " %s %s, %s %s --> moved conditional"
2463 ;; lap0 lap1 (cdr lap0) (car tmp))
2464 (let ((newtag (byte-compile-make-tag))) 2496 (let ((newtag (byte-compile-make-tag)))
2465 (byte-compile-log-lap 2497 (byte-compile-log-lap
2466 "%s %s: ... %s: %s\t-->\t%s ... %s:" 2498 " %s %s ... %s %s\t-->\t%s ... %s"
2467 lap0 (nth 1 lap1) (nth 1 (cdr lap0)) (car tmp) 2499 lap0 lap1 (cdr lap0) (car tmp)
2468 (cons (cdr (assq (car (car tmp)) 2500 (cons (cdr (assq (car (car tmp))
2469 '((byte-goto-if-nil . byte-goto-if-not-nil) 2501 '((byte-goto-if-nil . byte-goto-if-not-nil)
2470 (byte-goto-if-not-nil . byte-goto-if-nil) 2502 (byte-goto-if-not-nil . byte-goto-if-nil)
@@ -2474,8 +2506,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2474 byte-goto-if-nil-else-pop)))) 2506 byte-goto-if-nil-else-pop))))
2475 newtag) 2507 newtag)
2476 2508
2477 (nth 1 newtag) 2509 newtag)
2478 )
2479 (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp))) 2510 (setcdr tmp (cons (setcdr lap0 newtag) (cdr tmp)))
2480 (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop) 2511 (if (eq (car (car tmp)) 'byte-goto-if-nil-else-pop)
2481 ;; We can handle this case but not the -if-not-nil case, 2512 ;; We can handle this case but not the -if-not-nil case,
@@ -2492,6 +2523,24 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2492 ) 2523 )
2493 (setq keep-going t)) 2524 (setq keep-going t))
2494 2525
2526 ;;
2527 ;; discardN-preserve-tos(X) discardN-preserve-tos(Y)
2528 ;; --> discardN-preserve-tos(X+Y)
2529 ;; where stack-set(1) is accepted as discardN-preserve-tos(1)
2530 ;;
2531 ((and (or (eq (car lap0) 'byte-discardN-preserve-tos)
2532 (and (eq (car lap0) 'byte-stack-set) (eql (cdr lap0) 1)))
2533 (or (eq (car lap1) 'byte-discardN-preserve-tos)
2534 (and (eq (car lap1) 'byte-stack-set) (eql (cdr lap1) 1))))
2535 (setq keep-going t)
2536 (let ((new-op (cons 'byte-discardN-preserve-tos
2537 ;; This happens to work even when either
2538 ;; op is stack-set(1).
2539 (+ (cdr lap0) (cdr lap1)))))
2540 (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 new-op)
2541 (setcar rest new-op)
2542 (setcdr rest (cddr rest))))
2543
2495 ;; 2544 ;;
2496 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos 2545 ;; stack-set-M [discard/discardN ...] --> discardN-preserve-tos
2497 ;; stack-set-M [discard/discardN ...] --> discardN 2546 ;; stack-set-M [discard/discardN ...] --> discardN
@@ -2530,7 +2579,7 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2530 ;; 2579 ;;
2531 ;; discardN-preserve-tos return --> return 2580 ;; discardN-preserve-tos return --> return
2532 ;; dup return --> return 2581 ;; dup return --> return
2533 ;; stack-set-N return --> return ; where N is TOS-1 2582 ;; stack-set(1) return --> return
2534 ;; 2583 ;;
2535 ((and (eq (car lap1) 'byte-return) 2584 ((and (eq (car lap1) 'byte-return)
2536 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup)) 2585 (or (memq (car lap0) '(byte-discardN-preserve-tos byte-dup))
@@ -2547,8 +2596,15 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2547 ;; 2596 ;;
2548 ((and (eq (car lap0) 'byte-goto) 2597 ((and (eq (car lap0) 'byte-goto)
2549 (setq tmp (cdr (memq (cdr lap0) lap))) 2598 (setq tmp (cdr (memq (cdr lap0) lap)))
2550 (memq (caar tmp) '(byte-discard byte-discardN 2599 (or (memq (caar tmp) '(byte-discard byte-discardN))
2551 byte-discardN-preserve-tos))) 2600 ;; Make sure we don't hoist a discardN-preserve-tos
2601 ;; that really should be merged or deleted instead.
2602 (and (eq (caar tmp) 'byte-discardN-preserve-tos)
2603 (let ((next (cadr tmp)))
2604 (not (or (memq (car next) '(byte-discardN-preserve-tos
2605 byte-return))
2606 (and (eq (car next) 'byte-stack-set)
2607 (eql (cdr next) 1))))))))
2552 (byte-compile-log-lap 2608 (byte-compile-log-lap
2553 " goto-X .. X: \t-->\t%s goto-X.. X: %s Y:" 2609 " goto-X .. X: \t-->\t%s goto-X.. X: %s Y:"
2554 (car tmp) (car tmp)) 2610 (car tmp) (car tmp))
@@ -2563,11 +2619,16 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2563 2619
2564 ;; 2620 ;;
2565 ;; const discardN-preserve-tos ==> discardN const 2621 ;; const discardN-preserve-tos ==> discardN const
2622 ;; const stack-set(1) ==> discard const
2566 ;; 2623 ;;
2567 ((and (eq (car lap0) 'byte-constant) 2624 ((and (eq (car lap0) 'byte-constant)
2568 (eq (car lap1) 'byte-discardN-preserve-tos)) 2625 (or (eq (car lap1) 'byte-discardN-preserve-tos)
2626 (and (eq (car lap1) 'byte-stack-set)
2627 (eql (cdr lap1) 1))))
2569 (setq keep-going t) 2628 (setq keep-going t)
2570 (let ((newdiscard (cons 'byte-discardN (cdr lap1)))) 2629 (let ((newdiscard (if (eql (cdr lap1) 1)
2630 (cons 'byte-discard nil)
2631 (cons 'byte-discardN (cdr lap1)))))
2571 (byte-compile-log-lap 2632 (byte-compile-log-lap
2572 " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0) 2633 " %s %s\t-->\t%s %s" lap0 lap1 newdiscard lap0)
2573 (setf (car rest) newdiscard) 2634 (setf (car rest) newdiscard)
@@ -2652,16 +2713,6 @@ If FOR-EFFECT is non-nil, the return value is assumed to be of no importance."
2652 (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0)) 2713 (setcdr lap1 (+ (if (eq (car lap0) 'byte-discard) 1 (cdr lap0))
2653 (if (eq (car lap1) 'byte-discard) 1 (cdr lap1)))) 2714 (if (eq (car lap1) 'byte-discard) 1 (cdr lap1))))
2654 (setcar lap1 'byte-discardN)) 2715 (setcar lap1 'byte-discardN))
2655
2656 ;;
2657 ;; discardN-preserve-tos-X discardN-preserve-tos-Y -->
2658 ;; discardN-preserve-tos-(X+Y)
2659 ;;
2660 ((and (eq (car lap0) 'byte-discardN-preserve-tos)
2661 (eq (car lap1) 'byte-discardN-preserve-tos))
2662 (setq lap (delq lap0 lap))
2663 (setcdr lap1 (+ (cdr lap0) (cdr lap1)))
2664 (byte-compile-log-lap " %s %s\t-->\t%s" lap0 lap1 (car rest)))
2665 ) 2716 )
2666 (setq rest (cdr rest))) 2717 (setq rest (cdr rest)))
2667 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth))) 2718 (setq byte-compile-maxdepth (+ byte-compile-maxdepth add-depth)))
diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index bacc105a214..367f59e8785 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -182,6 +182,7 @@ to a package-local <package>-loaddefs.el file.")
182;; CL 182;; CL
183(put 'defconstant 'doc-string-elt 3) 183(put 'defconstant 'doc-string-elt 3)
184(put 'defparameter 'doc-string-elt 3) 184(put 'defparameter 'doc-string-elt 3)
185(put 'defstruct 'doc-string-elt 2)
185 186
186(defvar lisp-doc-string-elt-property 'doc-string-elt 187(defvar lisp-doc-string-elt-property 'doc-string-elt
187 "The symbol property that holds the docstring position info.") 188 "The symbol property that holds the docstring position info.")
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index acbf206a3c6..2439f1ed804 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -402,31 +402,6 @@ to writing a completion function."
402 args) 402 args)
403 posns))) 403 posns)))
404 404
405(defun eshell--pcomplete-executables ()
406 "Complete amongst a list of directories and executables.
407
408Wrapper for `pcomplete-executables' or `pcomplete-dirs-or-entries',
409depending on the value of `eshell-force-execution'.
410
411Adds path prefix to candidates independent of `action' value."
412 ;; `pcomplete-entries' returns filenames without path on `action' to
413 ;; use current string directory as done in `completion-file-name-table'
414 ;; when `action' is nil to construct executable candidates.
415 (let ((table (if eshell-force-execution
416 (pcomplete-dirs-or-entries nil #'file-readable-p)
417 (pcomplete-executables))))
418 (lambda (string pred action)
419 (let ((cands (funcall table string pred action)))
420 (if (eq action t)
421 (let ((specdir (file-name-directory string)))
422 (mapcar
423 (lambda (cand)
424 (if (stringp cand)
425 (file-name-concat specdir cand)
426 cand))
427 cands))
428 cands)))))
429
430(defun eshell--complete-commands-list () 405(defun eshell--complete-commands-list ()
431 "Generate list of applicable, visible commands." 406 "Generate list of applicable, visible commands."
432 ;; Building the commands list can take quite a while, especially over Tramp 407 ;; Building the commands list can take quite a while, especially over Tramp
@@ -437,11 +412,19 @@ Adds path prefix to candidates independent of `action' value."
437 ;; we complete. Adjust `pcomplete-stub' accordingly! 412 ;; we complete. Adjust `pcomplete-stub' accordingly!
438 (if (and (> (length pcomplete-stub) 0) 413 (if (and (> (length pcomplete-stub) 0)
439 (eq (aref pcomplete-stub 0) eshell-explicit-command-char)) 414 (eq (aref pcomplete-stub 0) eshell-explicit-command-char))
440 (setq pcomplete-stub (substring pcomplete-stub 1))))) 415 (setq pcomplete-stub (substring pcomplete-stub 1))))
441 (completion-table-dynamic 416 (filename (pcomplete-arg)))
442 (lambda (filename) 417 ;; Do not use `completion-table-dynamic' when completing a command file
443 (if (file-name-directory filename) 418 ;; name since it doesn't know about boundaries and would end up doing silly
444 (eshell--pcomplete-executables) 419 ;; things like adding a SPC char when completing to "/usr/sbin/".
420 ;;
421 ;; If you work on this function, be careful not to reintroduce bug#48995.
422 (if (file-name-directory filename)
423 (if eshell-force-execution
424 (pcomplete-dirs-or-entries nil #'file-readable-p)
425 (pcomplete-executables))
426 (completion-table-dynamic
427 (lambda (filename)
445 (let* ((paths (eshell-get-path)) 428 (let* ((paths (eshell-get-path))
446 (cwd (file-name-as-directory 429 (cwd (file-name-as-directory
447 (expand-file-name default-directory))) 430 (expand-file-name default-directory)))
diff --git a/lisp/faces.el b/lisp/faces.el
index cc0b80ac45b..7fe2cccba90 100644
--- a/lisp/faces.el
+++ b/lisp/faces.el
@@ -304,7 +304,16 @@ If the optional argument FRAME is given, report on face FACE in that frame.
304If FRAME is t, report on the defaults for face FACE (for new frames). 304If FRAME is t, report on the defaults for face FACE (for new frames).
305If FRAME is omitted or nil, use the selected frame." 305If FRAME is omitted or nil, use the selected frame."
306 (let ((attrs 306 (let ((attrs
307 (delq :inherit (mapcar 'car face-attribute-name-alist))) 307 ;; The _value_ of :inherit teaches us nothing about how FACE
308 ;; looks compared to the default face. Instead, we will ask
309 ;; `face-attribute' to take inheritance into account when
310 ;; examining other attributes.
311 (delq :inherit
312 ;; A difference in extension past EOL only matters when
313 ;; relevant attributes (such as :background) also
314 ;; differ from the default; otherwise this difference
315 ;; is a false positive.
316 (delq :extend (mapcar 'car face-attribute-name-alist))))
308 (differs nil)) 317 (differs nil))
309 (while (and attrs (not differs)) 318 (while (and attrs (not differs))
310 (let* ((attr (pop attrs)) 319 (let* ((attr (pop attrs))
diff --git a/lisp/keymap.el b/lisp/keymap.el
index de90b03ba64..201a49cef8c 100644
--- a/lisp/keymap.el
+++ b/lisp/keymap.el
@@ -290,26 +290,26 @@ See `kbd' for a descripion of KEYS."
290 res))) 290 res)))
291 291
292(defun key-valid-p (keys) 292(defun key-valid-p (keys)
293 "Say whether KEYS is a valid key. 293 "Return non-nil if KEYS, a string, is a valid key sequence.
294A key is a string consisting of one or more key strokes. 294KEYS should be a string consisting of one or more key strokes,
295The key strokes are separated by single space characters. 295with a single space character separating one key stroke from another.
296 296
297Each key stroke is either a single character, or the name of an 297Each key stroke is either a single character, or the name of an
298event, surrounded by angle brackets. In addition, any key stroke 298event, surrounded by angle brackets <like-this>. In addition, any
299may be preceded by one or more modifier keys. Finally, a limited 299key stroke may be preceded by one or more modifier keys. Finally,
300number of characters have a special shorthand syntax. 300a limited number of characters have a special shorthand syntax.
301 301
302Here's some example key sequences. 302Here are some example of valid key sequences.
303 303
304 \"f\" (the key `f') 304 \"f\" (the key `f')
305 \"S o m\" (a three key sequence of the keys `S', `o' and `m') 305 \"S o m\" (a three-key sequence of the keys `S', `o' and `m')
306 \"C-c o\" (a two key sequence of the keys `c' with the control modifier 306 \"C-c o\" (a two-key sequence: the key `c' with the control modifier
307 and then the key `o') 307 followed by the key `o')
308 \"H-<left>\" (the key named \"left\" with the hyper modifier) 308 \"H-<left>\" (the function key named \"left\" with the hyper modifier)
309 \"M-RET\" (the \"return\" key with a meta modifier) 309 \"M-RET\" (the \"return\" key with a meta modifier)
310 \"C-M-<space>\" (the \"space\" key with both the control and meta modifiers) 310 \"C-M-<space>\" (the \"space\" key with both the control and meta modifiers)
311 311
312These are the characters that have shorthand syntax: 312These are the characters that have special shorthand syntax:
313NUL, RET, TAB, LFD, ESC, SPC, DEL. 313NUL, RET, TAB, LFD, ESC, SPC, DEL.
314 314
315Modifiers have to be specified in this order: 315Modifiers have to be specified in this order:
@@ -358,7 +358,7 @@ which is
358This function creates a `keyboard-translate-table' if necessary 358This function creates a `keyboard-translate-table' if necessary
359and then modifies one entry in it. 359and then modifies one entry in it.
360 360
361Both KEY and TO are strings that satisfy `key-valid-p'." 361Both KEY and TO should be specified by strings that satisfy `key-valid-p'."
362 (declare (compiler-macro 362 (declare (compiler-macro
363 (lambda (form) (keymap--compile-check from to) form))) 363 (lambda (form) (keymap--compile-check from to) form)))
364 (keymap--check from) 364 (keymap--check from)
@@ -369,7 +369,7 @@ Both KEY and TO are strings that satisfy `key-valid-p'."
369 (aset keyboard-translate-table (key-parse from) (key-parse to))) 369 (aset keyboard-translate-table (key-parse from) (key-parse to)))
370 370
371(defun keymap-lookup (keymap key &optional accept-default no-remap position) 371(defun keymap-lookup (keymap key &optional accept-default no-remap position)
372 "Return the binding for command KEY. 372 "Return the binding for command KEY in KEYMAP.
373KEY is a string that satisfies `key-valid-p'. 373KEY is a string that satisfies `key-valid-p'.
374 374
375If KEYMAP is nil, look up in the current keymaps. If non-nil, it 375If KEYMAP is nil, look up in the current keymaps. If non-nil, it
@@ -391,15 +391,15 @@ in the current keymaps. However, if the optional third argument
391NO-REMAP is non-nil, `keymap-lookup' returns the unmapped 391NO-REMAP is non-nil, `keymap-lookup' returns the unmapped
392command. 392command.
393 393
394If KEY is a key sequence initiated with the mouse, the used keymaps 394If KEY is a mouse gesture, the keymaps used depend on the clicked
395will depend on the clicked mouse position with regard to the buffer 395mouse position with regards to the buffer, and local keymaps, if any,
396and possible local keymaps on strings. 396on display and overlay strings.
397 397
398If the optional argument POSITION is non-nil, it specifies a mouse 398If the optional argument POSITION is non-nil, it specifies a mouse
399position as returned by `event-start' and `event-end', and the lookup 399position as returned by `event-start' and `event-end', and the lookup
400occurs in the keymaps associated with it instead of KEY. It can also 400occurs in the keymaps associated with it instead of KEY. It can also
401be a number or marker, in which case the keymap properties at the 401be a number or marker, in which case the keymap properties at the
402specified buffer position instead of point are used." 402specified buffer position are used instead of point."
403 (declare (compiler-macro (lambda (form) (keymap--compile-check key) form))) 403 (declare (compiler-macro (lambda (form) (keymap--compile-check key) form)))
404 (keymap--check key) 404 (keymap--check key)
405 (when (and keymap position) 405 (when (and keymap position)
@@ -475,7 +475,7 @@ If MESSAGE (and interactively), message the result."
475 475
476(defun define-keymap (&rest definitions) 476(defun define-keymap (&rest definitions)
477 "Create a new keymap and define KEY/DEFINITION pairs as key bindings. 477 "Create a new keymap and define KEY/DEFINITION pairs as key bindings.
478The new keymap is returned. 478Return the new keymap.
479 479
480Options can be given as keywords before the KEY/DEFINITION 480Options can be given as keywords before the KEY/DEFINITION
481pairs. Available keywords are: 481pairs. Available keywords are:
diff --git a/lisp/progmodes/c-ts-common.el b/lisp/progmodes/c-ts-common.el
index c13b01aae5c..8729cae4ba7 100644
--- a/lisp/progmodes/c-ts-common.el
+++ b/lisp/progmodes/c-ts-common.el
@@ -194,7 +194,8 @@ comment."
194 (when end-marker 194 (when end-marker
195 (goto-char end-marker) 195 (goto-char end-marker)
196 (delete-region (point) (+ end-len (point))) 196 (delete-region (point) (+ end-len (point)))
197 (insert (make-string end-len ?\s)))))) 197 (insert (make-string end-len ?\s)))
198 (goto-char orig-point))))
198 199
199(defun c-ts-common-comment-setup () 200(defun c-ts-common-comment-setup ()
200 "Set up local variables for C-like comment. 201 "Set up local variables for C-like comment.
@@ -280,7 +281,7 @@ special handling from our bracket-counting indent algorithm.
280 281
281This can be nil, meaning such special handling is not needed.") 282This can be nil, meaning such special handling is not needed.")
282 283
283(defun c-ts-common-statement-offset (node parent &rest _) 284(defun c-ts-common-statement-offset (node parent bol &rest _)
284 "This anchor is used for children of a statement inside a block. 285 "This anchor is used for children of a statement inside a block.
285 286
286This function basically counts the number of block nodes (i.e., 287This function basically counts the number of block nodes (i.e.,
@@ -292,18 +293,21 @@ To support GNU style, on each block level, this function also
292checks whether the opening bracket { is on its own line, if so, 293checks whether the opening bracket { is on its own line, if so,
293it adds an extra level, except for the top-level. 294it adds an extra level, except for the top-level.
294 295
295PARENT is NODE's parent." 296PARENT is NODE's parent, BOL is the beginning of non-whitespace
297characters on the current line."
296 (let ((level 0)) 298 (let ((level 0))
299 ;; If NODE is a opening/closing bracket on its own line, take off
300 ;; one level because the code below assumes NODE is a statement
301 ;; _inside_ a {} block.
302 (when (and node
303 (or (string-match-p c-ts-common-indent-block-type-regexp
304 (treesit-node-type node))
305 (save-excursion (goto-char bol) (looking-at-p "}"))))
306 (cl-decf level))
297 ;; If point is on an empty line, NODE would be nil, but we pretend 307 ;; If point is on an empty line, NODE would be nil, but we pretend
298 ;; there is a statement node. 308 ;; there is a statement node.
299 (when (null node) 309 (when (null node)
300 (setq node t)) 310 (setq node t))
301 ;; If NODE is a opening bracket on its own line, take off one
302 ;; level because the code below assumes NODE is a statement
303 ;; _inside_ a {} block.
304 (when (string-match-p c-ts-common-indent-block-type-regexp
305 (treesit-node-type node))
306 (cl-decf level))
307 ;; Go up the tree and compute indent level. 311 ;; Go up the tree and compute indent level.
308 (while (if (eq node t) 312 (while (if (eq node t)
309 (setq node parent) 313 (setq node parent)
@@ -321,9 +325,9 @@ PARENT is NODE's parent."
321 (treesit-node-parent node)))) 325 (treesit-node-parent node))))
322 ;; Case (2). 326 ;; Case (2).
323 (and parent-type 327 (and parent-type
324 (or (string-match-p 328 (string-match-p
325 c-ts-common-indent-block-type-regexp 329 c-ts-common-indent-block-type-regexp
326 parent-type)))) 330 parent-type)))
327 nil) 331 nil)
328 ;; Add a level. 332 ;; Add a level.
329 ((looking-back (rx bol (* whitespace)) 333 ((looking-back (rx bol (* whitespace))
@@ -350,13 +354,6 @@ the bracket in the body."
350 (1+ level) 354 (1+ level)
351 level))) 355 level)))
352 356
353(defun c-ts-mode--close-bracket-offset (node parent &rest _)
354 "Offset for the closing bracket, NODE.
355It's basically one level less that the statements in the block.
356PARENT is NODE's parent."
357 (- (c-ts-common-statement-offset node parent)
358 (symbol-value c-ts-common-indent-offset)))
359
360(provide 'c-ts-common) 357(provide 'c-ts-common)
361 358
362;;; c-ts-common.el ends here 359;;; c-ts-common.el ends here
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 884fe6c3f15..586849e9a3d 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -100,12 +100,11 @@ the value of SYM in `c-ts-mode' and `c++-ts-mode' buffers to VAL."
100 (setq-local treesit-simple-indent-rules 100 (setq-local treesit-simple-indent-rules
101 (treesit--indent-rules-optimize 101 (treesit--indent-rules-optimize
102 (c-ts-mode--get-indent-style 102 (c-ts-mode--get-indent-style
103 (if (eq major-mode 'c-ts-mode) 'c 'cpp)))))) 103 (if (derived-mode-p 'c-ts-mode) 'c 'cpp))))))
104 res) 104 res)
105 (let ((buffer (car buffers))) 105 (let ((buffer (car buffers)))
106 (with-current-buffer buffer 106 (with-current-buffer buffer
107 ;; FIXME: Should we use `derived-mode-p' here? 107 (if (derived-mode-p 'c-ts-mode 'c++-ts-mode)
108 (if (or (eq major-mode 'c-ts-mode) (eq major-mode 'c++-ts-mode))
109 (loop (append res (list buffer)) (cdr buffers)) 108 (loop (append res (list buffer)) (cdr buffers))
110 (loop res (cdr buffers)))))))) 109 (loop res (cdr buffers))))))))
111 110
@@ -134,24 +133,33 @@ MODE is either `c' or `cpp'."
134 (alist-get c-ts-mode-indent-style (c-ts-mode--indent-styles mode))))) 133 (alist-get c-ts-mode-indent-style (c-ts-mode--indent-styles mode)))))
135 `((,mode ,@style)))) 134 `((,mode ,@style))))
136 135
137(defun c-ts-mode-set-style () 136(defun c-ts-mode--prompt-for-style ()
138 "Set the indent style of C/C++ modes globally. 137 "Prompt for a indent style and return the symbol for it."
138 (let ((mode (if (derived-mode-p 'c-ts-mode) 'c 'c++)))
139 (intern
140 (completing-read
141 "Style: "
142 (mapcar #'car (c-ts-mode--indent-styles mode))
143 nil t nil nil "gnu"))))
144
145(defun c-ts-mode-set-style (style)
146 "Set the indent style of C/C++ modes globally to STYLE.
139 147
140This changes the current indent style of every C/C++ buffer and 148This changes the current indent style of every C/C++ buffer and
141the default C/C++ indent style in this Emacs session." 149the default C/C++ indent style in this Emacs session."
142 (interactive) 150 (interactive (list (c-ts-mode--prompt-for-style)))
143 ;; FIXME: Should we use `derived-mode-p' here? 151 (c-ts-mode--indent-style-setter 'c-ts-mode-indent-style style))
144 (or (eq major-mode 'c-ts-mode) (eq major-mode 'c++-ts-mode) 152
145 (error "Buffer %s is not a c-ts-mode (c-ts-mode-set-style)" 153(defun c-ts-mode-set-local-style (style)
146 (buffer-name))) 154 "Set the C/C++ indent style of the current buffer to STYLE."
147 (c-ts-mode--indent-style-setter 155 (interactive (list (c-ts-mode--prompt-for-style)))
148 'c-ts-mode-indent-style 156 (if (not (derived-mode-p 'c-ts-mode 'c++-ts-mode))
149 ;; NOTE: We can probably use the interactive form for this. 157 (user-error "The current buffer is not in `c-ts-mode' nor `c++-ts-mode'")
150 (intern 158 (setq-local c-ts-mode-indent-style style)
151 (completing-read 159 (setq treesit-simple-indent-rules
152 "Select style: " 160 (treesit--indent-rules-optimize
153 (mapcar #'car (c-ts-mode--indent-styles (if (eq major-mode 'c-ts-mode) 'c 'cpp))) 161 (c-ts-mode--get-indent-style
154 nil t nil nil "gnu")))) 162 (if (derived-mode-p 'c-ts-mode) 'c 'cpp))))))
155 163
156;;; Syntax table 164;;; Syntax table
157 165
@@ -254,12 +262,16 @@ MODE is either `c' or `cpp'."
254 262
255 ;; int[5] a = { 0, 0, 0, 0 }; 263 ;; int[5] a = { 0, 0, 0, 0 };
256 ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset) 264 ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
265 ;; Statement in enum.
257 ((parent-is "enumerator_list") point-min c-ts-common-statement-offset) 266 ((parent-is "enumerator_list") point-min c-ts-common-statement-offset)
267 ;; Statement in struct and union.
258 ((parent-is "field_declaration_list") point-min c-ts-common-statement-offset) 268 ((parent-is "field_declaration_list") point-min c-ts-common-statement-offset)
259 269
260 ;; {} blocks. 270 ;; Statement in {} blocks.
261 ((node-is "}") point-min c-ts-mode--close-bracket-offset)
262 ((parent-is "compound_statement") point-min c-ts-common-statement-offset) 271 ((parent-is "compound_statement") point-min c-ts-common-statement-offset)
272 ;; Closing bracket.
273 ((node-is "}") point-min c-ts-common-statement-offset)
274 ;; Opening bracket.
263 ((node-is "compound_statement") point-min c-ts-common-statement-offset) 275 ((node-is "compound_statement") point-min c-ts-common-statement-offset)
264 276
265 ,@(when (eq mode 'cpp) 277 ,@(when (eq mode 'cpp)
@@ -824,6 +836,8 @@ in your configuration."
824 (c-ts-mode--get-indent-style 'c)) 836 (c-ts-mode--get-indent-style 'c))
825 ;; Font-lock. 837 ;; Font-lock.
826 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c)) 838 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
839 ;; Navigation.
840 (setq-local treesit-defun-tactic 'top-level)
827 (treesit-major-mode-setup))) 841 (treesit-major-mode-setup)))
828 842
829;;;###autoload 843;;;###autoload
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index f1e93c1c23c..86bc35baa7c 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -10146,6 +10146,24 @@ This function might do hidden buffer changes."
10146 ;; This identifier is bound only in the inner let. 10146 ;; This identifier is bound only in the inner let.
10147 '(setq start id-start)))) 10147 '(setq start id-start))))
10148 10148
10149(defmacro c-fdoc-assymetric-space-about-asterisk ()
10150 ;; We've got a "*" at `id-start' between two identifiers, the first at
10151 ;; `type-start'. Return non-nil when there is either whitespace between the
10152 ;; first id and the "*" or between the "*" and the second id, but not both.
10153 `(let ((space-before-id
10154 (save-excursion
10155 (goto-char id-start) ; Position of "*".
10156 (and (> (skip-chars-forward "* \t\n\r") 0)
10157 (memq (char-before) '(?\ ?\t ?\n ?\r)))))
10158 (space-after-type
10159 (save-excursion
10160 (goto-char type-start)
10161 (and (c-forward-type nil t)
10162 (or (eolp)
10163 (memq (char-after) '(?\ ?\t)))))))
10164 (not (eq (not space-before-id)
10165 (not space-after-type)))))
10166
10149(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end 10167(defun c-forward-decl-or-cast-1 (preceding-token-end context last-cast-end
10150 &optional inside-macro) 10168 &optional inside-macro)
10151 ;; Move forward over a declaration or a cast if at the start of one. 10169 ;; Move forward over a declaration or a cast if at the start of one.
@@ -11166,19 +11184,25 @@ This function might do hidden buffer changes."
11166 ;; CASE 16 11184 ;; CASE 16
11167 (when (and got-prefix-before-parens 11185 (when (and got-prefix-before-parens
11168 at-type 11186 at-type
11169 (or at-decl-end (looking-at "=[^=]"))
11170 (memq context '(nil top)) 11187 (memq context '(nil top))
11171 (or (not got-suffix) 11188 (or (not got-suffix)
11172 at-decl-start)) 11189 at-decl-start))
11173 ;; Got something like "foo * bar;". Since we're not inside 11190 ;; Got something like "foo * bar;". Since we're not inside
11174 ;; an arglist it would be a meaningless expression because 11191 ;; an arglist it would be a meaningless expression because
11175 ;; the result isn't used. We therefore choose to recognize 11192 ;; the result isn't used. We therefore choose to recognize
11176 ;; it as a declaration. We only allow a suffix (which makes 11193 ;; it as a declaration when there's "symmetrical WS" around
11177 ;; the construct look like a function call) when 11194 ;; the "*" or the flag `c-assymetry-fontification-flag' is
11178 ;; `at-decl-start' provides additional evidence that we do 11195 ;; not set. We only allow a suffix (which makes the
11179 ;; have a declaration. 11196 ;; construct look like a function call) when `at-decl-start'
11197 ;; provides additional evidence that we do have a
11198 ;; declaration.
11180 (setq maybe-expression t) 11199 (setq maybe-expression t)
11181 (throw 'at-decl-or-cast t)) 11200 (when (or (not c-asymmetry-fontification-flag)
11201 (looking-at "=[^=]")
11202 (c-fdoc-assymetric-space-about-asterisk))
11203 (when (eq at-type 'maybe)
11204 (setq unsafe-maybe t))
11205 (throw 'at-decl-or-cast t)))
11182 11206
11183 ;; CASE 17 11207 ;; CASE 17
11184 (when (and (or got-suffix-after-parens 11208 (when (and (or got-suffix-after-parens
@@ -11197,24 +11221,12 @@ This function might do hidden buffer changes."
11197 got-prefix-before-parens 11221 got-prefix-before-parens
11198 at-type 11222 at-type
11199 (or (not got-suffix) 11223 (or (not got-suffix)
11200 at-decl-start)) 11224 at-decl-start)
11201 (let ((space-before-id 11225 (c-fdoc-assymetric-space-about-asterisk))
11202 (save-excursion 11226 (when (eq at-type 'maybe)
11203 (goto-char id-start) ; Position of "*". 11227 (setq unsafe-maybe t))
11204 (and (> (skip-chars-forward "* \t\n\r") 0) 11228 (setq maybe-expression t)
11205 (memq (char-before) '(?\ ?\t ?\n ?\r))))) 11229 (throw 'at-decl-or-cast t)))
11206 (space-after-type
11207 (save-excursion
11208 (goto-char type-start)
11209 (and (c-forward-type nil t)
11210 (or (eolp)
11211 (memq (char-after) '(?\ ?\t)))))))
11212 (when (not (eq (not space-before-id)
11213 (not space-after-type)))
11214 (when (eq at-type 'maybe)
11215 (setq unsafe-maybe t))
11216 (setq maybe-expression t)
11217 (throw 'at-decl-or-cast t)))))
11218 11230
11219 ;; CASE 18 11231 ;; CASE 18
11220 (when (and at-decl-end 11232 (when (and at-decl-end
diff --git a/lisp/progmodes/hideshow.el b/lisp/progmodes/hideshow.el
index c160e6ad1df..b878986d7a4 100644
--- a/lisp/progmodes/hideshow.el
+++ b/lisp/progmodes/hideshow.el
@@ -256,10 +256,14 @@ This has effect only if `search-invisible' is set to `open'."
256(defvar hs-special-modes-alist 256(defvar hs-special-modes-alist
257 (mapcar #'purecopy 257 (mapcar #'purecopy
258 '((c-mode "{" "}" "/[*/]" nil nil) 258 '((c-mode "{" "}" "/[*/]" nil nil)
259 (c-ts-mode "{" "}" "/[*/]" nil nil)
259 (c++-mode "{" "}" "/[*/]" nil nil) 260 (c++-mode "{" "}" "/[*/]" nil nil)
261 (c++-ts-mode "{" "}" "/[*/]" nil nil)
260 (bibtex-mode ("@\\S(*\\(\\s(\\)" 1)) 262 (bibtex-mode ("@\\S(*\\(\\s(\\)" 1))
261 (java-mode "{" "}" "/[*/]" nil nil) 263 (java-mode "{" "}" "/[*/]" nil nil)
264 (java-ts-mode "{" "}" "/[*/]" nil nil)
262 (js-mode "{" "}" "/[*/]" nil) 265 (js-mode "{" "}" "/[*/]" nil)
266 (js-ts-mode "{" "}" "/[*/]" nil)
263 (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil) 267 (mhtml-mode "{\\|<[^/>]*?" "}\\|</[^/>]*[^/]>" "<!--" mhtml-forward nil)
264 ;; Add more support here. 268 ;; Add more support here.
265 )) 269 ))
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 9fc0c360a2a..beaab2e76e6 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -209,9 +209,6 @@ values of OVERRIDE"
209 (treesit-fontify-with-override (max plus-1 start) (min node-end end) 209 (treesit-fontify-with-override (max plus-1 start) (min node-end end)
210 font-lock-comment-face override))) 210 font-lock-comment-face override)))
211 211
212(defun ruby-ts--builtin-method-p (node)
213 (string-match-p ruby-ts--builtin-methods (treesit-node-text node t)))
214
215(defun ruby-ts--font-lock-settings (language) 212(defun ruby-ts--font-lock-settings (language)
216 "Tree-sitter font-lock settings for Ruby." 213 "Tree-sitter font-lock settings for Ruby."
217 (treesit-font-lock-rules 214 (treesit-font-lock-rules
@@ -340,7 +337,7 @@ values of OVERRIDE"
340 :language language 337 :language language
341 :feature 'builtin-function 338 :feature 'builtin-function
342 `((((identifier) @font-lock-builtin-face) 339 `((((identifier) @font-lock-builtin-face)
343 (:pred ruby-ts--builtin-method-p @font-lock-builtin-face))) 340 (:match ,ruby-ts--builtin-methods @font-lock-builtin-face)))
344 341
345 ;; Yuan recommends also putting method definitions into the 342 ;; Yuan recommends also putting method definitions into the
346 ;; 'function' category (thus keeping it in both). I've opted to 343 ;; 'function' category (thus keeping it in both). I've opted to
diff --git a/lisp/repeat.el b/lisp/repeat.el
index 0124ff4bc0c..37d4aaec985 100644
--- a/lisp/repeat.el
+++ b/lisp/repeat.el
@@ -349,7 +349,7 @@ For example, you can set it to <return> like `isearch-exit'."
349 :version "28.1") 349 :version "28.1")
350 350
351(defcustom repeat-exit-timeout nil 351(defcustom repeat-exit-timeout nil
352 "Break the repetition chain of keys after specified timeout. 352 "Break the repetition chain of keys after specified amount of idle time.
353When a number, exit the transient repeating mode after idle time 353When a number, exit the transient repeating mode after idle time
354of the specified number of seconds. 354of the specified number of seconds.
355You can also set the property `repeat-exit-timeout' on the command symbol. 355You can also set the property `repeat-exit-timeout' on the command symbol.
@@ -380,12 +380,12 @@ This property can override the value of this variable."
380 380
381(defcustom repeat-check-key t 381(defcustom repeat-check-key t
382 "Whether to check that the last key exists in the repeat map. 382 "Whether to check that the last key exists in the repeat map.
383When non-nil and the last typed key (with or without modifiers) 383When non-nil, and the last typed key (with or without modifiers)
384doesn't exist in the keymap attached by the `repeat-map' property, 384doesn't exist in the keymap specified by the `repeat-map' property
385then don't activate that keymap for the next command. So only the 385of the command, don't activate that keymap for the next command.
386same keys among repeatable keys are allowed in the repeating sequence. 386Thus, when this is non-nil, only the same keys among repeatable
387For example, with a non-nil value, only \\`C-x u u' repeats undo, 387keys are allowed in the repeating sequence. For example, with a
388whereas \\`C-/ u' doesn't. 388non-nil value, only \\`C-x u u' repeats undo, whereas \\`C-/ u' doesn't.
389 389
390You can also set the property `repeat-check-key' on the command symbol. 390You can also set the property `repeat-check-key' on the command symbol.
391This property can override the value of this variable. 391This property can override the value of this variable.
@@ -398,7 +398,7 @@ but the property value is `t', then check the last key."
398 398
399(defcustom repeat-echo-function #'repeat-echo-message 399(defcustom repeat-echo-function #'repeat-echo-message
400 "Function to display a hint about available keys. 400 "Function to display a hint about available keys.
401Function is called after every repeatable command with one argument: 401The function is called after every repeatable command with one argument:
402a repeating map, or nil after deactivating the transient repeating mode. 402a repeating map, or nil after deactivating the transient repeating mode.
403You can use `add-function' for multiple functions simultaneously." 403You can use `add-function' for multiple functions simultaneously."
404 :type '(choice (const :tag "Show hints in the echo area" 404 :type '(choice (const :tag "Show hints in the echo area"
@@ -422,8 +422,12 @@ the map can't be set on the command symbol property `repeat-map'.")
422;;;###autoload 422;;;###autoload
423(define-minor-mode repeat-mode 423(define-minor-mode repeat-mode
424 "Toggle Repeat mode. 424 "Toggle Repeat mode.
425When Repeat mode is enabled, and the command symbol has the property named 425When Repeat mode is enabled, certain commands bound to multi-key
426`repeat-map', this map is activated temporarily for the next command. 426sequences can be repeated by typing a single key, after typing the
427full key sequence once.
428The commands which can be repeated like that are those whose symbol
429 has the property `repeat-map' which specifies a keymap of single
430keys for repeating.
427See `describe-repeat-maps' for a list of all repeatable commands." 431See `describe-repeat-maps' for a list of all repeatable commands."
428 :global t :group 'repeat 432 :global t :group 'repeat
429 (if (not repeat-mode) 433 (if (not repeat-mode)
@@ -459,7 +463,7 @@ See `describe-repeat-maps' for a list of all repeatable commands."
459 rep-map)))) 463 rep-map))))
460 464
461(defun repeat-check-key (key map) 465(defun repeat-check-key (key map)
462 "Check if the last key is suitable to activate the repeating MAP." 466 "Check if the last KEY is suitable for activating the repeating MAP."
463 (let* ((prop (repeat--command-property 'repeat-check-key)) 467 (let* ((prop (repeat--command-property 'repeat-check-key))
464 (check-key (unless (eq prop 'no) (or prop repeat-check-key)))) 468 (check-key (unless (eq prop 'no) (or prop repeat-check-key))))
465 (or (not check-key) 469 (or (not check-key)
@@ -471,7 +475,7 @@ See `describe-repeat-maps' for a list of all repeatable commands."
471 "Previous minibuffer state.") 475 "Previous minibuffer state.")
472 476
473(defun repeat-check-map (map) 477(defun repeat-check-map (map)
474 "Decides whether MAP can be used for the next command." 478 "Decide whether MAP can be used for the next command."
475 (and map 479 (and map
476 ;; Detect changes in the minibuffer state to allow repetitions 480 ;; Detect changes in the minibuffer state to allow repetitions
477 ;; in the same minibuffer, but not when the minibuffer is activated 481 ;; in the same minibuffer, but not when the minibuffer is activated
@@ -547,7 +551,7 @@ This function can be used to force exit of repetition while it's active."
547 (setq repeat-exit-function nil))) 551 (setq repeat-exit-function nil)))
548 552
549(defun repeat-echo-message-string (keymap) 553(defun repeat-echo-message-string (keymap)
550 "Return a string with a list of repeating keys." 554 "Return a string with the list of repeating keys in KEYMAP."
551 (let (keys) 555 (let (keys)
552 (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap) 556 (map-keymap (lambda (key cmd) (and cmd (push key keys))) keymap)
553 (format-message "Repeat with %s%s" 557 (format-message "Repeat with %s%s"
@@ -565,7 +569,8 @@ This function can be used to force exit of repetition while it's active."
565 "")))) 569 ""))))
566 570
567(defun repeat-echo-message (keymap) 571(defun repeat-echo-message (keymap)
568 "Display available repeating keys in the echo area." 572 "Display in the echo area the repeating keys defined by KEYMAP.
573See `repeat-echo-function' to enable/disable."
569 (let ((message-log-max nil)) 574 (let ((message-log-max nil))
570 (if keymap 575 (if keymap
571 (let ((message (repeat-echo-message-string keymap))) 576 (let ((message (repeat-echo-message-string keymap)))
@@ -586,7 +591,9 @@ This function can be used to force exit of repetition while it's active."
586 "String displayed in the mode line in repeating mode.") 591 "String displayed in the mode line in repeating mode.")
587 592
588(defun repeat-echo-mode-line (keymap) 593(defun repeat-echo-mode-line (keymap)
589 "Display the repeat indicator in the mode line." 594 "Display the repeat indicator in the mode line.
595KEYMAP should be non-nil, but is otherwise ignored.
596See `repeat-echo-function' to enable/disable."
590 (if keymap 597 (if keymap
591 (unless (assq 'repeat-in-progress mode-line-modes) 598 (unless (assq 'repeat-in-progress mode-line-modes)
592 (add-to-list 'mode-line-modes (list 'repeat-in-progress 599 (add-to-list 'mode-line-modes (list 'repeat-in-progress
@@ -596,8 +603,11 @@ This function can be used to force exit of repetition while it's active."
596(declare-function help-fns--analyze-function "help-fns" (function)) 603(declare-function help-fns--analyze-function "help-fns" (function))
597 604
598(defun describe-repeat-maps () 605(defun describe-repeat-maps ()
599 "Describe mappings of commands repeatable by symbol property `repeat-map'. 606 "Describe transient keymaps installed for repeating multi-key commands.
600Used in `repeat-mode'." 607These keymaps enable repetition of commands bound to multi-key
608sequences by typing just one key, when `repeat-mode' is enabled.
609Commands that can be repeated this way must have their symbol
610to have the `repeat-map' property whose value specified a keymap."
601 (interactive) 611 (interactive)
602 (require 'help-fns) 612 (require 'help-fns)
603 (let ((help-buffer-under-preparation t)) 613 (let ((help-buffer-under-preparation t))
@@ -612,7 +622,9 @@ Used in `repeat-mode'."
612 (with-help-window (help-buffer) 622 (with-help-window (help-buffer)
613 (with-current-buffer standard-output 623 (with-current-buffer standard-output
614 (setq-local outline-regexp "[*]+") 624 (setq-local outline-regexp "[*]+")
615 (insert "A list of keymaps used by commands with the symbol property `repeat-map'.\n") 625 (insert "\
626A list of keymaps and their single-key shortcuts for repeating commands.
627Click on a keymap to see the commands repeatable by the keymap.\n")
616 628
617 (dolist (keymap (sort keymaps (lambda (a b) 629 (dolist (keymap (sort keymaps (lambda (a b)
618 (when (and (symbolp (car a)) 630 (when (and (symbolp (car a))
diff --git a/lisp/simple.el b/lisp/simple.el
index 7bda368d85d..22aa043069f 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -5871,6 +5871,25 @@ The value 0 disables blinking."
5871 :group 'killing 5871 :group 'killing
5872 :version "28.1") 5872 :version "28.1")
5873 5873
5874(defcustom copy-region-blink-predicate #'region-indistinguishable-p
5875 "Whether the cursor must be blinked after a copy.
5876When this condition holds, and the copied region fits in the
5877current window, `kill-ring-save' will blink the cursor between
5878point and mark for `copy-region-blink-delay' seconds."
5879 :type '(radio (function-item region-indistinguishable-p)
5880 (function-item :doc "Always blink point and mark." always)
5881 (function-item :doc "Never blink point and mark." ignore)
5882 (function :tag "Other predicate function"))
5883 :group 'killing
5884 :version "29.1")
5885
5886(defun region-indistinguishable-p ()
5887 "Whether the current region is not denoted visually.
5888This holds when the region is inactive, or when the `region' face
5889cannot be distinguished from the `default' face."
5890 (not (and (region-active-p)
5891 (face-differs-from-default-p 'region))))
5892
5874(defun indicate-copied-region (&optional message-len) 5893(defun indicate-copied-region (&optional message-len)
5875 "Indicate that the region text has been copied interactively. 5894 "Indicate that the region text has been copied interactively.
5876If the mark is visible in the selected window, blink the cursor between 5895If the mark is visible in the selected window, blink the cursor between
@@ -5891,8 +5910,7 @@ of this sample text; it defaults to 40."
5891 ;; was selected. Don't do it if the region is highlighted. 5910 ;; was selected. Don't do it if the region is highlighted.
5892 (when (and (numberp copy-region-blink-delay) 5911 (when (and (numberp copy-region-blink-delay)
5893 (> copy-region-blink-delay 0) 5912 (> copy-region-blink-delay 0)
5894 (or (not (region-active-p)) 5913 (funcall copy-region-blink-predicate))
5895 (not (face-background 'region nil t))))
5896 ;; Swap point and mark. 5914 ;; Swap point and mark.
5897 (set-marker (mark-marker) (point) (current-buffer)) 5915 (set-marker (mark-marker) (point) (current-buffer))
5898 (goto-char mark) 5916 (goto-char mark)
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 9f53b649efd..7c3069ca269 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -2653,14 +2653,14 @@ When `switch-to-buffer-obey-display-actions' is non-nil,
2653(keymap-set tab-prefix-map "t" #'other-tab-prefix) 2653(keymap-set tab-prefix-map "t" #'other-tab-prefix)
2654 2654
2655(defvar-keymap tab-bar-switch-repeat-map 2655(defvar-keymap tab-bar-switch-repeat-map
2656 :doc "Keymap to repeat tab switch key sequences \\`C-x t o o O'. 2656 :doc "Keymap to repeat tab switch commands `tab-next' and `tab-previous'.
2657Used in `repeat-mode'." 2657Used in `repeat-mode'."
2658 :repeat t 2658 :repeat t
2659 "o" #'tab-next 2659 "o" #'tab-next
2660 "O" #'tab-previous) 2660 "O" #'tab-previous)
2661 2661
2662(defvar-keymap tab-bar-move-repeat-map 2662(defvar-keymap tab-bar-move-repeat-map
2663 :doc "Keymap to repeat tab move key sequences \\`C-x t m m M'. 2663 :doc "Keymap to repeat tab move commands `tab-move' and `tab-bar-move-tab-backward'.
2664Used in `repeat-mode'." 2664Used in `repeat-mode'."
2665 :repeat t 2665 :repeat t
2666 "m" #'tab-move 2666 "m" #'tab-move
diff --git a/lisp/window.el b/lisp/window.el
index 0cd30822ff6..2d9f746d8fb 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -10567,8 +10567,7 @@ displaying that processes's buffer."
10567(define-key ctl-x-4-map "4" 'other-window-prefix) 10567(define-key ctl-x-4-map "4" 'other-window-prefix)
10568 10568
10569(defvar-keymap other-window-repeat-map 10569(defvar-keymap other-window-repeat-map
10570 :doc "Keymap to repeat `other-window' key sequences. 10570 :doc "Keymap to repeat `other-window'. Used in `repeat-mode'."
10571Used in `repeat-mode'."
10572 :repeat t 10571 :repeat t
10573 "o" #'other-window 10572 "o" #'other-window
10574 "O" (lambda () 10573 "O" (lambda ()
@@ -10578,6 +10577,8 @@ Used in `repeat-mode'."
10578 10577
10579(defvar-keymap resize-window-repeat-map 10578(defvar-keymap resize-window-repeat-map
10580 :doc "Keymap to repeat window resizing commands. 10579 :doc "Keymap to repeat window resizing commands.
10580Repeatable commands are `enlarge-window' and `shrink-window',
10581and also `enlarge-window-horizontally' and `shrink-window-horizontally'.
10581Used in `repeat-mode'." 10582Used in `repeat-mode'."
10582 :repeat t 10583 :repeat t
10583 ;; Standard keys: 10584 ;; Standard keys:
diff --git a/src/insdel.c b/src/insdel.c
index 0e1e98664b3..e459d0cfa17 100644
--- a/src/insdel.c
+++ b/src/insdel.c
@@ -1101,6 +1101,10 @@ insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1101 eassert (NILP (BVAR (current_buffer, enable_multibyte_characters)) 1101 eassert (NILP (BVAR (current_buffer, enable_multibyte_characters))
1102 ? nchars == nbytes : nchars <= nbytes); 1102 ? nchars == nbytes : nchars <= nbytes);
1103 1103
1104#ifdef HAVE_TREE_SITTER
1105 ptrdiff_t ins_bytepos = GPT_BYTE;
1106#endif
1107
1104 GAP_SIZE -= nbytes; 1108 GAP_SIZE -= nbytes;
1105 if (! text_at_gap_tail) 1109 if (! text_at_gap_tail)
1106 { 1110 {
@@ -1115,6 +1119,12 @@ insert_from_gap_1 (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1115 /* Put an anchor to ensure multi-byte form ends at gap. */ 1119 /* Put an anchor to ensure multi-byte form ends at gap. */
1116 if (GAP_SIZE > 0) *(GPT_ADDR) = 0; 1120 if (GAP_SIZE > 0) *(GPT_ADDR) = 0;
1117 eassert (GPT <= GPT_BYTE); 1121 eassert (GPT <= GPT_BYTE);
1122
1123#ifdef HAVE_TREE_SITTER
1124 eassert (nbytes >= 0);
1125 eassert (ins_bytepos >= 0);
1126 treesit_record_change (ins_bytepos, ins_bytepos, ins_bytepos + nbytes);
1127#endif
1118} 1128}
1119 1129
1120/* Insert a sequence of NCHARS chars which occupy NBYTES bytes 1130/* Insert a sequence of NCHARS chars which occupy NBYTES bytes
@@ -1150,12 +1160,6 @@ insert_from_gap (ptrdiff_t nchars, ptrdiff_t nbytes, bool text_at_gap_tail)
1150 current_buffer, 0); 1160 current_buffer, 0);
1151 } 1161 }
1152 1162
1153#ifdef HAVE_TREE_SITTER
1154 eassert (nbytes >= 0);
1155 eassert (ins_bytepos >= 0);
1156 treesit_record_change (ins_bytepos, ins_bytepos, ins_bytepos + nbytes);
1157#endif
1158
1159 if (ins_charpos < PT) 1163 if (ins_charpos < PT)
1160 adjust_point (nchars, nbytes); 1164 adjust_point (nchars, nbytes);
1161 1165
@@ -1191,6 +1195,9 @@ insert_from_buffer (struct buffer *buf,
1191#endif 1195#endif
1192} 1196}
1193 1197
1198/* NOTE: If we ever make insert_from_buffer_1 public, make sure to
1199 move the call to treesit_record_change into it. */
1200
1194static void 1201static void
1195insert_from_buffer_1 (struct buffer *buf, 1202insert_from_buffer_1 (struct buffer *buf,
1196 ptrdiff_t from, ptrdiff_t nchars, bool inherit) 1203 ptrdiff_t from, ptrdiff_t nchars, bool inherit)
diff --git a/src/lisp.h b/src/lisp.h
index 6fda1e95503..b545c498173 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4807,6 +4807,9 @@ extern ptrdiff_t find_newline_no_quit (ptrdiff_t, ptrdiff_t,
4807 ptrdiff_t, ptrdiff_t *); 4807 ptrdiff_t, ptrdiff_t *);
4808extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t, 4808extern ptrdiff_t find_before_next_newline (ptrdiff_t, ptrdiff_t,
4809 ptrdiff_t, ptrdiff_t *); 4809 ptrdiff_t, ptrdiff_t *);
4810extern EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t,
4811 ptrdiff_t, ptrdiff_t, EMACS_INT,
4812 int, Lisp_Object, Lisp_Object, bool);
4810extern void syms_of_search (void); 4813extern void syms_of_search (void);
4811extern void clear_regexp_cache (void); 4814extern void clear_regexp_cache (void);
4812 4815
diff --git a/src/search.c b/src/search.c
index dbc5a83946f..0bb52c03eef 100644
--- a/src/search.c
+++ b/src/search.c
@@ -68,9 +68,6 @@ static EMACS_INT simple_search (EMACS_INT, unsigned char *, ptrdiff_t,
68static EMACS_INT boyer_moore (EMACS_INT, unsigned char *, ptrdiff_t, 68static EMACS_INT boyer_moore (EMACS_INT, unsigned char *, ptrdiff_t,
69 Lisp_Object, Lisp_Object, ptrdiff_t, 69 Lisp_Object, Lisp_Object, ptrdiff_t,
70 ptrdiff_t, int); 70 ptrdiff_t, int);
71static EMACS_INT search_buffer (Lisp_Object, ptrdiff_t, ptrdiff_t,
72 ptrdiff_t, ptrdiff_t, EMACS_INT, int,
73 Lisp_Object, Lisp_Object, bool);
74 71
75Lisp_Object re_match_object; 72Lisp_Object re_match_object;
76 73
@@ -1510,7 +1507,7 @@ search_buffer_non_re (Lisp_Object string, ptrdiff_t pos,
1510 return result; 1507 return result;
1511} 1508}
1512 1509
1513static EMACS_INT 1510EMACS_INT
1514search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte, 1511search_buffer (Lisp_Object string, ptrdiff_t pos, ptrdiff_t pos_byte,
1515 ptrdiff_t lim, ptrdiff_t lim_byte, EMACS_INT n, 1512 ptrdiff_t lim, ptrdiff_t lim_byte, EMACS_INT n,
1516 int RE, Lisp_Object trt, Lisp_Object inverse_trt, bool posix) 1513 int RE, Lisp_Object trt, Lisp_Object inverse_trt, bool posix)
diff --git a/src/sqlite.c b/src/sqlite.c
index c96841e63f9..0361514766a 100644
--- a/src/sqlite.c
+++ b/src/sqlite.c
@@ -399,7 +399,7 @@ row_to_value (sqlite3_stmt *stmt)
399 int len = sqlite3_column_count (stmt); 399 int len = sqlite3_column_count (stmt);
400 Lisp_Object values = Qnil; 400 Lisp_Object values = Qnil;
401 401
402 for (int i = 0; i < len; ++i) 402 for (int i = len - 1; i >= 0; i--)
403 { 403 {
404 Lisp_Object v = Qnil; 404 Lisp_Object v = Qnil;
405 405
@@ -434,7 +434,7 @@ row_to_value (sqlite3_stmt *stmt)
434 values = Fcons (v, values); 434 values = Fcons (v, values);
435 } 435 }
436 436
437 return Fnreverse (values); 437 return values;
438} 438}
439 439
440static Lisp_Object 440static Lisp_Object
@@ -718,11 +718,15 @@ Only modules on Emacs' list of allowed modules can be loaded. */)
718#endif /* HAVE_SQLITE3_LOAD_EXTENSION */ 718#endif /* HAVE_SQLITE3_LOAD_EXTENSION */
719 719
720DEFUN ("sqlite-next", Fsqlite_next, Ssqlite_next, 1, 1, 0, 720DEFUN ("sqlite-next", Fsqlite_next, Ssqlite_next, 1, 1, 0,
721 doc: /* Return the next result set from SET. */) 721 doc: /* Return the next result set from SET.
722Return nil when the statement has finished executing successfully. */)
722 (Lisp_Object set) 723 (Lisp_Object set)
723{ 724{
724 check_sqlite (set, true); 725 check_sqlite (set, true);
725 726
727 if (XSQLITE (set)->eof)
728 return Qnil;
729
726 int ret = sqlite3_step (XSQLITE (set)->stmt); 730 int ret = sqlite3_step (XSQLITE (set)->stmt);
727 if (ret != SQLITE_ROW && ret != SQLITE_OK && ret != SQLITE_DONE) 731 if (ret != SQLITE_ROW && ret != SQLITE_OK && ret != SQLITE_DONE)
728 xsignal1 (Qsqlite_error, build_string (sqlite3_errmsg (XSQLITE (set)->db))); 732 xsignal1 (Qsqlite_error, build_string (sqlite3_errmsg (XSQLITE (set)->db)));
diff --git a/src/treesit.c b/src/treesit.c
index b163685419f..8e772523cc7 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -72,6 +72,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
72#undef ts_query_cursor_set_byte_range 72#undef ts_query_cursor_set_byte_range
73#undef ts_query_delete 73#undef ts_query_delete
74#undef ts_query_new 74#undef ts_query_new
75#undef ts_query_pattern_count
75#undef ts_query_predicates_for_pattern 76#undef ts_query_predicates_for_pattern
76#undef ts_query_string_value_for_id 77#undef ts_query_string_value_for_id
77#undef ts_set_allocator 78#undef ts_set_allocator
@@ -135,6 +136,7 @@ DEF_DLL_FN (void, ts_query_cursor_set_byte_range,
135DEF_DLL_FN (void, ts_query_delete, (TSQuery *)); 136DEF_DLL_FN (void, ts_query_delete, (TSQuery *));
136DEF_DLL_FN (TSQuery *, ts_query_new, 137DEF_DLL_FN (TSQuery *, ts_query_new,
137 (const TSLanguage *, const char *, uint32_t, uint32_t *, TSQueryError *)); 138 (const TSLanguage *, const char *, uint32_t, uint32_t *, TSQueryError *));
139DEF_DLL_FN (uint32_t, ts_query_pattern_count, (const TSQuery *));
138DEF_DLL_FN (const TSQueryPredicateStep *, ts_query_predicates_for_pattern, 140DEF_DLL_FN (const TSQueryPredicateStep *, ts_query_predicates_for_pattern,
139 ( const TSQuery *, uint32_t, uint32_t *)); 141 ( const TSQuery *, uint32_t, uint32_t *));
140DEF_DLL_FN (const char *, ts_query_string_value_for_id, 142DEF_DLL_FN (const char *, ts_query_string_value_for_id,
@@ -200,6 +202,7 @@ init_treesit_functions (void)
200 LOAD_DLL_FN (library, ts_query_cursor_set_byte_range); 202 LOAD_DLL_FN (library, ts_query_cursor_set_byte_range);
201 LOAD_DLL_FN (library, ts_query_delete); 203 LOAD_DLL_FN (library, ts_query_delete);
202 LOAD_DLL_FN (library, ts_query_new); 204 LOAD_DLL_FN (library, ts_query_new);
205 LOAD_DLL_FN (library, ts_query_pattern_count);
203 LOAD_DLL_FN (library, ts_query_predicates_for_pattern); 206 LOAD_DLL_FN (library, ts_query_predicates_for_pattern);
204 LOAD_DLL_FN (library, ts_query_string_value_for_id); 207 LOAD_DLL_FN (library, ts_query_string_value_for_id);
205 LOAD_DLL_FN (library, ts_set_allocator); 208 LOAD_DLL_FN (library, ts_set_allocator);
@@ -256,6 +259,7 @@ init_treesit_functions (void)
256#define ts_query_cursor_set_byte_range fn_ts_query_cursor_set_byte_range 259#define ts_query_cursor_set_byte_range fn_ts_query_cursor_set_byte_range
257#define ts_query_delete fn_ts_query_delete 260#define ts_query_delete fn_ts_query_delete
258#define ts_query_new fn_ts_query_new 261#define ts_query_new fn_ts_query_new
262#define ts_query_pattern_count fn_ts_query_pattern_count
259#define ts_query_predicates_for_pattern fn_ts_query_predicates_for_pattern 263#define ts_query_predicates_for_pattern fn_ts_query_predicates_for_pattern
260#define ts_query_string_value_for_id fn_ts_query_string_value_for_id 264#define ts_query_string_value_for_id fn_ts_query_string_value_for_id
261#define ts_set_allocator fn_ts_set_allocator 265#define ts_set_allocator fn_ts_set_allocator
@@ -2466,13 +2470,42 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures)
2466 build_string ("The second argument to `match' should " 2470 build_string ("The second argument to `match' should "
2467 "be a capture name, not a string")); 2471 "be a capture name, not a string"));
2468 2472
2469 Lisp_Object text = treesit_predicate_capture_name_to_text (capture_name, 2473 Lisp_Object node = treesit_predicate_capture_name_to_node (capture_name,
2470 captures); 2474 captures);
2471 2475
2472 if (fast_string_match (regexp, text) >= 0) 2476 struct buffer *old_buffer = current_buffer;
2473 return true; 2477 struct buffer *buffer = XBUFFER (XTS_PARSER (XTS_NODE (node)->parser)->buffer);
2474 else 2478 set_buffer_internal (buffer);
2475 return false; 2479
2480 TSNode treesit_node = XTS_NODE (node)->node;
2481 ptrdiff_t visible_beg = XTS_PARSER (XTS_NODE (node)->parser)->visible_beg;
2482 uint32_t start_byte_offset = ts_node_start_byte (treesit_node);
2483 uint32_t end_byte_offset = ts_node_end_byte (treesit_node);
2484 ptrdiff_t start_byte = visible_beg + start_byte_offset;
2485 ptrdiff_t end_byte = visible_beg + end_byte_offset;
2486 ptrdiff_t start_pos = BYTE_TO_CHAR (start_byte);
2487 ptrdiff_t end_pos = BYTE_TO_CHAR (end_byte);
2488 ptrdiff_t old_begv = BEGV;
2489 ptrdiff_t old_begv_byte = BEGV_BYTE;
2490 ptrdiff_t old_zv = ZV;
2491 ptrdiff_t old_zv_byte = ZV_BYTE;
2492
2493 BEGV = start_pos;
2494 BEGV_BYTE = start_byte;
2495 ZV = end_pos;
2496 ZV_BYTE = end_byte;
2497
2498 ptrdiff_t val = search_buffer (regexp, start_pos, start_byte,
2499 end_pos, end_byte, 1, 1, Qnil, Qnil, false);
2500
2501 BEGV = old_begv;
2502 BEGV_BYTE = old_begv_byte;
2503 ZV = old_zv;
2504 ZV_BYTE = old_zv_byte;
2505
2506 set_buffer_internal (old_buffer);
2507
2508 return (val > 0);
2476} 2509}
2477 2510
2478/* Handles predicate (#pred FN ARG...). Return true if FN returns 2511/* Handles predicate (#pred FN ARG...). Return true if FN returns
diff --git a/src/xfaces.c b/src/xfaces.c
index d6ffc92d20d..4207b73ee25 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -2817,8 +2817,7 @@ merge_face_ref (struct window *w,
2817 else if (EQ (keyword, QCstipple)) 2817 else if (EQ (keyword, QCstipple))
2818 { 2818 {
2819#if defined (HAVE_WINDOW_SYSTEM) 2819#if defined (HAVE_WINDOW_SYSTEM)
2820 Lisp_Object pixmap_p = Fbitmap_spec_p (value); 2820 if (NILP (value) || !NILP (Fbitmap_spec_p (value)))
2821 if (!NILP (pixmap_p))
2822 to[LFACE_STIPPLE_INDEX] = value; 2821 to[LFACE_STIPPLE_INDEX] = value;
2823 else 2822 else
2824 err = true; 2823 err = true;
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
index 07698077ffc..ba4f854baf8 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent-bsd.erts
@@ -1,9 +1,9 @@
1Code: 1Code:
2 (lambda () 2 (lambda ()
3 (setq indent-tabs-mode nil)
4 (setq c-ts-mode-indent-offset 2)
5 (setq c-ts-mode-indent-style 'bsd)
6 (c-ts-mode) 3 (c-ts-mode)
4 (setq-local indent-tabs-mode nil)
5 (setq-local c-ts-mode-indent-offset 2)
6 (c-ts-mode-set-local-style 'bsd)
7 (indent-region (point-min) (point-max))) 7 (indent-region (point-min) (point-max)))
8 8
9Point-Char: | 9Point-Char: |
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index 0ecbf922b15..058c6e9099c 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -1,9 +1,9 @@
1Code: 1Code:
2 (lambda () 2 (lambda ()
3 (setq indent-tabs-mode nil)
4 (setq c-ts-mode-indent-offset 2)
5 (setq c-ts-mode-indent-style 'gnu)
6 (c-ts-mode) 3 (c-ts-mode)
4 (setq-local indent-tabs-mode nil)
5 (setq-local c-ts-mode-indent-offset 2)
6 (c-ts-mode-set-local-style 'gnu)
7 (indent-region (point-min) (point-max))) 7 (indent-region (point-min) (point-max)))
8 8
9Point-Char: | 9Point-Char: |
@@ -135,32 +135,6 @@ int main() {
135} 135}
136=-=-= 136=-=-=
137 137
138Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
139
140=-=-=
141int main() {
142 while (true)
143 if (true) {
144 puts ("Hello");
145 }
146 for (int i=0;
147 i<5;
148 i++)
149 if (true) {
150 puts ("Hello");
151 }
152 do
153 if (true) {
154 puts ("Hello");
155 }
156 while (true);
157 if (true)
158 if (true) {
159 puts ("Hello");
160 }
161}
162=-=-=
163
164Name: Multiline Parameter List (bug#60398) 138Name: Multiline Parameter List (bug#60398)
165 139
166=-= 140=-=
@@ -219,10 +193,10 @@ line 2
219 193
220Code: 194Code:
221 (lambda () 195 (lambda ()
222 (setq indent-tabs-mode nil)
223 (setq c-ts-mode-indent-offset 8)
224 (setq c-ts-mode-indent-style 'linux)
225 (c-ts-mode) 196 (c-ts-mode)
197 (setq-local indent-tabs-mode nil)
198 (setq-local c-ts-mode-indent-offset 8)
199 (c-ts-mode-set-local-style 'linux)
226 (indent-region (point-min) (point-max))) 200 (indent-region (point-min) (point-max)))
227 201
228Name: Labels (Linux Style) 202Name: Labels (Linux Style)
@@ -244,3 +218,29 @@ label:
244 } 218 }
245} 219}
246=-=-= 220=-=-=
221
222Name: Bracket-less Block-Statement (Linux Style) (bug#61026)
223
224=-=-=
225int main() {
226 while (true)
227 if (true) {
228 puts ("Hello");
229 }
230 for (int i=0;
231 i<5;
232 i++)
233 if (true) {
234 puts ("Hello");
235 }
236 do
237 if (true) {
238 puts ("Hello");
239 }
240 while (true);
241 if (true)
242 if (true) {
243 puts ("Hello");
244 }
245}
246=-=-=