Merge from origin/emacs-29
5303152872
Revert "Fix treesit-node-field-name and friends (bug#66674)"fa0bb88302
; * src/buffer.c (syms_of_buffer) <default-directory>: Do...44517037ae
; Fix typoccf46acefd
; Fix last change.c86b039dff
; * etc/DEBUG: Improve advice for debugging native-compil...9afba605bb
Explain status "r" in `epa-list-keys`6271422196
; * lisp/dired.el (dired--make-directory-clickable): Refo...fcbb004489
Fix mouse clicks on directory line in Diredbe8a7155b4
Fix 'split-root-window-right' and 'split-root-window-below'eb19984c4d
Mark icalendar.el as maintained by emacs-devel03dc914fd3
; Fix footnotes in ELisp Intro manualceacf75395
Fix usage of `setq-default' and offer more suggestions2701da0eee
Fix python-ts-mode triple quote syntax (bug#67262)683c7c9687
Increment parser timestamp when narrowing changes (bug#67...8ae42c825e
ruby-ts-mode: Fix indentation for string_array closer9cfa498e0a
treesit-major-mode-setup: Use 'treesit--syntax-propertize...da2e440462
ruby-ts-mode: Fix an out-of-bounds error with heredoc at eob6ea507296a
Correctly refontify changed region in tree-sitter modes (...
This commit is contained in:
commit
3b7198dc47
15 changed files with 175 additions and 48 deletions
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
12
etc/DEBUG
12
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -85,6 +85,10 @@
|
|||
foo(foo, :bar =>
|
||||
tee)
|
||||
|
||||
foo = %w[
|
||||
asd
|
||||
]
|
||||
|
||||
# Local Variables:
|
||||
# mode: ruby-ts
|
||||
# ruby-after-operator-indent: t
|
||||
|
|
Loading…
Add table
Reference in a new issue