emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master 3b7198dc470: Merge from origin/emacs-29


From: Eli Zaretskii
Subject: master 3b7198dc470: Merge from origin/emacs-29
Date: Sat, 30 Dec 2023 04:53:26 -0500 (EST)

branch: master
commit 3b7198dc4703671fa8b00ed3bf159cb56d4d7ba3
Merge: aa0037aaf7c 53031528725
Author: Eli Zaretskii <eliz@gnu.org>
Commit: Eli Zaretskii <eliz@gnu.org>

    Merge from origin/emacs-29
    
    53031528725 Revert "Fix treesit-node-field-name and friends (bug#66674)"
    fa0bb88302b ; * src/buffer.c (syms_of_buffer) <default-directory>: Do...
    44517037aed ; Fix typo
    ccf46acefd2 ; Fix last change.
    c86b039dffc ; * etc/DEBUG: Improve advice for debugging native-compil...
    9afba605bbc Explain status "r" in `epa-list-keys`
    62714221968 ; * lisp/dired.el (dired--make-directory-clickable): Refo...
    fcbb0044899 Fix mouse clicks on directory line in Dired
    be8a7155b48 Fix 'split-root-window-right' and 'split-root-window-below'
    eb19984c4db Mark icalendar.el as maintained by emacs-devel
    03dc914fd37 ; Fix footnotes in ELisp Intro manual
    ceacf753958 Fix usage of `setq-default' and offer more suggestions
    2701da0eee5 Fix python-ts-mode triple quote syntax (bug#67262)
    683c7c96871 Increment parser timestamp when narrowing changes (bug#67...
    8ae42c825e1 ruby-ts-mode: Fix indentation for string_array closer
    9cfa498e0ab treesit-major-mode-setup: Use 'treesit--syntax-propertize...
    da2e440462b ruby-ts-mode: Fix an out-of-bounds error with heredoc at eob
    6ea507296a7 Correctly refontify changed region in tree-sitter modes (...
---
 doc/lispintro/emacs-lisp-intro.texi                | 35 ++++++----
 doc/lispref/control.texi                           |  2 +-
 doc/lispref/parsing.texi                           |  4 +-
 etc/DEBUG                                          | 12 +++-
 lisp/calendar/icalendar.el                         |  1 +
 lisp/dired.el                                      | 19 +++++-
 lisp/epa.el                                        |  2 +-
 lisp/progmodes/python.el                           | 17 +++++
 lisp/progmodes/ruby-ts-mode.el                     | 22 ++----
 lisp/treesit.el                                    | 78 +++++++++++++++++++++-
 lisp/window.el                                     |  6 +-
 src/buffer.c                                       |  4 +-
 src/treesit.c                                      | 13 ++--
 src/treesit.h                                      |  4 +-
 test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb |  4 ++
 15 files changed, 175 insertions(+), 48 deletions(-)

diff --git a/doc/lispintro/emacs-lisp-intro.texi 
b/doc/lispintro/emacs-lisp-intro.texi
index 4a0e8dfa1fc..673e1f0cfdf 100644
--- a/doc/lispintro/emacs-lisp-intro.texi
+++ b/doc/lispintro/emacs-lisp-intro.texi
@@ -16892,8 +16892,14 @@ remember to look here to remind myself.
 @node Text and Auto-fill
 @section Text and Auto Fill Mode
 
-Now we come to the part that turns on Text mode and
-Auto Fill mode.
+Now we come to the part that turns on Text mode and Auto Fill
+mode@footnote{
+This section suggests settings that are more suitable for writers.
+For programmers, the default mode will be set to the corresponding
+prog-mode automatically based on the type of the file.  And it's
+perfectly fine if you want to keep the fundamental mode as the default
+mode.
+}.
 
 @smallexample
 @group
@@ -16945,21 +16951,26 @@ Here is the line again; how does it work?
 
 @cindex Text Mode turned on
 @smallexample
-(setq major-mode 'text-mode)
+(setq-default major-mode 'text-mode)
 @end smallexample
 
 @noindent
 This line is a short, but complete Emacs Lisp expression.
 
-We are already familiar with @code{setq}.  It sets the following
-variable, @code{major-mode}, to the subsequent value, which is
-@code{text-mode}.  The single-quote before @code{text-mode} tells
-Emacs to deal directly with the @code{text-mode} symbol, not with
-whatever it might stand for.  @xref{setq, , Setting the Value of
-a Variable}, for a reminder of how @code{setq} works.  The main point
-is that there is no difference between the procedure you use to set
-a value in your @file{.emacs} file and the procedure you use anywhere
-else in Emacs.
+We are already familiar with @code{setq}.  We use a similar macro
+@code{setq-default} to set the following variable,
+@code{major-mode}@footnote{
+We use @code{setq-default} here because @code{text-mode} is
+buffer-local.  If we use @code{setq}, it will only apply to the
+current buffer, whereas using @code{setq-default} will also apply to
+newly created buffers.  This is not recommended for programmers.
+}, to the subsequent value, which is @code{text-mode}.  The
+single-quote before @code{text-mode} tells Emacs to deal directly with
+the @code{text-mode} symbol, not with whatever it might stand for.
+@xref{setq, , Setting the Value of a Variable}, for a reminder of how
+@code{setq} works.  The main point is that there is no difference
+between the procedure you use to set a value in your @file{.emacs}
+file and the procedure you use anywhere else in Emacs.
 
 @need 800
 Here is the next line:
diff --git a/doc/lispref/control.texi b/doc/lispref/control.texi
index d4bd8c14ae3..25c7be3adf5 100644
--- a/doc/lispref/control.texi
+++ b/doc/lispref/control.texi
@@ -729,7 +729,7 @@ has over @code{cl-case}
   ;; symbol
   ('success       (message "Done!"))
   ('would-block   (message "Sorry, can't do it now"))
-  ('read-only     (message "The shmliblick is read-only"))
+  ('read-only     (message "The schmilblick is read-only"))
   ('access-denied (message "You do not have the needed rights"))
 @end group
 @group
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 36238c1e1d7..df81a805e67 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -1071,8 +1071,8 @@ This function returns the field name of the @var{n}'th 
child of
 @var{node}.  It returns @code{nil} if there is no @var{n}'th child, or
 the @var{n}'th child doesn't have a field name.
 
-Note that @var{n} counts named nodes only, and @var{n} can be
-negative, e.g., @minus{}1 represents the last child.
+Note that @var{n} counts both named and anonymous children, and
+@var{n} can be negative, e.g., @minus{}1 represents the last child.
 @end defun
 
 @defun treesit-node-child-count node &optional named
diff --git a/etc/DEBUG b/etc/DEBUG
index 86bff45e7d9..55cec02c1c9 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -605,7 +605,17 @@ recommend to follow the procedure below to try to identify 
the cause:
  . Reduce the problematic .el file to the minimum by bisection, and
    try identifying the function that causes the problem.
 
- . Reduce the problematic function to the minimal code that still
+ . Try natively compiling the problematic file with
+   'native-comp-speed' set to 1 or even zero.  If doing that solves
+   the problem, you can use
+
+     (declare (speed 1))
+
+   at the beginning of the body of suspected function(s) to change
+   'native-comp-speed' only for those functions -- this could help you
+   identify the function(s) which cause(s) the problem.
+
+ . Reduce the problematic function(s) to the minimal code that still
    reproduces the problem.
 
  . Study the problem's artifacts, like Lisp or C backtraces, to try
diff --git a/lisp/calendar/icalendar.el b/lisp/calendar/icalendar.el
index 51e6a7d1170..0eca31b7dc4 100644
--- a/lisp/calendar/icalendar.el
+++ b/lisp/calendar/icalendar.el
@@ -3,6 +3,7 @@
 ;; Copyright (C) 2002-2023 Free Software Foundation, Inc.
 
 ;; Author:         Ulf Jasper <ulf.jasper@web.de>
+;; Maintainer:     emacs-devel@gnu.org
 ;; Created:        August 2002
 ;; Keywords:       calendar
 ;; Human-Keywords: calendar, diary, iCalendar, vCalendar
diff --git a/lisp/dired.el b/lisp/dired.el
index 5239e568de1..6b3d7303096 100644
--- a/lisp/dired.el
+++ b/lisp/dired.el
@@ -2017,9 +2017,22 @@ mouse-2: visit this file in other window"
               keymap ,(let* ((current-dir dir)
                              (click (lambda ()
                                       (interactive)
-                                      (if (assoc current-dir 
dired-subdir-alist)
-                                          (dired-goto-subdir current-dir)
-                                        (dired current-dir)))))
+                                      (cond
+                                       ((assoc current-dir dired-subdir-alist)
+                                        (dired-goto-subdir current-dir))
+                                       ;; If there is a wildcard chars
+                                       ;; in the directory name, don't
+                                       ;; use the alternate file machinery
+                                       ;; which tries to keep only one
+                                       ;; dired buffer open at once.
+                                       ;;
+                                       ;; FIXME: Is this code path reachable?
+                                       ((insert-directory-wildcard-in-dir-p
+                                         current-dir)
+                                        (dired current-dir))
+                                       (t
+                                        (dired--find-possibly-alternative-file
+                                         current-dir))))))
                         (define-keymap
                           "<mouse-2>" click
                           "<follow-link>" 'mouse-face
diff --git a/lisp/epa.el b/lisp/epa.el
index 8126584e4fb..b8af2a960f0 100644
--- a/lisp/epa.el
+++ b/lisp/epa.el
@@ -384,7 +384,7 @@ DOC is documentation text to insert at the start."
   (epa--list-keys name nil
                   "The letters at the start of a line have these meanings.
 e  expired key.  n  never trust.  m  trust marginally.  u  trust ultimately.
-f  trust fully (keys you have signed, usually).
+f  trust fully (keys you have signed, usually).  r  revoked key.
 q  trust status questionable.  -  trust status unspecified.
  See GPG documentation for more explanation.
 \n"))
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 211969140ab..ff9402eaaaf 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1238,6 +1238,21 @@ For NODE, OVERRIDE, START, END, and ARGS, see
      (treesit-node-start node) (treesit-node-end node)
      'font-lock-variable-use-face override start end)))
 
+(defun python--treesit-syntax-propertize (start end)
+  "Propertize triple-quote strings between START and END."
+  (save-excursion
+    (goto-char start)
+    (while (re-search-forward (rx (or "\"\"\"" "'''")) end t)
+      (let ((node (treesit-node-at (point))))
+        ;; The triple quotes surround a non-empty string.
+        (when (equal (treesit-node-type node) "string_content")
+          (let ((start (treesit-node-start node))
+                (end (treesit-node-end node)))
+            (put-text-property (1- start) start
+                               'syntax-table (string-to-syntax "|"))
+            (put-text-property end (min (1+ end) (point-max))
+                               'syntax-table (string-to-syntax "|"))))))))
+
 
 ;;; Indentation
 
@@ -6854,6 +6869,8 @@ implementations: `python-mode' and `python-ts-mode'."
                 #'python--treesit-defun-name)
     (treesit-major-mode-setup)
 
