aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorPo Lu2023-01-11 16:07:32 +0800
committerPo Lu2023-01-11 16:07:32 +0800
commit2fa5583d96fe78ff66d6fd41f18e54e4e20ea7d6 (patch)
treed3cf4a755e2da9b11c284763ed20041033b5dc3b /lisp
parent494bedde3235f9034746c977260bbbc2c1e51d8c (diff)
parent033f2cc6140d03e78403f37689b9f54b64bded01 (diff)
downloademacs-2fa5583d96fe78ff66d6fd41f18e54e4e20ea7d6.tar.gz
emacs-2fa5583d96fe78ff66d6fd41f18e54e4e20ea7d6.zip
Merge remote-tracking branch 'origin/master' into feature/android
Diffstat (limited to 'lisp')
-rw-r--r--lisp/align.el3
-rw-r--r--lisp/char-fold.el18
-rw-r--r--lisp/erc/erc-networks.el6
-rw-r--r--lisp/erc/erc-track.el12
-rw-r--r--lisp/erc/erc.el6
-rw-r--r--lisp/files.el6
-rw-r--r--lisp/font-lock.el9
-rw-r--r--lisp/minibuffer.el2
-rw-r--r--lisp/net/ange-ftp.el3
-rw-r--r--lisp/net/tramp-adb.el12
-rw-r--r--lisp/net/tramp-crypt.el8
-rw-r--r--lisp/net/tramp-fuse.el8
-rw-r--r--lisp/net/tramp-gvfs.el21
-rw-r--r--lisp/net/tramp-sh.el12
-rw-r--r--lisp/net/tramp-smb.el29
-rw-r--r--lisp/net/tramp-sudoedit.el19
-rw-r--r--lisp/net/tramp.el38
-rw-r--r--lisp/org/ob-core.el14
-rw-r--r--lisp/org/ob-shell.el2
-rw-r--r--lisp/org/org-macs.el11
-rw-r--r--lisp/org/org-persist.el2
-rw-r--r--lisp/org/org-table.el1
-rw-r--r--lisp/org/org-version.el2
-rw-r--r--lisp/org/org.el22
-rw-r--r--lisp/org/ox.el1
-rw-r--r--lisp/progmodes/c-ts-mode.el174
-rw-r--r--lisp/progmodes/cc-fonts.el4
-rw-r--r--lisp/progmodes/go-ts-mode.el107
-rw-r--r--lisp/progmodes/gud.el5
-rw-r--r--lisp/progmodes/js.el5
-rw-r--r--lisp/progmodes/project.el2
-rw-r--r--lisp/progmodes/python.el36
-rw-r--r--lisp/progmodes/ruby-ts-mode.el17
-rw-r--r--lisp/progmodes/typescript-ts-mode.el22
-rw-r--r--lisp/progmodes/xref.el2
-rw-r--r--lisp/simple.el131
-rw-r--r--lisp/textmodes/reftex-cite.el2
-rw-r--r--lisp/treesit.el61
-rw-r--r--lisp/vc/diff-mode.el14
39 files changed, 551 insertions, 298 deletions
diff --git a/lisp/align.el b/lisp/align.el
index 569186d241d..79a75dcec79 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -179,7 +179,8 @@ If nil, then no messages will ever be printed to the minibuffer."
179 :type '(choice (const :tag "Align a large region silently" nil) integer) 179 :type '(choice (const :tag "Align a large region silently" nil) integer)
180 :group 'align) 180 :group 'align)
181 181
182(defcustom align-c++-modes '(c++-mode c-mode java-mode) 182(defcustom align-c++-modes '( c++-mode c-mode java-mode
183 c-ts-mode c++-ts-mode)
183 "A list of modes whose syntax resembles C/C++." 184 "A list of modes whose syntax resembles C/C++."
184 :type '(repeat symbol) 185 :type '(repeat symbol)
185 :group 'align) 186 :group 'align)
diff --git a/lisp/char-fold.el b/lisp/char-fold.el
index eff2f5558b3..6da2dae8471 100644
--- a/lisp/char-fold.el
+++ b/lisp/char-fold.el
@@ -436,7 +436,23 @@ specify the character). With no input, i.e. when CHAR is nil,
436describe all available character equivalences of `char-fold-to-regexp'. 436describe all available character equivalences of `char-fold-to-regexp'.
437Optional argument LAX (interactively, the prefix argument), if 437Optional argument LAX (interactively, the prefix argument), if
438non-nil, means also include partially matching ligatures and 438non-nil, means also include partially matching ligatures and
439non-canonical equivalences." 439non-canonical equivalences.
440
441Each line of the display shows the equivalences in two different
442ways separated by a colon:
443
444 - as the literal character or sequence
445 - using an ASCII-only escape syntax
446
447For example, for the letter \\='r\\=', the first line is
448
449 r: ?\\N{LATIN SMALL LETTER R}
450
451which is for the requested character itself, and a later line has
452
453 ṟ: ?\\N{LATIN SMALL LETTER R}?\\N{COMBINING MACRON BELOW}
454
455which clearly shows what the constituent characters are."
440 (interactive (list (ignore-errors 456 (interactive (list (ignore-errors
441 (read-char-by-name 457 (read-char-by-name
442 (format-prompt "Unicode name, single char, or hex" 458 (format-prompt "Unicode name, single char, or hex"
diff --git a/lisp/erc/erc-networks.el b/lisp/erc/erc-networks.el
index 4044be08f92..95fd8990c99 100644
--- a/lisp/erc/erc-networks.el
+++ b/lisp/erc/erc-networks.el
@@ -1366,6 +1366,11 @@ ANNOUNCED is the server's reported host name."
1366 erc-server-connected t 1366 erc-server-connected t
1367 erc-networks--id nid)))))) 1367 erc-networks--id nid))))))
1368 1368
1369(defvar erc-networks--copy-server-buffer-functions nil
1370 "Abnormal hook run in new server buffers when deduping.
1371Passed the existing buffer to be killed, whose contents have
1372already been copied over to the current, replacement buffer.")
1373
1369(defun erc-networks--copy-over-server-buffer-contents (existing name) 1374(defun erc-networks--copy-over-server-buffer-contents (existing name)
1370 "Kill off existing server buffer after copying its contents. 1375 "Kill off existing server buffer after copying its contents.
1371Must be called from the replacement buffer." 1376Must be called from the replacement buffer."
@@ -1386,6 +1391,7 @@ Must be called from the replacement buffer."
1386 erc-kill-server-hook 1391 erc-kill-server-hook
1387 erc-kill-buffer-hook) 1392 erc-kill-buffer-hook)
1388 (erc-networks--insert-transplanted-content text) 1393 (erc-networks--insert-transplanted-content text)
1394 (run-hook-with-args 'erc-networks--copy-server-buffer-functions existing)
1389 (kill-buffer name))) 1395 (kill-buffer name)))
1390 1396
1391;; This stands alone for testing purposes 1397;; This stands alone for testing purposes
diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el
index 61c0c66abfb..7fd7b53602e 100644
--- a/lisp/erc/erc-track.el
+++ b/lisp/erc/erc-track.el
@@ -521,7 +521,9 @@ keybindings will not do anything useful."
521 (add-hook 'erc-disconnected-hook #'erc-modified-channels-update)) 521 (add-hook 'erc-disconnected-hook #'erc-modified-channels-update))
522 ;; enable the tracking keybindings 522 ;; enable the tracking keybindings
523 (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) 523 (add-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
524 (erc-track-minor-mode-maybe))) 524 (erc-track-minor-mode-maybe))
525 (add-hook 'erc-networks--copy-server-buffer-functions
526 #'erc-track--replace-killed-buffer))
525 ;; Disable: 527 ;; Disable:
526 ((when (boundp 'erc-track-when-inactive) 528 ((when (boundp 'erc-track-when-inactive)
527 (erc-track-remove-from-mode-line) 529 (erc-track-remove-from-mode-line)
@@ -539,7 +541,9 @@ keybindings will not do anything useful."
539 ;; disable the tracking keybindings 541 ;; disable the tracking keybindings
540 (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe) 542 (remove-hook 'erc-connect-pre-hook #'erc-track-minor-mode-maybe)
541 (when erc-track-minor-mode 543 (when erc-track-minor-mode
542 (erc-track-minor-mode -1))))) 544 (erc-track-minor-mode -1)))
545 (remove-hook 'erc-networks--copy-server-buffer-functions
546 #'erc-track--replace-killed-buffer)))
543 547
544(defcustom erc-track-when-inactive nil 548(defcustom erc-track-when-inactive nil
545 "Enable channel tracking even for visible buffers, if you are inactive." 549 "Enable channel tracking even for visible buffers, if you are inactive."
@@ -942,6 +946,10 @@ reverse it."
942 (interactive "p") 946 (interactive "p")
943 (erc-track--switch-buffer 'switch-to-buffer-other-window arg)) 947 (erc-track--switch-buffer 'switch-to-buffer-other-window arg))
944 948
949(defun erc-track--replace-killed-buffer (existing)
950 (when-let ((found (assq existing erc-modified-channels-alist)))
951 (setcar found (current-buffer))))
952
945(provide 'erc-track) 953(provide 'erc-track)
946 954
947;;; erc-track.el ends here 955;;; erc-track.el ends here
diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el
index 6315d5aa482..ba7db15cf8c 100644
--- a/lisp/erc/erc.el
+++ b/lisp/erc/erc.el
@@ -323,7 +323,8 @@ A typical value would be \((\"Libera.Chat\" \"MODE\")
323 \(\"OFTC\" \"JOIN\" \"QUIT\"))." 323 \(\"OFTC\" \"JOIN\" \"QUIT\"))."
324 :version "25.1" 324 :version "25.1"
325 :group 'erc-ignore 325 :group 'erc-ignore
326 :type 'erc-message-type) 326 :type '(alist :key-type string :value-type erc-message-type
327 :options ("Libera.Chat")))
327 328
328(defcustom erc-channel-hide-list nil 329(defcustom erc-channel-hide-list nil
329 "A list of IRC channels to hide message types from. 330 "A list of IRC channels to hide message types from.
@@ -331,7 +332,8 @@ A typical value would be \((\"#emacs\" \"QUIT\" \"JOIN\")
331 \(\"#erc\" \"NICK\")." 332 \(\"#erc\" \"NICK\")."
332 :version "25.1" 333 :version "25.1"
333 :group 'erc-ignore 334 :group 'erc-ignore
334 :type 'erc-message-type) 335 :type '(alist :key-type string :value-type erc-message-type
336 :options ("#emacs")))
335 337
336(defcustom erc-disconnected-hook nil 338(defcustom erc-disconnected-hook nil
337 "Run this hook with arguments (NICK IP REASON) when disconnected. 339 "Run this hook with arguments (NICK IP REASON) when disconnected.
diff --git a/lisp/files.el b/lisp/files.el
index e1b7a990b15..d0167bf3814 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6336,6 +6336,12 @@ RECURSIVE if DIRECTORY is nonempty."
6336 directory-exists)) 6336 directory-exists))
6337 (files--force recursive #'delete-directory-internal directory)))))) 6337 (files--force recursive #'delete-directory-internal directory))))))
6338 6338
6339(defcustom remote-file-name-inhibit-delete-by-moving-to-trash nil
6340 "Whether remote files shall be moved to the Trash.
6341This overrules any setting of `delete-by-moving-to-trash'."
6342 :version "30.1"
6343 :type 'boolean)
6344
6339(defun file-equal-p (file1 file2) 6345(defun file-equal-p (file1 file2)
6340 "Return non-nil if files FILE1 and FILE2 name the same file. 6346 "Return non-nil if files FILE1 and FILE2 name the same file.
6341If FILE1 or FILE2 does not exist, the return value is unspecified." 6347If FILE1 or FILE2 does not exist, the return value is unspecified."
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 99df8fb9e06..1fa45379b9f 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1183,7 +1183,7 @@ This function is the default `font-lock-fontify-region-function'."
1183 (setq font-lock-syntactically-fontified end)) 1183 (setq font-lock-syntactically-fontified end))
1184 (font-lock-fontify-syntactic-keywords-region start end))) 1184 (font-lock-fontify-syntactic-keywords-region start end)))
1185 (unless font-lock-keywords-only 1185 (unless font-lock-keywords-only
1186 (funcall font-lock-fontify-syntactically-function beg end loudly)) 1186 (font-lock-fontify-syntactically-region beg end loudly))
1187 (font-lock-fontify-keywords-region beg end loudly) 1187 (font-lock-fontify-keywords-region beg end loudly)
1188 `(jit-lock-bounds ,beg . ,end)))) 1188 `(jit-lock-bounds ,beg . ,end))))
1189 1189
@@ -1531,6 +1531,12 @@ START should be at the beginning of a line."
1531(defvar font-lock-comment-end-skip nil 1531(defvar font-lock-comment-end-skip nil
1532 "If non-nil, Font Lock mode uses this instead of `comment-end-skip'.") 1532 "If non-nil, Font Lock mode uses this instead of `comment-end-skip'.")
1533 1533
1534(defun font-lock-fontify-syntactically-region (beg end &optional loudly)
1535 "Syntactically fontify the text between BEG and END.
1536If LOUDLY is non-nil, print status messages while fontifying.
1537This works by calling `font-lock-fontify-syntactically-function'."
1538 (funcall font-lock-fontify-syntactically-function beg end loudly))
1539
1534(defun font-lock-default-fontify-syntactically (start end &optional loudly) 1540(defun font-lock-default-fontify-syntactically (start end &optional loudly)
1535 "Put proper face on each string and comment between START and END. 1541 "Put proper face on each string and comment between START and END.
1536START should be at the beginning of a line." 1542START should be at the beginning of a line."
@@ -2369,7 +2375,6 @@ in which C preprocessor directives are used, e.g. `asm-mode' and
2369 2375
2370(define-obsolete-function-alias 'font-lock-after-fontify-buffer #'ignore "29.1") 2376(define-obsolete-function-alias 'font-lock-after-fontify-buffer #'ignore "29.1")
2371(define-obsolete-function-alias 'font-lock-after-unfontify-buffer #'ignore "29.1") 2377(define-obsolete-function-alias 'font-lock-after-unfontify-buffer #'ignore "29.1")
2372(define-obsolete-function-alias 'font-lock-fontify-syntactically-region #'font-lock-default-fontify-syntactically "29.1")
2373 2378
2374 2379
2375(provide 'font-lock) 2380(provide 'font-lock)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index f47299bd0da..21d4607e7cf 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -986,7 +986,7 @@ already visible.
986If the value is `visible', the *Completions* buffer is displayed 986If the value is `visible', the *Completions* buffer is displayed
987whenever completion is requested but cannot be done for the first time, 987whenever completion is requested but cannot be done for the first time,
988but remains visible thereafter, and the list of completions in it is 988but remains visible thereafter, and the list of completions in it is
989updated for subsequent attempts to complete.." 989updated for subsequent attempts to complete."
990 :type '(choice (const :tag "Don't show" nil) 990 :type '(choice (const :tag "Don't show" nil)
991 (const :tag "Show only when cannot complete" t) 991 (const :tag "Show only when cannot complete" t)
992 (const :tag "Show after second failed completion attempt" lazy) 992 (const :tag "Show after second failed completion attempt" lazy)
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 41c28672aae..a14122f815a 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -3534,7 +3534,8 @@ system TYPE.")
3534 (setq file (expand-file-name file)) 3534 (setq file (expand-file-name file))
3535 (let ((parsed (ange-ftp-ftp-name file))) 3535 (let ((parsed (ange-ftp-ftp-name file)))
3536 (if parsed 3536 (if parsed
3537 (if (and delete-by-moving-to-trash trash) 3537 (if (and delete-by-moving-to-trash trash
3538 (not remote-file-name-inhibit-delete-by-moving-to-trash))
3538 (move-file-to-trash file) 3539 (move-file-to-trash file)
3539 (let* ((host (nth 0 parsed)) 3540 (let* ((host (nth 0 parsed))
3540 (user (nth 1 parsed)) 3541 (user (nth 1 parsed))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 619d29bb4d6..493a9fb39a9 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -424,14 +424,10 @@ Emacs dired can't find files."
424 424
425(defun tramp-adb-handle-delete-file (filename &optional trash) 425(defun tramp-adb-handle-delete-file (filename &optional trash)
426 "Like `delete-file' for Tramp files." 426 "Like `delete-file' for Tramp files."
427 (setq filename (expand-file-name filename)) 427 (tramp-skeleton-delete-file filename trash
428 (with-parsed-tramp-file-name filename nil 428 (tramp-adb-barf-unless-okay
429 (tramp-flush-file-properties v localname) 429 v (format "rm %s" (tramp-shell-quote-argument localname))
430 (if (and delete-by-moving-to-trash trash) 430 "Couldn't delete %s" filename)))
431 (move-file-to-trash filename)
432 (tramp-adb-barf-unless-okay
433 v (format "rm %s" (tramp-shell-quote-argument localname))
434 "Couldn't delete %s" filename))))
435 431
436(defun tramp-adb-handle-file-name-all-completions (filename directory) 432(defun tramp-adb-handle-file-name-all-completions (filename directory)
437 "Like `file-name-all-completions' for Tramp files." 433 "Like `file-name-all-completions' for Tramp files."
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 61d1c529619..507fd432419 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -689,17 +689,17 @@ absolute file names."
689 (directory &optional recursive _trash) 689 (directory &optional recursive _trash)
690 "Like `delete-directory' for Tramp files." 690 "Like `delete-directory' for Tramp files."
691 (with-parsed-tramp-file-name (expand-file-name directory) nil 691 (with-parsed-tramp-file-name (expand-file-name directory) nil
692 (tramp-flush-directory-properties v localname)
693 (let (tramp-crypt-enabled) 692 (let (tramp-crypt-enabled)
694 (delete-directory (tramp-crypt-encrypt-file-name directory) recursive)))) 693 (delete-directory (tramp-crypt-encrypt-file-name directory) recursive))
694 (tramp-flush-directory-properties v localname)))
695 695
696;; Encrypted files won't be trashed. 696;; Encrypted files won't be trashed.
697(defun tramp-crypt-handle-delete-file (filename &optional _trash) 697(defun tramp-crypt-handle-delete-file (filename &optional _trash)
698 "Like `delete-file' for Tramp files." 698 "Like `delete-file' for Tramp files."
699 (with-parsed-tramp-file-name (expand-file-name filename) nil 699 (with-parsed-tramp-file-name (expand-file-name filename) nil
700 (tramp-flush-file-properties v localname)
701 (let (tramp-crypt-enabled) 700 (let (tramp-crypt-enabled)
702 (delete-file (tramp-crypt-encrypt-file-name filename))))) 701 (delete-file (tramp-crypt-encrypt-file-name filename)))
702 (tramp-flush-file-properties v localname)))
703 703
704(defun tramp-crypt-handle-directory-files 704(defun tramp-crypt-handle-directory-files
705 (directory &optional full match nosort count) 705 (directory &optional full match nosort count)
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index c8754e2b03d..b846caadc18 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -34,15 +34,13 @@
34(defun tramp-fuse-handle-delete-directory 34(defun tramp-fuse-handle-delete-directory
35 (directory &optional recursive trash) 35 (directory &optional recursive trash)
36 "Like `delete-directory' for Tramp files." 36 "Like `delete-directory' for Tramp files."
37 (with-parsed-tramp-file-name (expand-file-name directory) nil 37 (tramp-skeleton-delete-directory directory recursive trash
38 (tramp-flush-directory-properties v localname)
39 (delete-directory (tramp-fuse-local-file-name directory) recursive trash))) 38 (delete-directory (tramp-fuse-local-file-name directory) recursive trash)))
40 39
41(defun tramp-fuse-handle-delete-file (filename &optional trash) 40(defun tramp-fuse-handle-delete-file (filename &optional trash)
42 "Like `delete-file' for Tramp files." 41 "Like `delete-file' for Tramp files."
43 (with-parsed-tramp-file-name (expand-file-name filename) nil 42 (tramp-skeleton-delete-file filename trash
44 (delete-file (tramp-fuse-local-file-name filename) trash) 43 (delete-file (tramp-fuse-local-file-name filename) trash)))
45 (tramp-flush-file-properties v localname)))
46 44
47(defvar tramp-fuse-remove-hidden-files nil 45(defvar tramp-fuse-remove-hidden-files nil
48 "Remove hidden files from directory listings.") 46 "Remove hidden files from directory listings.")
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index bb81b3eb66c..cca7a5fe247 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1139,18 +1139,15 @@ file names."
1139 1139
1140(defun tramp-gvfs-handle-delete-file (filename &optional trash) 1140(defun tramp-gvfs-handle-delete-file (filename &optional trash)
1141 "Like `delete-file' for Tramp files." 1141 "Like `delete-file' for Tramp files."
1142 (with-parsed-tramp-file-name (expand-file-name filename) nil 1142 (tramp-skeleton-delete-file filename trash
1143 (tramp-flush-file-properties v localname) 1143 (unless (and (tramp-gvfs-send-command
1144 (if (and delete-by-moving-to-trash trash) 1144 v "gvfs-rm" (tramp-gvfs-url-file-name filename))
1145 (move-file-to-trash filename) 1145 (not (tramp-gvfs-info filename)))
1146 (unless (and (tramp-gvfs-send-command 1146 ;; Propagate the error.
1147 v "gvfs-rm" (tramp-gvfs-url-file-name filename)) 1147 (with-current-buffer (tramp-get-connection-buffer v)
1148 (not (tramp-gvfs-info filename))) 1148 (goto-char (point-min))
1149 ;; Propagate the error. 1149 (tramp-error-with-buffer
1150 (with-current-buffer (tramp-get-connection-buffer v) 1150 nil v 'file-error "Couldn't delete %s" filename)))))
1151 (goto-char (point-min))
1152 (tramp-error-with-buffer
1153 nil v 'file-error "Couldn't delete %s" filename))))))
1154 1151
1155(defun tramp-gvfs-handle-expand-file-name (name &optional dir) 1152(defun tramp-gvfs-handle-expand-file-name (name &optional dir)
1156 "Like `expand-file-name' for Tramp files." 1153 "Like `expand-file-name' for Tramp files."
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index fbdd40dd1d2..4647600071c 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2567,14 +2567,10 @@ The method used must be an out-of-band method."
2567 2567
2568(defun tramp-sh-handle-delete-file (filename &optional trash) 2568(defun tramp-sh-handle-delete-file (filename &optional trash)
2569 "Like `delete-file' for Tramp files." 2569 "Like `delete-file' for Tramp files."
2570 (setq filename (expand-file-name (expand-file-name filename))) 2570 (tramp-skeleton-delete-file filename trash
2571 (with-parsed-tramp-file-name filename nil 2571 (tramp-barf-unless-okay
2572 (if (and delete-by-moving-to-trash trash) 2572 v (format "rm -f %s" (tramp-shell-quote-argument localname))
2573 (move-file-to-trash filename) 2573 "Couldn't delete %s" filename)))
2574 (tramp-barf-unless-okay
2575 v (format "rm -f %s" (tramp-shell-quote-argument localname))
2576 "Couldn't delete %s" filename))
2577 (tramp-flush-file-properties v localname)))
2578 2574
2579;; Dired. 2575;; Dired.
2580 2576
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index f31865d498d..d6f3cca9733 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -695,24 +695,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
695 695
696(defun tramp-smb-handle-delete-file (filename &optional trash) 696(defun tramp-smb-handle-delete-file (filename &optional trash)
697 "Like `delete-file' for Tramp files." 697 "Like `delete-file' for Tramp files."
698 (setq filename (expand-file-name filename)) 698 (tramp-skeleton-delete-file filename trash
699 (when (file-exists-p filename) 699 (unless (tramp-smb-send-command
700 (with-parsed-tramp-file-name filename nil 700 v (format
701 ;; We must also flush the cache of the directory, because 701 "%s %s"
702 ;; `file-attributes' reads the values from there. 702 (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
703 (tramp-flush-file-properties v localname) 703 (tramp-smb-shell-quote-localname v)))
704 (if (and delete-by-moving-to-trash trash) 704 ;; Error.
705 (move-file-to-trash filename) 705 (with-current-buffer (tramp-get-connection-buffer v)
706 (unless (tramp-smb-send-command 706 (goto-char (point-min))
707 v (format 707 (search-forward-regexp tramp-smb-errors nil t)
708 "%s %s" 708 (tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))
709 (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
710 (tramp-smb-shell-quote-localname v)))
711 ;; Error.
712 (with-current-buffer (tramp-get-connection-buffer v)
713 (goto-char (point-min))
714 (search-forward-regexp tramp-smb-errors nil t)
715 (tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))))
716 709
717(defun tramp-smb-handle-expand-file-name (name &optional dir) 710(defun tramp-smb-handle-expand-file-name (name &optional dir)
718 "Like `expand-file-name' for Tramp files." 711 "Like `expand-file-name' for Tramp files."
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index c4e1d32f525..2660dbb1fac 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -347,17 +347,14 @@ absolute file names."
347 347
348(defun tramp-sudoedit-handle-delete-file (filename &optional trash) 348(defun tramp-sudoedit-handle-delete-file (filename &optional trash)
349 "Like `delete-file' for Tramp files." 349 "Like `delete-file' for Tramp files."
350 (with-parsed-tramp-file-name (expand-file-name filename) nil 350 (tramp-skeleton-delete-file filename trash
351 (tramp-flush-file-properties v localname) 351 (unless (tramp-sudoedit-send-command
352 (if (and delete-by-moving-to-trash trash) 352 v "rm" "-f" (file-name-unquote localname))
353 (move-file-to-trash filename) 353 ;; Propagate the error.
354 (unless (tramp-sudoedit-send-command 354 (with-current-buffer (tramp-get-connection-buffer v)
355 v "rm" "-f" (file-name-unquote localname)) 355 (goto-char (point-min))
356 ;; Propagate the error. 356 (tramp-error-with-buffer
357 (with-current-buffer (tramp-get-connection-buffer v) 357 nil v 'file-error "Couldn't delete %s" filename)))))
358 (goto-char (point-min))
359 (tramp-error-with-buffer
360 nil v 'file-error "Couldn't delete %s" filename))))))
361 358
362(defun tramp-sudoedit-handle-expand-file-name (name &optional dir) 359(defun tramp-sudoedit-handle-expand-file-name (name &optional dir)
363 "Like `expand-file-name' for Tramp files. 360 "Like `expand-file-name' for Tramp files.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 4bf0fdefc0b..b8475b7cb48 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3399,15 +3399,35 @@ BODY is the backend specific code."
3399BODY is the backend specific code." 3399BODY is the backend specific code."
3400 (declare (indent 3) (debug t)) 3400 (declare (indent 3) (debug t))
3401 `(with-parsed-tramp-file-name (expand-file-name ,directory) nil 3401 `(with-parsed-tramp-file-name (expand-file-name ,directory) nil
3402 (if (and delete-by-moving-to-trash ,trash) 3402 (let ((delete-by-moving-to-trash
3403 ;; Move non-empty dir to trash only if recursive deletion was 3403 (and delete-by-moving-to-trash
3404 ;; requested. 3404 ;; This variable exists since Emacs 30.1.
3405 (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory))) 3405 (not (bound-and-true-p
3406 (tramp-error 3406 remote-file-name-inhibit-delete-by-moving-to-trash)))))
3407 v 'file-error "Directory is not empty, not moving to trash") 3407 (if (and delete-by-moving-to-trash ,trash)
3408 (move-file-to-trash ,directory)) 3408 ;; Move non-empty dir to trash only if recursive deletion was
3409 ,@body) 3409 ;; requested.
3410 (tramp-flush-directory-properties v localname))) 3410 (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
3411 (tramp-error
3412 v 'file-error "Directory is not empty, not moving to trash")
3413 (move-file-to-trash ,directory))
3414 ,@body)
3415 (tramp-flush-directory-properties v localname))))
3416
3417(defmacro tramp-skeleton-delete-file (filename &optional trash &rest body)
3418 "Skeleton for `tramp-*-handle-delete-file'.
3419BODY is the backend specific code."
3420 (declare (indent 2) (debug t))
3421 `(with-parsed-tramp-file-name (expand-file-name ,filename) nil
3422 (let ((delete-by-moving-to-trash
3423 (and delete-by-moving-to-trash
3424 ;; This variable exists since Emacs 30.1.
3425 (not (bound-and-true-p
3426 remote-file-name-inhibit-delete-by-moving-to-trash)))))
3427 (if (and delete-by-moving-to-trash ,trash)
3428 (move-file-to-trash ,filename)
3429 ,@body)
3430 (tramp-flush-file-properties v localname))))
3411 3431
3412(defmacro tramp-skeleton-directory-files 3432(defmacro tramp-skeleton-directory-files
3413 (directory &optional full match nosort count &rest body) 3433 (directory &optional full match nosort count &rest body)
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 9bb77f7920b..93cdf6ae868 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1690,6 +1690,7 @@ shown below.
1690 (append 1690 (append
1691 (split-string (if (stringp raw-result) 1691 (split-string (if (stringp raw-result)
1692 raw-result 1692 raw-result
1693 ;; FIXME: Arbitrary code evaluation.
1693 (eval raw-result t))) 1694 (eval raw-result t)))
1694 (cdr (assq :result-params params)))))) 1695 (cdr (assq :result-params params))))))
1695 (append 1696 (append
@@ -2860,6 +2861,7 @@ parameters when merging lists."
2860 (split-string 2861 (split-string
2861 (cond ((stringp value) value) 2862 (cond ((stringp value) value)
2862 ((functionp value) (funcall value)) 2863 ((functionp value) (funcall value))
2864 ;; FIXME: Arbitrary code evaluation.
2863 (t (eval value t))))))) 2865 (t (eval value t)))))))
2864 (`(:exports . ,value) 2866 (`(:exports . ,value)
2865 (setq exports (funcall merge 2867 (setq exports (funcall merge
@@ -3188,16 +3190,8 @@ situations in which is it not appropriate."
3188 ((and (not inhibit-lisp-eval) 3190 ((and (not inhibit-lisp-eval)
3189 (or (memq (string-to-char cell) '(?\( ?' ?` ?\[)) 3191 (or (memq (string-to-char cell) '(?\( ?' ?` ?\[))
3190 (string= cell "*this*"))) 3192 (string= cell "*this*")))
3191 ;; Prevent arbitrary function calls. 3193 ;; FIXME: Arbitrary code evaluation.
3192 (if (and (memq (string-to-char cell) '(?\( ?`)) 3194 (eval (read cell) t))
3193 (not (org-babel-confirm-evaluate
3194 ;; See `org-babel-get-src-block-info'.
3195 (list "emacs-lisp" cell
3196 '((:eval . yes)) nil (format "%s" cell)
3197 nil nil))))
3198 ;; Not allowed.
3199 (user-error "Evaluation of elisp code %S aborted." cell)
3200 (eval (read cell) t)))
3201 ((save-match-data 3195 ((save-match-data
3202 (and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell) 3196 (and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell)
3203 (not (string-match "[^\\]\"" (match-string 1 cell))))) 3197 (not (string-match "[^\\]\"" (match-string 1 cell)))))
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
index 4a60186cd5d..2c30a26056b 100644
--- a/lisp/org/ob-shell.el
+++ b/lisp/org/ob-shell.el
@@ -79,7 +79,7 @@ is modified outside the Customize interface."
79 ,(format "Execute a block of %s commands with Babel." name) 79 ,(format "Execute a block of %s commands with Babel." name)
80 (let ((shell-file-name ,name) 80 (let ((shell-file-name ,name)
81 (org-babel-prompt-command 81 (org-babel-prompt-command
82 (or (alist-get ,name org-babel-shell-set-prompt-commands) 82 (or (cdr (assoc ,name org-babel-shell-set-prompt-commands))
83 (alist-get t org-babel-shell-set-prompt-commands)))) 83 (alist-get t org-babel-shell-set-prompt-commands))))
84 (org-babel-execute:shell body params)))) 84 (org-babel-execute:shell body params))))
85 (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name)) 85 (eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 72929cdd26c..07c668a807d 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -372,18 +372,23 @@ be set to a buffer or a buffer name. `shell-command' then uses
372it for output." 372it for output."
373 (let* ((base-name (file-name-base source)) 373 (let* ((base-name (file-name-base source))
374 (full-name (file-truename source)) 374 (full-name (file-truename source))
375 (out-dir (or (file-name-directory source) "./")) 375 (relative-name (file-relative-name source))
376 (out-dir (if (file-name-directory source)
377 ;; Expand "~". Shell expansion will be disabled
378 ;; in the shell command call.
379 (file-name-directory full-name)
380 "./"))
376 (output (expand-file-name (concat base-name "." ext) out-dir)) 381 (output (expand-file-name (concat base-name "." ext) out-dir))
377 (time (file-attribute-modification-time (file-attributes output))) 382 (time (file-attribute-modification-time (file-attributes output)))
378 (err-msg (if (stringp err-msg) (concat ". " err-msg) ""))) 383 (err-msg (if (stringp err-msg) (concat ". " err-msg) "")))
379 (save-window-excursion 384 (save-window-excursion
380 (pcase process 385 (pcase process
381 ((pred functionp) (funcall process (shell-quote-argument source))) 386 ((pred functionp) (funcall process (shell-quote-argument relative-name)))
382 ((pred consp) 387 ((pred consp)
383 (let ((log-buf (and log-buf (get-buffer-create log-buf))) 388 (let ((log-buf (and log-buf (get-buffer-create log-buf)))
384 (spec (append spec 389 (spec (append spec
385 `((?b . ,(shell-quote-argument base-name)) 390 `((?b . ,(shell-quote-argument base-name))
386 (?f . ,(shell-quote-argument source)) 391 (?f . ,(shell-quote-argument relative-name))
387 (?F . ,(shell-quote-argument full-name)) 392 (?F . ,(shell-quote-argument full-name))
388 (?o . ,(shell-quote-argument out-dir)) 393 (?o . ,(shell-quote-argument out-dir))
389 (?O . ,(shell-quote-argument output)))))) 394 (?O . ,(shell-quote-argument output))))))
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index c3650c167e2..336496efbfb 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -753,12 +753,12 @@ with `org-persist-write'."
753When ASSOCIATED is `all', unregister CONTAINER everywhere." 753When ASSOCIATED is `all', unregister CONTAINER everywhere."
754 (unless org-persist--index (org-persist--load-index)) 754 (unless org-persist--index (org-persist--load-index))
755 (setq container (org-persist--normalize-container container)) 755 (setq container (org-persist--normalize-container container))
756 (setq associated (org-persist--normalize-associated associated))
757 (if (eq associated 'all) 756 (if (eq associated 'all)
758 (mapc (lambda (collection) 757 (mapc (lambda (collection)
759 (when (member container (plist-get collection :container)) 758 (when (member container (plist-get collection :container))
760 (org-persist-unregister container (plist-get collection :associated)))) 759 (org-persist-unregister container (plist-get collection :associated))))
761 org-persist--index) 760 org-persist--index)
761 (setq associated (org-persist--normalize-associated associated))
762 (let ((collection (org-persist--find-index `(:container ,container :associated ,associated)))) 762 (let ((collection (org-persist--find-index `(:container ,container :associated ,associated))))
763 (when collection 763 (when collection
764 (if (= (length (plist-get collection :container)) 1) 764 (if (= (length (plist-get collection :container)) 1)
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 06cf919db76..fac9e68c124 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2614,6 +2614,7 @@ location of point."
2614 2614
2615 (if lispp 2615 (if lispp
2616 (setq ev (condition-case nil 2616 (setq ev (condition-case nil
2617 ;; FIXME: Arbitrary code evaluation.
2617 (eval (eval (read form))) 2618 (eval (eval (read form)))
2618 (error "#ERROR")) 2619 (error "#ERROR"))
2619 ev (if (numberp ev) (number-to-string ev) ev) 2620 ev (if (numberp ev) (number-to-string ev) ev)
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index dd6d92d8e58..942cc4eae8b 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made."
11(defun org-git-version () 11(defun org-git-version ()
12 "The Git version of Org mode. 12 "The Git version of Org mode.
13Inserted by installing Org or when a release is made." 13Inserted by installing Org or when a release is made."
14 (let ((org-git-version "release_9.6-81-g563a43")) 14 (let ((org-git-version "release_9.6-90-ga6523f"))
15 org-git-version)) 15 org-git-version))
16 16
17(provide 'org-version) 17(provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 21764f3d434..8d226c2c5ab 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -4898,16 +4898,20 @@ The following commands are available:
4898 (= (point-min) (point-max))) 4898 (= (point-min) (point-max)))
4899 (insert "# -*- mode: org -*-\n\n")) 4899 (insert "# -*- mode: org -*-\n\n"))
4900 (unless org-inhibit-startup 4900 (unless org-inhibit-startup
4901 (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
4902 (org-table-map-tables
4903 (cond ((and org-startup-align-all-tables
4904 org-startup-shrink-all-tables)
4905 (lambda () (org-table-align) (org-table-shrink)))
4906 (org-startup-align-all-tables #'org-table-align)
4907 (t #'org-table-shrink))
4908 t))
4909 ;; Suppress modification hooks to speed up the startup.
4910 ;; However, do it only when text properties/overlays, but not
4911 ;; buffer text are actually modified. We still need to track text
4912 ;; modifications to make cache updates work reliably.
4901 (org-unmodified 4913 (org-unmodified
4902 (when org-startup-with-beamer-mode (org-beamer-mode)) 4914 (when org-startup-with-beamer-mode (org-beamer-mode))
4903 (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
4904 (org-table-map-tables
4905 (cond ((and org-startup-align-all-tables
4906 org-startup-shrink-all-tables)
4907 (lambda () (org-table-align) (org-table-shrink)))
4908 (org-startup-align-all-tables #'org-table-align)
4909 (t #'org-table-shrink))
4910 t))
4911 (when org-startup-with-inline-images (org-display-inline-images)) 4915 (when org-startup-with-inline-images (org-display-inline-images))
4912 (when org-startup-with-latex-preview (org-latex-preview '(16))) 4916 (when org-startup-with-latex-preview (org-latex-preview '(16)))
4913 (unless org-inhibit-startup-visibility-stuff (org-cycle-set-startup-visibility)) 4917 (unless org-inhibit-startup-visibility-stuff (org-cycle-set-startup-visibility))
@@ -8855,7 +8859,7 @@ keywords relative to each registered export back-end."
8855 "EXCLUDE_TAGS:" "FILETAGS:" "INCLUDE:" "INDEX:" "KEYWORDS:" "LANGUAGE:" 8859 "EXCLUDE_TAGS:" "FILETAGS:" "INCLUDE:" "INDEX:" "KEYWORDS:" "LANGUAGE:"
8856 "MACRO:" "OPTIONS:" "PROPERTY:" "PRINT_BIBLIOGRAPHY" "PRIORITIES:" 8860 "MACRO:" "OPTIONS:" "PROPERTY:" "PRINT_BIBLIOGRAPHY" "PRIORITIES:"
8857 "SELECT_TAGS:" "SEQ_TODO:" "SETUPFILE:" "STARTUP:" "TAGS:" "TITLE:" "TODO:" 8861 "SELECT_TAGS:" "SEQ_TODO:" "SETUPFILE:" "STARTUP:" "TAGS:" "TITLE:" "TODO:"
8858 "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:")) 8862 "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:" "EXPORT_FILE_NAME:"))
8859 8863
8860(defcustom org-structure-template-alist 8864(defcustom org-structure-template-alist
8861 '(("a" . "export ascii") 8865 '(("a" . "export ascii")
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 62fc8d583e4..12767267a71 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -6757,7 +6757,6 @@ Return file name as a string."
6757 (cond 6757 (cond
6758 (pub-dir (concat (file-name-as-directory pub-dir) 6758 (pub-dir (concat (file-name-as-directory pub-dir)
6759 (file-name-nondirectory base-name))) 6759 (file-name-nondirectory base-name)))
6760 ((file-name-absolute-p base-name) base-name)
6761 (t base-name)))) 6760 (t base-name))))
6762 ;; If writing to OUTPUT-FILE would overwrite original file, append 6761 ;; If writing to OUTPUT-FILE would overwrite original file, append
6763 ;; EXTENSION another time to final name. 6762 ;; EXTENSION another time to final name.
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index e76966e7660..e929fe1dd81 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -122,9 +122,13 @@ MODE is either `c' or `cpp'."
122 ((node-is "else") parent-bol 0) 122 ((node-is "else") parent-bol 0)
123 ((node-is "case") parent-bol 0) 123 ((node-is "case") parent-bol 0)
124 ((node-is "preproc_arg") no-indent) 124 ((node-is "preproc_arg") no-indent)
125 (c-ts-mode--comment-2nd-line-matcher
126 c-ts-mode--comment-2nd-line-anchor
127 1)
125 ((and (parent-is "comment") c-ts-mode--looking-at-star) 128 ((and (parent-is "comment") c-ts-mode--looking-at-star)
126 c-ts-mode--comment-start-after-first-star -1) 129 c-ts-mode--comment-start-after-first-star -1)
127 ((parent-is "comment") prev-adaptive-prefix 0) 130 ((parent-is "comment") prev-adaptive-prefix 0)
131 (c-ts-mode--top-level-label-matcher point-min 1)
128 ((node-is "labeled_statement") parent-bol 0) 132 ((node-is "labeled_statement") parent-bol 0)
129 ((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset) 133 ((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
130 ((match "preproc_ifdef" "compound_statement") point-min 0) 134 ((match "preproc_ifdef" "compound_statement") point-min 0)
@@ -138,6 +142,7 @@ MODE is either `c' or `cpp'."
138 ((parent-is "function_definition") parent-bol 0) 142 ((parent-is "function_definition") parent-bol 0)
139 ((parent-is "conditional_expression") first-sibling 0) 143 ((parent-is "conditional_expression") first-sibling 0)
140 ((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset) 144 ((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset)
145 ((parent-is "concatenated_string") parent-bol c-ts-mode-indent-offset)
141 ((parent-is "comma_expression") first-sibling 0) 146 ((parent-is "comma_expression") first-sibling 0)
142 ((parent-is "init_declarator") parent-bol c-ts-mode-indent-offset) 147 ((parent-is "init_declarator") parent-bol c-ts-mode-indent-offset)
143 ((parent-is "parenthesized_expression") first-sibling 1) 148 ((parent-is "parenthesized_expression") first-sibling 1)
@@ -151,7 +156,9 @@ MODE is either `c' or `cpp'."
151 ((parent-is "call_expression") parent 0) 156 ((parent-is "call_expression") parent 0)
152 ((parent-is "enumerator_list") parent-bol c-ts-mode-indent-offset) 157 ((parent-is "enumerator_list") parent-bol c-ts-mode-indent-offset)
153 ,@(when (eq mode 'cpp) 158 ,@(when (eq mode 'cpp)
154 '(((node-is "access_specifier") parent-bol 0))) 159 '(((node-is "access_specifier") parent-bol 0)
160 ;; Indent the body of namespace definitions.
161 ((parent-is "declaration_list") parent-bol c-ts-mode-indent-offset)))
155 ((parent-is "field_declaration_list") parent-bol c-ts-mode-indent-offset) 162 ((parent-is "field_declaration_list") parent-bol c-ts-mode-indent-offset)
156 ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset) 163 ((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
157 ((parent-is "if_statement") parent-bol c-ts-mode-indent-offset) 164 ((parent-is "if_statement") parent-bol c-ts-mode-indent-offset)
@@ -167,7 +174,12 @@ MODE is either `c' or `cpp'."
167 ((match "while" "do_statement") parent 0) 174 ((match "while" "do_statement") parent 0)
168 ,@common) 175 ,@common)
169 (k&r ,@common) 176 (k&r ,@common)
170 (linux ,@common) 177 (linux
178 ;; Reference:
179 ;; https://www.kernel.org/doc/html/latest/process/coding-style.html,
180 ;; and script/Lindent in Linux kernel repository.
181 ((node-is "labeled_statement") point-min 0)
182 ,@common)
171 (bsd 183 (bsd
172 ((parent-is "if_statement") parent-bol 0) 184 ((parent-is "if_statement") parent-bol 0)
173 ((parent-is "for_statement") parent-bol 0) 185 ((parent-is "for_statement") parent-bol 0)
@@ -190,6 +202,17 @@ MODE is either `c' or `cpp'."
190 ('linux (alist-get 'linux (c-ts-mode--indent-styles mode))))))) 202 ('linux (alist-get 'linux (c-ts-mode--indent-styles mode)))))))
191 `((,mode ,@style)))) 203 `((,mode ,@style))))
192 204
205(defun c-ts-mode--top-level-label-matcher (node &rest _)
206 "A matcher that matches a top-level label.
207NODE should be a labeled_statement."
208 (let ((func (treesit-parent-until
209 node (lambda (n)
210 (equal (treesit-node-type n)
211 "function_definition")))))
212 (and (equal (treesit-node-type node)
213 "labeled_statement")
214 (not (treesit-node-top-level func "function_definition")))))
215
193(defun c-ts-mode--bracket-children-anchor (_n parent &rest _) 216(defun c-ts-mode--bracket-children-anchor (_n parent &rest _)
194 "This anchor is used for children of a compound_statement. 217 "This anchor is used for children of a compound_statement.
195So anything inside a {} block. PARENT should be the 218So anything inside a {} block. PARENT should be the
@@ -205,11 +228,10 @@ beginning of grandparent."
205 (treesit-node-parent parent) 228 (treesit-node-parent parent)
206 parent))))) 229 parent)))))
207 230
208(defun c-ts-mode--looking-at-star (&rest _) 231(defun c-ts-mode--looking-at-star (_n _p bol &rest _)
209 "A tree-sitter simple indent matcher. 232 "A tree-sitter simple indent matcher.
210Matches if there is a \"*\" after point (ignoring whitespace in 233Matches if there is a \"*\" after BOL."
211between)." 234 (eq (char-after bol) ?*))
212 (looking-at (rx (* (syntax whitespace)) "*")))
213 235
214(defun c-ts-mode--comment-start-after-first-star (_n parent &rest _) 236(defun c-ts-mode--comment-start-after-first-star (_n parent &rest _)
215 "A tree-sitter simple indent anchor. 237 "A tree-sitter simple indent anchor.
@@ -221,6 +243,35 @@ Assumes PARENT is a comment node."
221 (match-end 0) 243 (match-end 0)
222 (point)))) 244 (point))))
223 245
246(defun c-ts-mode--comment-2nd-line-matcher (_n parent &rest _)
247 "Matches if point is at the second line of a block comment.
248PARENT should be a comment node."
249 (and (equal (treesit-node-type parent) "comment")
250 (save-excursion
251 (forward-line -1)
252 (back-to-indentation)
253 (eq (point) (treesit-node-start parent)))))
254
255(defun c-ts-mode--comment-2nd-line-anchor (&rest _)
256 "Return appropriate anchor for the second line of a comment.
257
258If the first line is /* alone, return the position right after
259the star; if the first line is /* followed by some text, return
260the position right before the text minus 1.
261
262Use an offset of 1 with this anchor."
263 (save-excursion
264 (forward-line -1)
265 (back-to-indentation)
266 (when (looking-at comment-start-skip)
267 (goto-char (match-end 0))
268 (if (looking-at (rx (* (or " " "\t")) eol))
269 ;; Only /* at the first line.
270 (progn (skip-chars-backward " \t")
271 (point))
272 ;; There is something after /* at the first line.
273 (1- (point))))))
274
224;;; Font-lock 275;;; Font-lock
225 276
226(defvar c-ts-mode--preproc-keywords 277(defvar c-ts-mode--preproc-keywords
@@ -419,20 +470,29 @@ MODE is either `c' or `cpp'."
419 470
420;;; Font-lock helpers 471;;; Font-lock helpers
421 472
422(defun c-ts-mode--declarator-identifier (node) 473(defun c-ts-mode--declarator-identifier (node &optional qualified)
423 "Return the identifier of the declarator node NODE." 474 "Return the identifier of the declarator node NODE.
475
476If QUALIFIED is non-nil, include the names space part of the
477identifier and return a qualified_identifier."
424 (pcase (treesit-node-type node) 478 (pcase (treesit-node-type node)
425 ;; Recurse. 479 ;; Recurse.
426 ((or "attributed_declarator" "parenthesized_declarator") 480 ((or "attributed_declarator" "parenthesized_declarator")
427 (c-ts-mode--declarator-identifier (treesit-node-child node 0 t))) 481 (c-ts-mode--declarator-identifier (treesit-node-child node 0 t)
482 qualified))
428 ((or "pointer_declarator" "reference_declarator") 483 ((or "pointer_declarator" "reference_declarator")
429 (c-ts-mode--declarator-identifier (treesit-node-child node -1))) 484 (c-ts-mode--declarator-identifier (treesit-node-child node -1)
485 qualified))
430 ((or "function_declarator" "array_declarator" "init_declarator") 486 ((or "function_declarator" "array_declarator" "init_declarator")
431 (c-ts-mode--declarator-identifier 487 (c-ts-mode--declarator-identifier
432 (treesit-node-child-by-field-name node "declarator"))) 488 (treesit-node-child-by-field-name node "declarator")
489 qualified))
433 ("qualified_identifier" 490 ("qualified_identifier"
434 (c-ts-mode--declarator-identifier 491 (if qualified
435 (treesit-node-child-by-field-name node "name"))) 492 node
493 (c-ts-mode--declarator-identifier
494 (treesit-node-child-by-field-name node "name")
495 qualified)))
436 ;; Terminal case. 496 ;; Terminal case.
437 ((or "identifier" "field_identifier") 497 ((or "identifier" "field_identifier")
438 node))) 498 node)))
@@ -534,9 +594,11 @@ Return nil if NODE is not a defun node or doesn't have a name."
534 (pcase (treesit-node-type node) 594 (pcase (treesit-node-type node)
535 ((or "function_definition" "declaration") 595 ((or "function_definition" "declaration")
536 (c-ts-mode--declarator-identifier 596 (c-ts-mode--declarator-identifier
537 (treesit-node-child-by-field-name node "declarator"))) 597 (treesit-node-child-by-field-name node "declarator")
598 t))
538 ((or "struct_specifier" "enum_specifier" 599 ((or "struct_specifier" "enum_specifier"
539 "union_specifier" "class_specifier") 600 "union_specifier" "class_specifier"
601 "namespace_definition")
540 (treesit-node-child-by-field-name node "name"))) 602 (treesit-node-child-by-field-name node "name")))
541 t)) 603 t))
542 604
@@ -568,6 +630,23 @@ Ie, NODE is not nested."
568 node "declarator")) 630 node "declarator"))
569 "function_declarator"))))) 631 "function_declarator")))))
570 632
633(defun c-ts-mode--defun-for-class-in-imenu-p (node)
634 "Check if NODE is a valid entry for the Class subindex.
635
636Basically, if NODE is a class, return non-nil; if NODE is a
637function but is under a class, return non-nil; if NODE is a
638top-level function, return nil.
639
640This is for the Class subindex in
641`treesit-simple-imenu-settings'."
642 (pcase (treesit-node-type node)
643 ;; The Class subindex only has class_specifier and
644 ;; function_definition.
645 ("class_specifier" t)
646 ("function_definition"
647 ;; Return t if this function is nested in a class.
648 (treesit-node-top-level node "class_specifier"))))
649
571(defun c-ts-mode--defun-skipper () 650(defun c-ts-mode--defun-skipper ()
572 "Custom defun skipper for `c-ts-mode' and friends. 651 "Custom defun skipper for `c-ts-mode' and friends.
573Structs in C ends with a semicolon, but the semicolon is not 652Structs in C ends with a semicolon, but the semicolon is not
@@ -741,7 +820,8 @@ Set up:
741 "struct_specifier" 820 "struct_specifier"
742 "enum_specifier" 821 "enum_specifier"
743 "union_specifier" 822 "union_specifier"
744 "class_specifier")) 823 "class_specifier"
824 "namespace_definition"))
745 #'c-ts-mode--defun-valid-p)) 825 #'c-ts-mode--defun-valid-p))
746 (setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper) 826 (setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
747 (setq-local treesit-defun-name-function #'c-ts-mode--defun-name) 827 (setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
@@ -772,7 +852,7 @@ Set up:
772 ("Class" ,(rx bos (or "class_specifier" 852 ("Class" ,(rx bos (or "class_specifier"
773 "function_definition") 853 "function_definition")
774 eos) 854 eos)
775 ,pred nil)))) 855 c-ts-mode--defun-for-class-in-imenu-p nil))))
776 856
777 (setq-local treesit-font-lock-feature-list 857 (setq-local treesit-font-lock-feature-list
778 '(( comment definition) 858 '(( comment definition)
@@ -782,49 +862,49 @@ Set up:
782 862
783;;;###autoload 863;;;###autoload
784(define-derived-mode c-ts-mode c-ts-base-mode "C" 864(define-derived-mode c-ts-mode c-ts-base-mode "C"
785 "Major mode for editing C, powered by tree-sitter." 865 "Major mode for editing C, powered by tree-sitter.
786 :group 'c
787
788 (unless (treesit-ready-p 'c)
789 (error "Tree-sitter for C isn't available"))
790
791 (treesit-parser-create 'c)
792
793 ;; Comments.
794 (setq-local comment-start "/* ")
795 (setq-local comment-end " */")
796
797 (setq-local treesit-simple-indent-rules
798 (c-ts-mode--set-indent-style 'c))
799 866
800 ;; Font-lock. 867This mode is independent from the classic cc-mode.el based
801 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c)) 868`c-mode', so configuration variables of that mode, like
869`c-basic-offset', don't affect this mode."
870 :group 'c
802 871
803 (treesit-major-mode-setup)) 872 (when (treesit-ready-p 'c)
873 (treesit-parser-create 'c)
874 ;; Comments.
875 (setq-local comment-start "/* ")
876 (setq-local comment-end " */")
877 ;; Indent.
878 (setq-local treesit-simple-indent-rules
879 (c-ts-mode--set-indent-style 'c))
880 ;; Font-lock.
881 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
882 (treesit-major-mode-setup)))
804 883
805;;;###autoload 884;;;###autoload
806(define-derived-mode c++-ts-mode c-ts-base-mode "C++" 885(define-derived-mode c++-ts-mode c-ts-base-mode "C++"
807 "Major mode for editing C++, powered by tree-sitter." 886 "Major mode for editing C++, powered by tree-sitter."
808 :group 'c++ 887 :group 'c++
809 888
810 (unless (treesit-ready-p 'cpp) 889 (when (treesit-ready-p 'cpp)
811 (error "Tree-sitter for C++ isn't available")) 890 (setq-local treesit-text-type-regexp
891 (regexp-opt '("comment"
892 "raw_string_literal")))
812 893
813 (setq-local treesit-text-type-regexp 894 (treesit-parser-create 'cpp)
814 (regexp-opt '("comment"
815 "raw_string_literal")))
816 895
817 (treesit-parser-create 'cpp) 896 ;; Syntax.
818 (setq-local syntax-propertize-function 897 (setq-local syntax-propertize-function
819 #'c-ts-mode--syntax-propertize) 898 #'c-ts-mode--syntax-propertize)
820 899
821 (setq-local treesit-simple-indent-rules 900 ;; Indent.
822 (c-ts-mode--set-indent-style 'cpp)) 901 (setq-local treesit-simple-indent-rules
902 (c-ts-mode--set-indent-style 'cpp))
823 903
824 ;; Font-lock. 904 ;; Font-lock.
825 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp)) 905 (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp))
826 906
827 (treesit-major-mode-setup)) 907 (treesit-major-mode-setup)))
828 908
829(provide 'c-ts-mode) 909(provide 'c-ts-mode)
830 910
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el
index d84c4f8ad8a..4dcc3e0ade9 100644
--- a/lisp/progmodes/cc-fonts.el
+++ b/lisp/progmodes/cc-fonts.el
@@ -2530,8 +2530,8 @@ higher."
2530 (get-text-property (match-beginning 0) 'fontified) 2530 (get-text-property (match-beginning 0) 'fontified)
2531 (not (memq (c-get-char-property (match-beginning 0) 'face) 2531 (not (memq (c-get-char-property (match-beginning 0) 'face)
2532 c-literal-faces))) 2532 c-literal-faces)))
2533 (c-put-font-lock-face (match-beginning 0) (match-end 0) 2533 (put-text-property (match-beginning 0) (match-end 0)
2534 font-lock-type-face)) 2534 'fontified nil))
2535 (dolist (win-boundary window-boundaries) 2535 (dolist (win-boundary window-boundaries)
2536 (when (and (< (match-beginning 0) (cdr win-boundary)) 2536 (when (and (< (match-beginning 0) (cdr win-boundary))
2537 (> (match-end 0) (car win-boundary)) 2537 (> (match-end 0) (car win-boundary))
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 1d6a8a30db5..64e761d2f72 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -36,6 +36,7 @@
36(declare-function treesit-node-child-by-field-name "treesit.c") 36(declare-function treesit-node-child-by-field-name "treesit.c")
37(declare-function treesit-node-start "treesit.c") 37(declare-function treesit-node-start "treesit.c")
38(declare-function treesit-node-type "treesit.c") 38(declare-function treesit-node-type "treesit.c")
39(declare-function treesit-search-subtree "treesit.c")
39 40
40(defcustom go-ts-mode-indent-offset 4 41(defcustom go-ts-mode-indent-offset 4
41 "Number of spaces for each indentation step in `go-ts-mode'." 42 "Number of spaces for each indentation step in `go-ts-mode'."
@@ -173,44 +174,6 @@
173 '((ERROR) @font-lock-warning-face)) 174 '((ERROR) @font-lock-warning-face))
174 "Tree-sitter font-lock settings for `go-ts-mode'.") 175 "Tree-sitter font-lock settings for `go-ts-mode'.")
175 176
176(defun go-ts-mode--imenu ()
177 "Return Imenu alist for the current buffer."
178 (let* ((node (treesit-buffer-root-node))
179 (func-tree (treesit-induce-sparse-tree
180 node "function_declaration" nil 1000))
181 (type-tree (treesit-induce-sparse-tree
182 node "type_spec" nil 1000))
183 (func-index (go-ts-mode--imenu-1 func-tree))
184 (type-index (go-ts-mode--imenu-1 type-tree)))
185 (append
186 (when func-index `(("Function" . ,func-index)))
187 (when type-index `(("Type" . ,type-index))))))
188
189(defun go-ts-mode--imenu-1 (node)
190 "Helper for `go-ts-mode--imenu'.
191Find string representation for NODE and set marker, then recurse
192the subtrees."
193 (let* ((ts-node (car node))
194 (children (cdr node))
195 (subtrees (mapcan #'go-ts-mode--imenu-1
196 children))
197 (name (when ts-node
198 (treesit-node-text
199 (pcase (treesit-node-type ts-node)
200 ("function_declaration"
201 (treesit-node-child-by-field-name ts-node "name"))
202 ("type_spec"
203 (treesit-node-child-by-field-name ts-node "name"))))))
204 (marker (when ts-node
205 (set-marker (make-marker)
206 (treesit-node-start ts-node)))))
207 (cond
208 ((or (null ts-node) (null name)) subtrees)
209 (subtrees
210 `((,name ,(cons name marker) ,@subtrees)))
211 (t
212 `((,name . ,marker))))))
213
214;;;###autoload 177;;;###autoload
215(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode)) 178(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
216 179
@@ -228,14 +191,30 @@ the subtrees."
228 (setq-local comment-end "") 191 (setq-local comment-end "")
229 (setq-local comment-start-skip (rx "//" (* (syntax whitespace)))) 192 (setq-local comment-start-skip (rx "//" (* (syntax whitespace))))
230 193
194 ;; Navigation.
195 (setq-local treesit-defun-type-regexp
196 (regexp-opt '("method_declaration"
197 "function_declaration"
198 "type_declaration")))
199 (setq-local treesit-defun-name-function #'go-ts-mode--defun-name)
200
231 ;; Imenu. 201 ;; Imenu.
232 (setq-local imenu-create-index-function #'go-ts-mode--imenu) 202 (setq-local treesit-simple-imenu-settings
233 (setq-local which-func-functions nil) 203 `(("Function" "\\`function_declaration\\'" nil nil)
204 ("Method" "\\`method_declaration\\'" nil nil)
205 ("Struct" "\\`type_declaration\\'" go-ts-mode--struct-node-p nil)
206 ("Interface" "\\`type_declaration\\'" go-ts-mode--interface-node-p nil)
207 ("Type" "\\`type_declaration\\'" go-ts-mode--other-type-node-p nil)
208 ("Alias" "\\`type_declaration\\'" go-ts-mode--alias-node-p nil)))
234 209
235 ;; Indent. 210 ;; Indent.
236 (setq-local indent-tabs-mode t 211 (setq-local indent-tabs-mode t
237 treesit-simple-indent-rules go-ts-mode--indent-rules) 212 treesit-simple-indent-rules go-ts-mode--indent-rules)
238 213
214 ;; Electric
215 (setq-local electric-indent-chars
216 (append "{}()" electric-indent-chars))
217
239 ;; Font-lock. 218 ;; Font-lock.
240 (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings) 219 (setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings)
241 (setq-local treesit-font-lock-feature-list 220 (setq-local treesit-font-lock-feature-list
@@ -247,6 +226,54 @@ the subtrees."
247 226
248 (treesit-major-mode-setup))) 227 (treesit-major-mode-setup)))
249 228
229(defun go-ts-mode--defun-name (node)
230 "Return the defun name of NODE.
231Return nil if there is no name or if NODE is not a defun node."
232 (pcase (treesit-node-type node)
233 ("function_declaration"
234 (treesit-node-text
235 (treesit-node-child-by-field-name
236 node "name")
237 t))
238 ("method_declaration"
239 (let* ((receiver-node (treesit-node-child-by-field-name node "receiver"))
240 (type-node (treesit-search-subtree receiver-node "type_identifier"))
241 (name-node (treesit-node-child-by-field-name node "name")))
242 (concat
243 "(" (treesit-node-text type-node) ")."
244 (treesit-node-text name-node))))
245 ("type_declaration"
246 (treesit-node-text
247 (treesit-node-child-by-field-name
248 (treesit-node-child node 0 t) "name")
249 t))))
250
251(defun go-ts-mode--interface-node-p (node)
252 "Return t if NODE is an interface."
253 (and
254 (string-equal "type_declaration" (treesit-node-type node))
255 (treesit-search-subtree node "interface_type" nil nil 2)))
256
257(defun go-ts-mode--struct-node-p (node)
258 "Return t if NODE is a struct."
259 (and
260 (string-equal "type_declaration" (treesit-node-type node))
261 (treesit-search-subtree node "struct_type" nil nil 2)))
262
263(defun go-ts-mode--alias-node-p (node)
264 "Return t if NODE is a type alias."
265 (and
266 (string-equal "type_declaration" (treesit-node-type node))
267 (treesit-search-subtree node "type_alias" nil nil 1)))
268
269(defun go-ts-mode--other-type-node-p (node)
270 "Return t if NODE is a type, other than interface, struct or alias."
271 (and
272 (string-equal "type_declaration" (treesit-node-type node))
273 (not (go-ts-mode--interface-node-p node))
274 (not (go-ts-mode--struct-node-p node))
275 (not (go-ts-mode--alias-node-p node))))
276
250;; go.mod support. 277;; go.mod support.
251 278
252(defvar go-mod-ts-mode--syntax-table 279(defvar go-mod-ts-mode--syntax-table
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 20692d6c8df..92e018aaec1 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -3561,8 +3561,9 @@ Treats actions as defuns."
3561 (kill-local-variable 'gdb-define-alist) 3561 (kill-local-variable 'gdb-define-alist)
3562 (remove-hook 'after-save-hook #'gdb-create-define-alist t)))) 3562 (remove-hook 'after-save-hook #'gdb-create-define-alist t))))
3563 3563
3564(defcustom gud-tooltip-modes '(gud-mode c-mode c++-mode fortran-mode 3564(defcustom gud-tooltip-modes '( gud-mode c-mode c++-mode fortran-mode
3565 python-mode) 3565 python-mode c-ts-mode c++-ts-mode
3566 python-ts-mode)
3566 "List of modes for which to enable GUD tooltips." 3567 "List of modes for which to enable GUD tooltips."
3567 :type '(repeat (symbol :tag "Major mode")) 3568 :type '(repeat (symbol :tag "Major mode"))
3568 :group 'tooltip) 3569 :group 'tooltip)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 881f4a83b17..902d4fa7ab3 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3542,7 +3542,10 @@ This function is intended for use in `after-change-functions'."
3542 (identifier) 3542 (identifier)
3543 (identifier) 3543 (identifier)
3544 @font-lock-function-name-face) 3544 @font-lock-function-name-face)
3545 value: (array (number) (function)))) 3545 value: (array (number) (function)))
3546 (import_clause (identifier) @font-lock-variable-name-face)
3547 (import_clause (named_imports (import_specifier (identifier))
3548 @font-lock-variable-name-face)))
3546 3549
3547 :language 'javascript 3550 :language 'javascript
3548 :feature 'property 3551 :feature 'property
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 730998727ce..dc87cb8e15d 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,7 +1,7 @@
1;;; project.el --- Operations on the current project -*- lexical-binding: t; -*- 1;;; project.el --- Operations on the current project -*- lexical-binding: t; -*-
2 2
3;; Copyright (C) 2015-2023 Free Software Foundation, Inc. 3;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
4;; Version: 0.9.3 4;; Version: 0.9.4
5;; Package-Requires: ((emacs "26.1") (xref "1.4.0")) 5;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
6 6
7;; This is a GNU ELPA :core package. Avoid using functionality that 7;; This is a GNU ELPA :core package. Avoid using functionality that
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 59164d7d50c..21d16db287c 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1067,11 +1067,28 @@ fontified."
1067 "expression_statement")) 1067 "expression_statement"))
1068 'font-lock-doc-face 1068 'font-lock-doc-face
1069 'font-lock-string-face))) 1069 'font-lock-string-face)))
1070 (when (eq (char-after string-beg) ?f) 1070 ;; Don't highlight string prefixes like f/r/b.
1071 (cl-incf string-beg)) 1071 (save-excursion
1072 (goto-char string-beg)
1073 (when (search-forward "\"" string-end t)
1074 (setq string-beg (match-beginning 0))))
1072 (treesit-fontify-with-override 1075 (treesit-fontify-with-override
1073 string-beg string-end face override start end))) 1076 string-beg string-end face override start end)))
1074 1077
1078(defun python--treesit-fontify-string-interpolation
1079 (node _ start end &rest _)
1080 "Fontify string interpolation.
1081NODE is the string node. Do not fontify the initial f for
1082f-strings. START and END mark the region to be
1083fontified."
1084 ;; This is kind of a hack, it basically removes the face applied by
1085 ;; the string feature, so that following features can apply their
1086 ;; face.
1087 (let ((n-start (treesit-node-start node))
1088 (n-end (treesit-node-end node)))
1089 (remove-text-properties
1090 (max start n-start) (min end n-end) '(face))))
1091
1075(defvar python--treesit-settings 1092(defvar python--treesit-settings
1076 (treesit-font-lock-rules 1093 (treesit-font-lock-rules
1077 :feature 'comment 1094 :feature 'comment
@@ -1082,10 +1099,12 @@ fontified."
1082 :language 'python 1099 :language 'python
1083 '((string) @python--treesit-fontify-string) 1100 '((string) @python--treesit-fontify-string)
1084 1101
1102 ;; HACK: This feature must come after the string feature and before
1103 ;; other features. Maybe we should make string-interpolation an
1104 ;; option rather than a feature.
1085 :feature 'string-interpolation 1105 :feature 'string-interpolation
1086 :language 'python 1106 :language 'python
1087 :override t 1107 '((interpolation) @python--treesit-fontify-string-interpolation)
1088 '((interpolation (identifier) @font-lock-variable-name-face))
1089 1108
1090 :feature 'definition 1109 :feature 'definition
1091 :language 'python 1110 :language 'python
@@ -3766,15 +3785,16 @@ the python shell:
3766 (line-beginning-position) 3785 (line-beginning-position)
3767 start)))) 3786 start))))
3768 (substring (buffer-substring-no-properties start end)) 3787 (substring (buffer-substring-no-properties start end))
3769 (starts-at-point-min-p (save-restriction 3788 (starts-at-first-line-p (save-restriction
3770 (widen) 3789 (widen)
3771 (= (point-min) start))) 3790 (goto-char start)
3791 (= (line-number-at-pos) 1)))
3772 (encoding (python-info-encoding)) 3792 (encoding (python-info-encoding))
3773 (toplevel-p (zerop (save-excursion 3793 (toplevel-p (zerop (save-excursion
3774 (goto-char start) 3794 (goto-char start)
3775 (python-util-forward-comment 1) 3795 (python-util-forward-comment 1)
3776 (current-indentation)))) 3796 (current-indentation))))
3777 (fillstr (cond (starts-at-point-min-p 3797 (fillstr (cond (starts-at-first-line-p
3778 nil) 3798 nil)
3779 ((not no-cookie) 3799 ((not no-cookie)
3780 (concat 3800 (concat
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 5f5de500435..d68b57966ba 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -82,6 +82,16 @@
82(require 'ruby-mode) 82(require 'ruby-mode)
83 83
84(declare-function treesit-parser-create "treesit.c") 84(declare-function treesit-parser-create "treesit.c")
85(declare-function treesit-induce-sparse-tree "treesit.c")
86(declare-function treesit-node-child-by-field-name "treesit.c")
87(declare-function treesit-search-subtree "treesit.c")
88(declare-function treesit-node-parent "treesit.c")
89(declare-function treesit-node-next-sibling "treesit.c")
90(declare-function treesit-node-type "treesit.c")
91(declare-function treesit-node-child "treesit.c")
92(declare-function treesit-node-end "treesit.c")
93(declare-function treesit-node-start "treesit.c")
94(declare-function treesit-node-string "treesit.c")
85 95
86(defgroup ruby-ts nil 96(defgroup ruby-ts nil
87 "Major mode for editing Ruby code." 97 "Major mode for editing Ruby code."
@@ -304,7 +314,12 @@ values of OVERRIDE"
304 (array_pattern 314 (array_pattern
305 (identifier) @font-lock-variable-name-face) 315 (identifier) @font-lock-variable-name-face)
306 (keyword_pattern 316 (keyword_pattern
307 key: (hash_key_symbol) @font-lock-variable-name-face) 317 value: (identifier) @font-lock-variable-name-face)
318 (keyword_pattern
319 key: (hash_key_symbol) @font-lock-variable-name-face
320 !value)
321 (as_pattern
322 name: (identifier) @font-lock-variable-name-face)
308 (in_clause 323 (in_clause
309 pattern: (identifier) @font-lock-variable-name-face)) 324 pattern: (identifier) @font-lock-variable-name-face))
310 325
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index 0a79ae01248..0786150d906 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -194,7 +194,13 @@ Argument LANGUAGE is either `typescript' or `tsx'."
194 name: (array_pattern 194 name: (array_pattern
195 (identifier) 195 (identifier)
196 (identifier) @font-lock-function-name-face) 196 (identifier) @font-lock-function-name-face)
197 value: (array (number) (function)))) 197 value: (array (number) (function)))
198
199 (catch_clause
200 parameter: (identifier) @font-lock-variable-name-face)
201
202 (import_clause (identifier) @font-lock-variable-name-face)
203 (import_clause (named_imports (import_specifier (identifier)) @font-lock-variable-name-face)))
198 204
199 :language language 205 :language language
200 :override t 206 :override t
@@ -223,17 +229,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
223 parameters: 229 parameters:
224 [(_ (identifier) @font-lock-variable-name-face) 230 [(_ (identifier) @font-lock-variable-name-face)
225 (_ (_ (identifier) @font-lock-variable-name-face)) 231 (_ (_ (identifier) @font-lock-variable-name-face))
226 (_ (_ (_ (identifier) @font-lock-variable-name-face)))]) 232 (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
227
228 (return_statement (identifier) @font-lock-variable-name-face)
229
230 (binary_expression left: (identifier) @font-lock-variable-name-face)
231 (binary_expression right: (identifier) @font-lock-variable-name-face)
232
233 (arguments (identifier) @font-lock-variable-name-face)
234
235 (parenthesized_expression (identifier) @font-lock-variable-name-face)
236 (parenthesized_expression (_ (identifier) @font-lock-variable-name-face)))
237 233
238 :language language 234 :language language
239 :override t 235 :override t
@@ -245,8 +241,6 @@ Argument LANGUAGE is either `typescript' or `tsx'."
245 241
246 (pair key: (property_identifier) @font-lock-variable-name-face) 242 (pair key: (property_identifier) @font-lock-variable-name-face)
247 243
248 (pair value: (identifier) @font-lock-variable-name-face)
249
250 ((shorthand_property_identifier) @font-lock-property-face) 244 ((shorthand_property_identifier) @font-lock-property-face)
251 245
252 ((shorthand_property_identifier_pattern) 246 ((shorthand_property_identifier_pattern)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index d5cee9fa84f..916d83d407b 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
1;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*- 1;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
2 2
3;; Copyright (C) 2014-2023 Free Software Foundation, Inc. 3;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
4;; Version: 1.6.0 4;; Version: 1.6.1
5;; Package-Requires: ((emacs "26.1")) 5;; Package-Requires: ((emacs "26.1"))
6 6
7;; This is a GNU ELPA :core package. Avoid functionality that is not 7;; This is a GNU ELPA :core package. Avoid functionality that is not
diff --git a/lisp/simple.el b/lisp/simple.el
index 690968ca938..f5712177234 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2207,15 +2207,39 @@ to get different commands to edit and resubmit."
2207 "Predicate to use to determine which commands to include when completing. 2207 "Predicate to use to determine which commands to include when completing.
2208If it's nil, include all the commands. 2208If it's nil, include all the commands.
2209If it's a function, it will be called with two parameters: the 2209If it's a function, it will be called with two parameters: the
2210symbol of the command and a buffer. The predicate should return 2210symbol of the command and the current buffer. The predicate should
2211non-nil if the command should be present when doing \\`M-x TAB' 2211return non-nil if the command should be considered as a completion
2212in that buffer." 2212candidate for \\`M-x' in that buffer.
2213
2214Several predicate functions suitable for various optional behaviors
2215are available:
2216
2217 `command-completion-default-include-p'
2218 This excludes from completion candidates those commands
2219 which have been marked specific to modes other than the
2220 current buffer's mode. Commands that are not specific
2221 to any mode are included.
2222
2223 `command-completion-using-modes-p'
2224 This includes in completion candidates only commands
2225 marked as specific to the current buffer's mode.
2226
2227 `command-completion-using-modes-and-keymaps-p'
2228 This includes commands marked as specific to the current
2229 buffer's modes and commands that have keybindings in the
2230 current buffer's active local keymaps. It also includes
2231 several commands, like Cuztomize commands, which should
2232 always be avaliable."
2213 :version "28.1" 2233 :version "28.1"
2214 :group 'completion 2234 :group 'completion
2215 :type '(choice (const :tag "Don't exclude any commands" nil) 2235 :type '(choice (const :tag "Don't exclude any commands" nil)
2216 (const :tag "Exclude commands irrelevant to current buffer's mode" 2236 (const :tag "Exclude commands irrelevant to current buffer's mode"
2217 command-completion-default-include-p) 2237 command-completion-default-include-p)
2218 (function :tag "Other function"))) 2238 (const :tag "Include only commands relevant to current buffer's mode"
2239 command-completion-using-modes-p)
2240 (const :tag "Commands relevant to current buffer's mode or bound in its keymaps"
2241 command-completion-using-modes-and-keymaps-p)
2242 (function :tag "Other predicate function")))
2219 2243
2220(defun execute-extended-command-cycle () 2244(defun execute-extended-command-cycle ()
2221 "Choose the next version of the extended command predicates. 2245 "Choose the next version of the extended command predicates.
@@ -2401,6 +2425,35 @@ or (if one of MODES is a minor mode), if it is switched on in BUFFER."
2401 #'eq) 2425 #'eq)
2402 (seq-intersection modes global-minor-modes #'eq))) 2426 (seq-intersection modes global-minor-modes #'eq)))
2403 2427
2428(defun command-completion-using-modes-and-keymaps-p (symbol buffer)
2429 "Return non-nil if SYMBOL is marked for BUFFER's mode or bound in its keymaps."
2430 (with-current-buffer buffer
2431 (let ((keymaps
2432 ;; The major mode's keymap and any active minor modes.
2433 (nconc
2434 (and (current-local-map) (list (current-local-map)))
2435 (mapcar
2436 #'cdr
2437 (seq-filter
2438 (lambda (elem)
2439 (symbol-value (car elem)))
2440 minor-mode-map-alist)))))
2441 (or (command-completion-using-modes-p symbol buffer)
2442 ;; Include commands that are bound in a keymap in the
2443 ;; current buffer.
2444 (and (where-is-internal symbol keymaps)
2445 ;; But not if they have a command predicate that
2446 ;; says that they shouldn't. (This is the case
2447 ;; for `ignore' and `undefined' and similar
2448 ;; commands commonly found in keymaps.)
2449 (or (null (get symbol 'completion-predicate))
2450 (funcall (get symbol 'completion-predicate)
2451 symbol buffer)))
2452 ;; Include customize-* commands (do we need a list of such
2453 ;; "always available" commands? customizable?)
2454 (string-match-p "customize-" (symbol-name symbol))))))
2455
2456
2404(defun command-completion-button-p (category buffer) 2457(defun command-completion-button-p (category buffer)
2405 "Return non-nil if there's a button of CATEGORY at point in BUFFER." 2458 "Return non-nil if there's a button of CATEGORY at point in BUFFER."
2406 (with-current-buffer buffer 2459 (with-current-buffer buffer
@@ -2502,7 +2555,11 @@ Also see `suggest-key-bindings'."
2502(defun execute-extended-command (prefixarg &optional command-name typed) 2555(defun execute-extended-command (prefixarg &optional command-name typed)
2503 "Read a command name, then read the arguments and call the command. 2556 "Read a command name, then read the arguments and call the command.
2504To pass a prefix argument to the command you are 2557To pass a prefix argument to the command you are
2505invoking, give a prefix argument to `execute-extended-command'." 2558invoking, give a prefix argument to `execute-extended-command'.
2559
2560This command provides completion when reading the command name.
2561Which completion candidates are shown can be controlled by
2562customizing `read-extended-command-predicate'."
2506 (declare (interactive-only command-execute)) 2563 (declare (interactive-only command-execute))
2507 ;; FIXME: Remember the actual text typed by the user before completion, 2564 ;; FIXME: Remember the actual text typed by the user before completion,
2508 ;; so that we don't later on suggest the same shortening. 2565 ;; so that we don't later on suggest the same shortening.
@@ -8436,37 +8493,39 @@ are interchanged."
8436 (interactive "*p") 8493 (interactive "*p")
8437 (transpose-subr 'forward-word arg)) 8494 (transpose-subr 'forward-word arg))
8438 8495
8439(defvar transpose-sexps-function 8496(defun transpose-sexps-default-function (arg)
8440 (lambda (arg) 8497 "Default method to locate a pair of points for transpose-sexps."
8441 ;; Here we should try to simulate the behavior of 8498 ;; Here we should try to simulate the behavior of
8442 ;; (cons (progn (forward-sexp x) (point)) 8499 ;; (cons (progn (forward-sexp x) (point))
8443 ;; (progn (forward-sexp (- x)) (point))) 8500 ;; (progn (forward-sexp (- x)) (point)))
8444 ;; Except that we don't want to rely on the second forward-sexp 8501 ;; Except that we don't want to rely on the second forward-sexp
8445 ;; putting us back to where we want to be, since forward-sexp-function 8502 ;; putting us back to where we want to be, since forward-sexp-function
8446 ;; might do funny things like infix-precedence. 8503 ;; might do funny things like infix-precedence.
8447 (if (if (> arg 0) 8504 (if (if (> arg 0)
8448 (looking-at "\\sw\\|\\s_") 8505 (looking-at "\\sw\\|\\s_")
8449 (and (not (bobp)) 8506 (and (not (bobp))
8450 (save-excursion 8507 (save-excursion
8451 (forward-char -1) 8508 (forward-char -1)
8452 (looking-at "\\sw\\|\\s_")))) 8509 (looking-at "\\sw\\|\\s_"))))
8453 ;; Jumping over a symbol. We might be inside it, mind you. 8510 ;; Jumping over a symbol. We might be inside it, mind you.
8454 (progn (funcall (if (> arg 0) 8511 (progn (funcall (if (> arg 0)
8455 #'skip-syntax-backward #'skip-syntax-forward) 8512 #'skip-syntax-backward #'skip-syntax-forward)
8456 "w_") 8513 "w_")
8457 (cons (save-excursion (forward-sexp arg) (point)) (point))) 8514 (cons (save-excursion (forward-sexp arg) (point)) (point)))
8458 ;; Otherwise, we're between sexps. Take a step back before jumping 8515 ;; Otherwise, we're between sexps. Take a step back before jumping
8459 ;; to make sure we'll obey the same precedence no matter which 8516 ;; to make sure we'll obey the same precedence no matter which
8460 ;; direction we're going. 8517 ;; direction we're going.
8461 (funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward) 8518 (funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward)
8462 " .") 8519 " .")
8463 (cons (save-excursion (forward-sexp arg) (point)) 8520 (cons (save-excursion (forward-sexp arg) (point))
8464 (progn (while (or (forward-comment (if (> arg 0) 1 -1)) 8521 (progn (while (or (forward-comment (if (> arg 0) 1 -1))
8465 (not (zerop (funcall (if (> arg 0) 8522 (not (zerop (funcall (if (> arg 0)
8466 #'skip-syntax-forward 8523 #'skip-syntax-forward
8467 #'skip-syntax-backward) 8524 #'skip-syntax-backward)
8468 "."))))) 8525 ".")))))
8469 (point))))) 8526 (point)))))
8527
8528(defvar transpose-sexps-function #'transpose-sexps-default-function
8470 "If non-nil, `transpose-sexps' delegates to this function. 8529 "If non-nil, `transpose-sexps' delegates to this function.
8471 8530
8472This function takes one argument ARG, a number. Its expected 8531This function takes one argument ARG, a number. Its expected
diff --git a/lisp/textmodes/reftex-cite.el b/lisp/textmodes/reftex-cite.el
index 77373707d65..6beae816257 100644
--- a/lisp/textmodes/reftex-cite.el
+++ b/lisp/textmodes/reftex-cite.el
@@ -636,7 +636,7 @@ command, it will add another key, ignoring the value of
636 636
637The regular expression uses an expanded syntax: && is interpreted as `and'. 637The regular expression uses an expanded syntax: && is interpreted as `and'.
638Thus, `aaaa&&bbb' matches entries which contain both `aaaa' and `bbb'. 638Thus, `aaaa&&bbb' matches entries which contain both `aaaa' and `bbb'.
639While entering the regexp, completion on knows citation keys is possible. 639While entering the regexp, completion on known citation keys is possible.
640`=' is a good regular expression to match all entries in all files." 640`=' is a good regular expression to match all entries in all files."
641 (interactive) 641 (interactive)
642 642
diff --git a/lisp/treesit.el b/lisp/treesit.el
index a7f453a8899..25b2c70ce0a 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1143,20 +1143,17 @@ See `treesit-simple-indent-presets'.")
1143 (point)))) 1143 (point))))
1144 (cons 'prev-adaptive-prefix 1144 (cons 'prev-adaptive-prefix
1145 (lambda (_n parent &rest _) 1145 (lambda (_n parent &rest _)
1146 (save-excursion 1146 (let ((comment-start-bol
1147 (re-search-backward 1147 (save-excursion
1148 (rx (not (or " " "\t" "\n"))) nil t) 1148 (goto-char (treesit-node-start parent))
1149 (beginning-of-line) 1149 (line-beginning-position))))
1150 (and (>= (point) (treesit-node-start parent)) 1150 (save-excursion
1151 ;; `adaptive-fill-regexp' will not match "/*", 1151 (forward-line -1)
1152 ;; so we need to also try `comment-start-skip'. 1152 (and (>= (point) comment-start-bol)
1153 (or (and adaptive-fill-regexp 1153 adaptive-fill-regexp
1154 (looking-at adaptive-fill-regexp) 1154 (looking-at adaptive-fill-regexp)
1155 (> (- (match-end 0) (match-beginning 0)) 0) 1155 (> (match-end 0) (match-beginning 0))
1156 (match-end 0)) 1156 (match-end 0))))))
1157 (and comment-start-skip
1158 (looking-at comment-start-skip)
1159 (match-end 0)))))))
1160 ;; TODO: Document. 1157 ;; TODO: Document.
1161 (cons 'grand-parent 1158 (cons 'grand-parent
1162 (lambda (_n parent &rest _) 1159 (lambda (_n parent &rest _)
@@ -1187,9 +1184,12 @@ See `treesit-simple-indent-presets'.")
1187 res)))) 1184 res))))
1188 (cons 'or (lambda (&rest fns) 1185 (cons 'or (lambda (&rest fns)
1189 (lambda (node parent bol &rest _) 1186 (lambda (node parent bol &rest _)
1190 (seq-find 1187 (let (res)
1191 (lambda (fn) (funcall fn node parent bol)) 1188 (catch 'break
1192 fns)))) 1189 (dolist (fn fns)
1190 (setq res (funcall fn node parent bol))
1191 (and res (throw 'break t))))
1192 res))))
1193 (cons 'not (lambda (fn) 1193 (cons 'not (lambda (fn)
1194 (lambda (node parent bol &rest _) 1194 (lambda (node parent bol &rest _)
1195 (not (funcall fn node parent bol))))) 1195 (not (funcall fn node parent bol)))))
@@ -1338,10 +1338,10 @@ and returns
1338 (ANCHOR . OFFSET). 1338 (ANCHOR . OFFSET).
1339 1339
1340BOL is the position of the beginning of the line; NODE is the 1340BOL is the position of the beginning of the line; NODE is the
1341\"largest\" node that starts at BOL; PARENT is its parent; ANCHOR 1341\"largest\" node that starts at BOL (and isn't a root node);
1342is a point (not a node), and OFFSET is a number. Emacs finds the 1342PARENT is its parent; ANCHOR is a point (not a node), and OFFSET
1343column of ANCHOR and adds OFFSET to it as the final indentation 1343is a number. Emacs finds the column of ANCHOR and adds OFFSET to
1344of the current line.") 1344it as the final indentation of the current line.")
1345 1345
1346(defun treesit--indent-1 () 1346(defun treesit--indent-1 ()
1347 "Indent the current line. 1347 "Indent the current line.
@@ -1359,10 +1359,13 @@ Return (ANCHOR . OFFSET). This function is used by
1359 ((treesit-language-at (point)) 1359 ((treesit-language-at (point))
1360 (treesit-node-at bol (treesit-language-at (point)))) 1360 (treesit-node-at bol (treesit-language-at (point))))
1361 (t (treesit-node-at bol)))) 1361 (t (treesit-node-at bol))))
1362 (root (treesit-parser-root-node
1363 (treesit-node-parser smallest-node)))
1362 (node (treesit-parent-while 1364 (node (treesit-parent-while
1363 smallest-node 1365 smallest-node
1364 (lambda (node) 1366 (lambda (node)
1365 (eq bol (treesit-node-start node)))))) 1367 (and (eq bol (treesit-node-start node))
1368 (not (treesit-node-eq node root)))))))
1366 (let* 1369 (let*
1367 ((parser (if smallest-node 1370 ((parser (if smallest-node
1368 (treesit-node-parser smallest-node) 1371 (treesit-node-parser smallest-node)
@@ -2447,11 +2450,15 @@ in the region."
2447 (window-start) (window-end) treesit--explorer-language)) 2450 (window-start) (window-end) treesit--explorer-language))
2448 ;; Only highlight the current top-level construct. 2451 ;; Only highlight the current top-level construct.
2449 ;; Highlighting the whole buffer is slow and unnecessary. 2452 ;; Highlighting the whole buffer is slow and unnecessary.
2450 (top-level (treesit-node-first-child-for-pos 2453 ;; But if the buffer is small (ie, used in playground
2451 root (if (eolp) 2454 ;; style), just highlight the whole buffer.
2452 (max (point-min) (1- (point))) 2455 (top-level (if (< (buffer-size) 4000)
2453 (point)) 2456 root
2454 t)) 2457 (treesit-node-first-child-for-pos
2458 root (if (eolp)
2459 (max (point-min) (1- (point)))
2460 (point))
2461 t)))
2455 ;; Only highlight node when region is active, if we 2462 ;; Only highlight node when region is active, if we
2456 ;; highlight node at point the syntax tree is too jumpy. 2463 ;; highlight node at point the syntax tree is too jumpy.
2457 (nodes-hl 2464 (nodes-hl
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index acfd2c30f0c..eb01dede56e 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -485,17 +485,19 @@ use the face `diff-removed' for removed lines, and the face
485 ;; if below, use `diff-added'. 485 ;; if below, use `diff-added'.
486 (save-match-data 486 (save-match-data
487 (let ((limit (save-excursion (diff-beginning-of-hunk)))) 487 (let ((limit (save-excursion (diff-beginning-of-hunk))))
488 (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t)) 488 (when (< limit (point))
489 diff-indicator-added-face 489 (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
490 diff-indicator-removed-face))))) 490 diff-indicator-added-face
491 diff-indicator-removed-face))))))
491 (2 (if diff-use-changed-face 492 (2 (if diff-use-changed-face
492 'diff-changed-unspecified 493 'diff-changed-unspecified
493 ;; Otherwise, use the same method as above. 494 ;; Otherwise, use the same method as above.
494 (save-match-data 495 (save-match-data
495 (let ((limit (save-excursion (diff-beginning-of-hunk)))) 496 (let ((limit (save-excursion (diff-beginning-of-hunk))))
496 (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t)) 497 (when (< limit (point))
497 'diff-added 498 (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
498 'diff-removed)))))) 499 'diff-added
500 'diff-removed)))))))
499 ("^\\(?:Index\\|revno\\): \\(.+\\).*\n" 501 ("^\\(?:Index\\|revno\\): \\(.+\\).*\n"
500 (0 'diff-header) (1 'diff-index prepend)) 502 (0 'diff-header) (1 'diff-index prepend))
501 ("^\\(?:index .*\\.\\.\\|diff \\).*\n" . 'diff-header) 503 ("^\\(?:index .*\\.\\.\\|diff \\).*\n" . 'diff-header)