+    (setq-local syntax-propertize-function #'python--treesit-syntax-propertize)
+
     (python-skeleton-add-menu-items)
 
     (when python-indent-guess-indent-offset
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index c7e0b8f49ad..78a911d2189 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -753,8 +753,9 @@ a statement container is a node that matches
 
            ((match "}" "hash")  ruby-ts--parent-call-or-bol 0)
            ((parent-is "hash")  ruby-ts--parent-call-or-bol ruby-indent-level)
-           ((match "]" "array") ruby-ts--parent-call-or-bol 0)
-           ((parent-is "array") ruby-ts--parent-call-or-bol ruby-indent-level)
+           ((match "]" "^array") ruby-ts--parent-call-or-bol 0)
+           ((parent-is "^array") ruby-ts--parent-call-or-bol ruby-indent-level)
+           ((match ")" "string_array") ruby-ts--parent-call-or-bol 0)
 
            ((parent-is "pair") ruby-ts--parent-call-or-bol 0)
 
@@ -1063,8 +1064,9 @@ leading double colon is not added."
         ('heredoc
          (put-text-property (treesit-node-start node) (1+ (treesit-node-start 
node))
                             'syntax-table (string-to-syntax "\""))
-         (put-text-property (treesit-node-end node) (1+ (treesit-node-end 
node))
-                            'syntax-table (string-to-syntax "\"")))
+         (when (< (treesit-node-end node) (point-max))
+           (put-text-property (treesit-node-end node) (1+ (treesit-node-end 
node))
+                              'syntax-table (string-to-syntax "\""))))
         ('percent
          ;; FIXME: Put the first one on the first paren in both %Q{} and %().
          ;; That would stop electric-pair-mode from pairing, though.  Hmm.
@@ -1192,20 +1194,8 @@ leading double colon is not added."
 
   (treesit-major-mode-setup)
 
-  (treesit-parser-add-notifier (car (treesit-parser-list))
-                               #'ruby-ts--parser-after-change)
-
   (setq-local syntax-propertize-function #'ruby-ts--syntax-propertize))
 
-(defun ruby-ts--parser-after-change (ranges parser)
-  ;; Make sure we re-syntax-propertize the full node that is being
-  ;; edited.  This is most pertinent to multi-line complex nodes such
-  ;; as heredocs.
-  (when ranges
-    (with-current-buffer (treesit-parser-buffer parser)
-      (syntax-ppss-flush-cache (cl-loop for r in ranges
-                                        minimize (car r))))))
-
 (if (treesit-ready-p 'ruby)
     ;; Copied from ruby-mode.el.
     (add-to-list 'auto-mode-alist
diff --git a/lisp/treesit.el b/lisp/treesit.el
index c6b9d8ff4bc..d4857dea72e 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -385,7 +385,6 @@ If NAMED is non-nil, collect named child only."
   "Return the index of NODE in its parent.
 If NAMED is non-nil, count named child only."
   (let ((count 0))
-    ;; TODO: Use next-sibling as it's more efficient.
     (while (setq node (treesit-node-prev-sibling node named))
       (cl-incf count))
     count))
@@ -393,7 +392,7 @@ If NAMED is non-nil, count named child only."
 (defun treesit-node-field-name (node)
   "Return the field name of NODE as a child of its parent."
   (when-let ((parent (treesit-node-parent node))
-             (idx (treesit-node-index node t)))
+             (idx (treesit-node-index node)))
     (treesit-node-field-name-for-child parent idx)))
 
 (defun treesit-node-get (node instructions)
@@ -1331,6 +1330,72 @@ parser notifying of the change."
       (with-silent-modifications
         (put-text-property (car range) (cdr range) 'fontified nil)))))
 
+(defvar-local treesit--syntax-propertize-start nil
+  "If non-nil, next `syntax-propertize' should start at this position.
+
+When tree-sitter parser reparses, it calls
+`treesit--syntax-propertize-notifier' with the affected region,
+and that function sets this variable to the start of the affected
+region.")
+
+(defun treesit--syntax-propertize-notifier (ranges parser)
+  "Sets `treesit--syntax-propertize-start' to the smallest start.
+Specifically, the smallest start position among all the ranges in
+RANGES for PARSER."
+  (with-current-buffer (treesit-parser-buffer parser)
+    (when-let* ((range-starts (mapcar #'car ranges))
+                (min-range-start
+                 (seq-reduce
+                  #'min (cdr range-starts) (car range-starts))))
+      (if (null treesit--syntax-propertize-start)
+          (setq treesit--syntax-propertize-start min-range-start)
+        (setq treesit--syntax-propertize-start
+              (min treesit--syntax-propertize-start min-range-start))))))
+
+(defvar-local treesit--pre-redisplay-tick nil
+  "The last `buffer-chars-modified-tick' that we've processed.
+Because `pre-redisplay-functions' could be called multiple times
+during a single command loop, we use this variable to debounce
+calls to `treesit--pre-redisplay'.")
+
+(defun treesit--pre-redisplay (&rest _)
+  "Force reparse and consequently run all notifiers.
+
+One of the notifiers is `treesit--font-lock-notifier', which will
+mark the region whose syntax has changed to \"need to refontify\".
+
+For example, when the user types the final slash of a C block
+comment /* xxx */, not only do we need to fontify the slash, but
+also the whole block comment, which previously wasn't fontified
+as comment due to incomplete parse tree."
+  (unless (eq treesit--pre-redisplay-tick (buffer-chars-modified-tick))
+    ;; `treesit-update-ranges' will force the host language's parser to
+    ;; reparse and set correct ranges for embedded parsers.  Then
+    ;; `treesit-parser-root-node' will force those parsers to reparse.
+    (treesit-update-ranges)
+    ;; Force repase on _all_ the parsers might not be necessary, but
+    ;; this is probably the most robust way.
+    (dolist (parser (treesit-parser-list))
+      (treesit-parser-root-node parser))
+    (setq treesit--pre-redisplay-tick (buffer-chars-modified-tick))))
+
+(defun treesit--pre-syntax-ppss (start end)
+  "Force reparse and consequently run all notifiers.
+
+Similar to font-lock, we want to update the `syntax' text
+property before `syntax-ppss' starts working on the text.  We
+also want to extend the to-be-propertized region to include the
+whole region affected by the last reparse.
+
+START and END mark the current to-be-propertized region."
+  (treesit--pre-redisplay)
+  (let ((new-start treesit--syntax-propertize-start))
+    (if (and new-start (< new-start start))
+        (progn
+          (setq treesit--syntax-propertize-start nil)
+          (cons new-start end))
+      nil)))
+
 ;;; Indent
 
 (define-error 'treesit-indent-error
@@ -2853,7 +2918,14 @@ before calling this function."
     (treesit-font-lock-recompute-features)
     (dolist (parser (treesit-parser-list))
       (treesit-parser-add-notifier
-       parser #'treesit--font-lock-notifier)))
+       parser #'treesit--font-lock-notifier))
+    (add-hook 'pre-redisplay-functions #'treesit--pre-redisplay 0 t))
+  ;; Syntax
+  (dolist (parser (treesit-parser-list))
+    (treesit-parser-add-notifier
+     parser #'treesit--syntax-propertize-notifier))
+  (add-hook 'syntax-propertize-extend-region-functions
+            #'treesit--pre-syntax-ppss 0 t)
   ;; Indent.
   (when treesit-simple-indent-rules
     (setq-local treesit-simple-indent-rules
diff --git a/lisp/window.el b/lisp/window.el
index 40070a4d929..24495b21e10 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -5737,7 +5737,8 @@ The current window configuration is retained in the top 
window,
 the lower window takes up the whole width of the frame.  SIZE is
 handled as in `split-window-below', and interactively is the
 prefix numeric argument."
-  (interactive "p")
+  (interactive `(,(when current-prefix-arg
+                    (prefix-numeric-value current-prefix-arg))))
   (split-window-below size (frame-root-window)))
 
 (defun split-window-right (&optional size window-to-split)
@@ -5777,7 +5778,8 @@ The current window configuration is retained within the 
left
 window, and a new window is created on the right, taking up the
 whole height of the frame.  SIZE is treated as by
 `split-window-right' and interactively, is the prefix numeric argument."
-  (interactive "p")
+  (interactive `(,(when current-prefix-arg
+                    (prefix-numeric-value current-prefix-arg))))
   (split-window-right size (frame-root-window)))
 
 ;;; Balancing windows.
diff --git a/src/buffer.c b/src/buffer.c
index 637830704e6..5b4c4ea390e 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -5367,8 +5367,8 @@ visual lines rather than logical lines.  See the 
documentation of
                     Qstringp,
                     doc: /* Name of default directory of current buffer.
 It should be an absolute directory name; on GNU and Unix systems,
-these names start with `/' or `~' and end with `/'.
-To interactively change the default directory, use command `cd'. */);
+these names start with "/" or "~" and end with "/".
+To interactively change the default directory, use the command `cd'. */);
 
   DEFVAR_PER_BUFFER ("auto-fill-function", &BVAR (current_buffer, 
auto_fill_function),
                     Qnil,
diff --git a/src/treesit.c b/src/treesit.c
index c65873a28f7..296a404a9d1 100644
--- a/src/treesit.c
+++ b/src/treesit.c
@@ -948,7 +948,10 @@ treesit_sync_visible_region (Lisp_Object parser)
      this function is called), we need to reparse.  */
   if (visible_beg != BUF_BEGV_BYTE (buffer)
       || visible_end != BUF_ZV_BYTE (buffer))
-    XTS_PARSER (parser)->need_reparse = true;
+    {
+      XTS_PARSER (parser)->need_reparse = true;
+      XTS_PARSER (parser)->timestamp++;
+    }
 
   /* Before we parse or set ranges, catch up with the narrowing
      situation.  We change visible_beg and visible_end to match
@@ -1722,6 +1725,7 @@ buffer.  */)
              ranges);
 
   XTS_PARSER (parser)->need_reparse = true;
+  XTS_PARSER (parser)->timestamp++;
   return Qnil;
 }
 
@@ -2066,8 +2070,9 @@ DEFUN ("treesit-node-field-name-for-child",
 Return nil if there's no Nth child, or if it has no field.
 If NODE is nil, return nil.
 
-Note that N counts named nodes only.  Also, N could be negative, e.g.,
--1 represents the last child.  */)
+N counts all children, i.e., named ones and anonymous ones.
+
+N could be negative, e.g., -1 represents the last child.  */)
   (Lisp_Object node, Lisp_Object n)
 {
   if (NILP (node))
@@ -2081,7 +2086,7 @@ Note that N counts named nodes only.  Also, N could be 
negative, e.g.,
 
   /* Process negative index.  */
   if (idx < 0)
-    idx = ts_node_named_child_count (treesit_node) + idx;
+    idx = ts_node_child_count (treesit_node) + idx;
   if (idx < 0)
     return Qnil;
   if (idx > UINT32_MAX)
diff --git a/src/treesit.h b/src/treesit.h
index ef7e2e15317..75d3ed778c4 100644
--- a/src/treesit.h
+++ b/src/treesit.h
@@ -61,7 +61,9 @@ struct Lisp_TS_Parser
   /* Re-parsing an unchanged buffer is not free for tree-sitter, so we
      only make it re-parse when need_reparse == true.  That usually
      means some change is made in the buffer.  But others could set
-     this field to true to force tree-sitter to re-parse.  */
+     this field to true to force tree-sitter to re-parse.  When you
+     set this to true, you should _always_ also increment
+     timestamp.  */
   bool need_reparse;
   /* These two positions record the buffer byte position (1-based) of
      the "visible region" that tree-sitter sees.  Before re-parse, we
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb 
b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
index 4be532a5e9d..8e372de6e45 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby-ts.rb
@@ -85,6 +85,10 @@ foo(foo, bar:
 foo(foo, :bar =>
     tee)
 
+foo = %w[
+  asd
+]
+
 # Local Variables:
 # mode: ruby-ts
 # ruby-after-operator-indent: t



reply via email to

[Prev in Thread] Current Thread [Next in Thread]