mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
Merge from origin/emacs-30
d509a35699
Fix regression in widget-move (bug#72995)ef0276de82
; * lisp/cus-edit.el (setopt): Doc fix. (Bug#73098)b115c2d5eb
; * lisp/minibuffer.el (completion-pcm--merge-completions...3cda1fdc3b
Correctly include fixed strings before a prefix wildcard ...57d93d0259
; * lisp/treesit.el (treesit-major-mode-setup): Doc fix.ad289f364e
; Improve documentation of 'easy-menu-define'3cad7cc8dc
Set treesit-primary-parser for c and elixir ts mode2f243fb91d
; Minor doc fix in treesit.el6a6d7925c9
Fix range handling so it works for multibyte buffer (bug#...76faf7e609
Revert "Read more on each call to treesit's buffer reader"c70bd0e3fe
Fix tree-sitter indent preset prev-adaptive-prefix272df33fb8
; * CONTRIBUTE: Minor copyedits.8e1187e336
Improve NEWS entriesca3932121a
Don't fail uniquify-tests in non-version-controlled sourc...79f68597ab
; * etc/ORG-NEWS: Fix typo.d66b70f360
* doc/misc/auth.texi: Minor copy edits.2c6b7b2da9
; * admin/MAINTAINERS: Remove some entries for Artur Mala...11e7ae3964
Fix bug#72254 # Conflicts: # etc/NEWS
This commit is contained in:
commit
0cf9886cdf
@ -208,8 +208,9 @@ formatting them:
|
||||
|
||||
- Unindented ChangeLog entries normally come next. However, if the
|
||||
commit couldn't be properly summarized in the brief summary line,
|
||||
you can put a paragraph (after the empty line and before the
|
||||
individual ChangeLog entries) that further describes the commit.
|
||||
you can put one or more paragraphs (after the empty line and before
|
||||
the individual ChangeLog entries) that further describe(s) the
|
||||
commit.
|
||||
|
||||
- Lines in ChangeLog entries should preferably be not longer than 63
|
||||
characters, and must not exceed 78 characters, unless they consist
|
||||
|
@ -58,9 +58,7 @@ Bastien Guerry
|
||||
doc/misc/org.texi
|
||||
|
||||
Artur Malabarba
|
||||
lisp/emacs-lisp/package.el
|
||||
lisp/emacs-lisp/let-alist.el
|
||||
lisp/character-fold.el
|
||||
|
||||
Michael Albinus
|
||||
Tramp
|
||||
@ -295,9 +293,6 @@ Stefan Monnier
|
||||
lisp/progmodes/tcl.el
|
||||
lisp/emacs-lisp/easymenu.el
|
||||
|
||||
Artur Malabarba
|
||||
lisp/isearch.el
|
||||
|
||||
Paul Eggert
|
||||
.dir-locals.el
|
||||
.gitattributes
|
||||
|
@ -3243,7 +3243,8 @@ contents are given by @var{menu}.
|
||||
|
||||
If @var{symbol} is non-@code{nil}, it should be a symbol; then this
|
||||
macro defines @var{symbol} as a function for popping up the menu
|
||||
(@pxref{Pop-Up Menus}), with @var{doc} as its documentation string.
|
||||
(@pxref{Pop-Up Menus}), with @var{doc} as its documentation string. It
|
||||
also defines @var{symbol} as a variable whose value is the menu.
|
||||
@var{symbol} should not be quoted.
|
||||
|
||||
Regardless of the value of @var{symbol}, if @var{maps} is a keymap,
|
||||
|
@ -73,7 +73,7 @@ It is a way for multiple applications to share a single configuration
|
||||
@chapter Overview
|
||||
|
||||
The auth-source library is simply a way for Emacs and Gnus, among
|
||||
others, to answer the old burning question ``What are my user name and
|
||||
others, to answer the old burning question ``What is my user name and
|
||||
password?''
|
||||
|
||||
(This is different from the old question about burning ``Where is the
|
||||
@ -82,11 +82,11 @@ fire extinguisher, please?''.)
|
||||
The auth-source library supports more than just the user name or the
|
||||
password (known as the secret).
|
||||
|
||||
Similarly, the auth-source library supports multiple storage backend,
|
||||
Similarly, the auth-source library supports multiple storage backends,
|
||||
currently either the classic ``netrc'' backend, examples of which you
|
||||
can see later in this document, JSON files, the Secret Service API, and pass, the
|
||||
standard unix password manager. This is done with EIEIO-based
|
||||
backends and you can write your own if you want.
|
||||
can see later in this document, JSON files, the Secret Service API, and
|
||||
@samp{pass}, the standard unix password manager. This is done with
|
||||
EIEIO-based backends, and you can write your own if you want.
|
||||
|
||||
@node Help for users
|
||||
@chapter Help for users
|
||||
@ -363,7 +363,7 @@ collections such as @code{"login"}.
|
||||
|
||||
With GNOME Keyring, there exists a special collection called
|
||||
@code{"session"}, which has the lifetime of the user being logged in.
|
||||
Its data are not stored on disk and go away when the user logs out.
|
||||
Its data is not stored on disk and goes away when the user logs out.
|
||||
Therefore, it can be used to store and retrieve secret items
|
||||
temporarily. The @code{"session"} collection is better than a
|
||||
persistent collection when the secret items should not live
|
||||
@ -372,7 +372,7 @@ by the string @code{"session"}, or by @code{nil}, whenever a
|
||||
collection parameter is needed.
|
||||
|
||||
However, other Secret Service provider don't create this temporary
|
||||
@code{"session"} collection. You shall check first that this
|
||||
@code{"session"} collection. You must check first that this
|
||||
collection exists, before you use it.
|
||||
|
||||
@defun secrets-list-items collection
|
||||
@ -474,13 +474,13 @@ functions.
|
||||
@chapter The Unix password store
|
||||
|
||||
@uref{https://www.passwordstore.org,,The standard unix password
|
||||
manager} (or just @code{pass}) stores your passwords in
|
||||
manager} (or just @samp{pass}) stores your passwords in
|
||||
@code{gpg}-protected files following the Unix philosophy. The store
|
||||
location (any directory) must be specified in the
|
||||
@code{auth-source-pass-filename} variable which defaults to
|
||||
@file{~/.password-store}.
|
||||
|
||||
Emacs integration of @code{pass} follows the approach suggested by the
|
||||
Emacs integration of @samp{pass} follows the approach suggested by the
|
||||
pass project itself for data organization to find data. In
|
||||
particular, to store a password for the user @code{rms} on the host
|
||||
@code{gnu.org} and port @code{22}, you should use one of the following
|
||||
@ -531,12 +531,13 @@ while searching for an entry matching the @code{rms} user on host
|
||||
However, such processing is not applied when the option
|
||||
@code{auth-source-pass-extra-query-keywords} is set to @code{t}.
|
||||
|
||||
Users of @code{pass} may also be interested in functionality provided
|
||||
Users of @samp{pass} may also be interested in functionality provided
|
||||
by other Emacs packages:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
@uref{https://git.zx2c4.com/password-store/tree/contrib/emacs/password-store.el,,password-store}: library wrapping @code{pass};
|
||||
@uref{https://git.zx2c4.com/password-store/tree/contrib/emacs/password-store.el,,password-store}:
|
||||
library wrapping @samp{pass};
|
||||
@item
|
||||
@uref{https://github.com/NicolasPetton/pass,,pass}: major mode to manipulate the store and edit entries;
|
||||
@item
|
||||
@ -585,7 +586,7 @@ The auth-source library only has a few functions for external use.
|
||||
|
||||
@defun auth-source-search &rest spec &key type max host user port secret require create delete &allow-other-keys
|
||||
This function searches (or modifies) authentication backends according
|
||||
to @var{spec}. See the function's doc-string for details.
|
||||
to @var{spec}. See the function's docstring for details.
|
||||
@c TODO more details.
|
||||
@end defun
|
||||
|
||||
@ -635,8 +636,6 @@ authentication information we just used, if it was newly created.''
|
||||
After the first time it's called, the @code{:save-function} will not
|
||||
run again (but it will log something if you have set
|
||||
@code{auth-source-debug} to @code{'trivia}). This is so it won't ask
|
||||
the same question again, which is annoying. This is so it won't ask
|
||||
the same question again, which is annoying. This is so it won't ask
|
||||
the same question again, which is annoying.
|
||||
|
||||
So the responsibility of the API user that specified @code{:create t}
|
||||
|
84
etc/NEWS.30
84
etc/NEWS.30
@ -150,7 +150,7 @@ number has been bumped to 2048 bits.
|
||||
+++
|
||||
** URL now never sends user email addresses in HTTP requests.
|
||||
Emacs never sent email addresses by default, but it used to be
|
||||
possible to customize 'url-privacy-level' so that the users email
|
||||
possible to customize 'url-privacy-level' so that the user's email
|
||||
address was sent along in HTTP requests. This feature has now been
|
||||
removed, as it was considered more dangerous than useful. RFC 9110
|
||||
(§ 10.1.2) also recommends against it. The user option
|
||||
@ -670,15 +670,15 @@ that shows as diffs replacements in the marked files in Dired.
|
||||
+++
|
||||
** New mode of prompting for register names and showing preview.
|
||||
The new user option 'register-use-preview' can be customized to the
|
||||
value t or insist to request a different user interface of prompting for
|
||||
value t or 'insist' to request a different user interface of prompting for
|
||||
register names and previewing the registers: Emacs will require
|
||||
confirmation for overwriting the value of a register, and will show
|
||||
the preview of registers without delay. You can also customize this
|
||||
new option to disable the preview completely.
|
||||
|
||||
The default value of 'register-use-preview' preserves the behavior of
|
||||
Emacs 29 and before. See the Info node "(emacs) Registers" for more
|
||||
details about the new UI and its variants.
|
||||
The default value of 'register-use-preview' ('traditional') preserves the
|
||||
behavior of Emacs 29 and before. See the Info node "(emacs) Registers"
|
||||
for more details about the new UI and its variants.
|
||||
|
||||
+++
|
||||
** New advanced macro counter commands.
|
||||
@ -1464,8 +1464,8 @@ bookmark URIs.
|
||||
*** New command 'eww-copy-alternate-url'.
|
||||
It copies an alternate link on the page currently visited in EWW into
|
||||
the kill ring. Alternate links are optional metadata that HTML pages
|
||||
use for linking to their alternative representations, such as
|
||||
translated versions or associated RSS feeds.
|
||||
use for linking to their alternative representations, such as translated
|
||||
versions or associated RSS feeds. It is bound to 'A' by default.
|
||||
|
||||
+++
|
||||
*** 'eww-open-in-new-buffer' supports the prefix argument.
|
||||
@ -1565,9 +1565,10 @@ following to your init file:
|
||||
|
||||
---
|
||||
*** New user option 'package-vc-register-as-project'.
|
||||
When non-nil, it will automatically register every package as a
|
||||
project, that you can quickly select using 'project-switch-project'
|
||||
('C-x p p').
|
||||
When non-nil, 'package-vc-install' and 'package-vc-checkout' will
|
||||
automatically register every package they install as a project, that you
|
||||
can quickly select using 'project-switch-project' ('C-x p p'). Default
|
||||
is t.
|
||||
|
||||
---
|
||||
*** New user option 'package-vc-allow-build-commands'.
|
||||
@ -1592,9 +1593,9 @@ in a clean environment.
|
||||
|
||||
+++
|
||||
*** New user option 'flymake-indicator-type'.
|
||||
This user option controls which error indicator type Flymake should use
|
||||
in current buffer. Depending on your preference, this can either use
|
||||
fringes or margins for indicating errors.
|
||||
This controls which error indicator type Flymake should use in the
|
||||
current buffer. Depending on your preference, this can either use
|
||||
fringes or margins for indicating errors, the default is 'margins'.
|
||||
|
||||
+++
|
||||
*** New user option 'flymake-margin-indicators-string'.
|
||||
@ -1603,14 +1604,14 @@ the margin indicator.
|
||||
|
||||
+++
|
||||
*** New user option 'flymake-autoresize-margins'.
|
||||
If non-nil, Flymake will resize the margins when 'flymake-mode' is
|
||||
turned on or off.
|
||||
If non-nil (the default), Flymake will resize the margins when
|
||||
'flymake-mode' is turned on or off.
|
||||
Only relevant if 'flymake-indicator-type' is set to 'margins'.
|
||||
|
||||
+++
|
||||
*** New user option 'flymake-margin-indicator-position'.
|
||||
It controls which margin (left or right) is used for margin
|
||||
indicators.
|
||||
It controls whether to use margins for margin indicators, and which
|
||||
margin (left or right) to use. Default is to use the left margin.
|
||||
|
||||
+++
|
||||
*** New user option 'flymake-show-diagnostics-at-end-of-line'.
|
||||
@ -1618,7 +1619,7 @@ When non-nil, Flymake shows summarized descriptions of diagnostics at
|
||||
the end of the line. Depending on your preference, this can either be
|
||||
distracting and easily confused with actual code, or a significant
|
||||
early aid that relieves you from moving the buffer or reaching for the
|
||||
mouse to consult an error message.
|
||||
mouse to consult an error message. Default is nil.
|
||||
|
||||
** Flyspell
|
||||
|
||||
@ -1626,6 +1627,7 @@ mouse to consult an error message.
|
||||
*** New user option 'flyspell-check-changes'.
|
||||
When non-nil, Flyspell mode spell-checks only words that you edited; it
|
||||
does not check unedited words just because you move point across them.
|
||||
Default is nil.
|
||||
|
||||
---
|
||||
** JS mode.
|
||||
@ -1647,7 +1649,7 @@ buffers contain Javascript code.
|
||||
*** New user option 'python-indent-block-paren-deeper'.
|
||||
If non-nil, increase the indentation of the lines inside parens in a
|
||||
header of a block when they are indented to the same level as the body
|
||||
of the block:
|
||||
of the block, producing:
|
||||
|
||||
if (some_expression
|
||||
and another_expression):
|
||||
@ -1659,6 +1661,8 @@ instead of:
|
||||
and another_expression):
|
||||
do_something()
|
||||
|
||||
Default is nil.
|
||||
|
||||
---
|
||||
*** New user option 'python-interpreter-args'.
|
||||
This allows the user to specify command line arguments to the non
|
||||
@ -1699,8 +1703,8 @@ This keyword enables the user to install packages using package-vc.el.
|
||||
|
||||
+++
|
||||
*** New user option 'use-package-vc-prefer-newest'.
|
||||
This allows the user to always install the newest commit of a package
|
||||
when using the ':vc' keyword.
|
||||
If non-nil, always install the newest commit of a package when using the
|
||||
':vc' keyword rather than its stable release. Default is nil.
|
||||
|
||||
** Gnus
|
||||
|
||||
@ -1749,6 +1753,7 @@ Controls how the 'dictionary-search' command prompts for and displays
|
||||
dictionary definitions. Customize this user option to 'help' to have
|
||||
'dictionary-search' display definitions in a "*Help*" buffer and
|
||||
provide dictionary-based minibuffer completion for word selection.
|
||||
Default is nil, which means to use a "*Dictionary*" buffer.
|
||||
|
||||
---
|
||||
*** New user option 'dictionary-read-word-prompt'.
|
||||
@ -1971,11 +1976,11 @@ If non-nil, moving point forward or backward between widgets by typing
|
||||
*** New user option 'ruby-rubocop-use-bundler'.
|
||||
By default it retains the previous behavior: read the contents of
|
||||
Gemfile and act accordingly. But you can also set it to t or nil to
|
||||
skip the check.
|
||||
skip checking the Gemfile.
|
||||
|
||||
*** New user option 'ruby-bracketed-args-indent'.
|
||||
When it is set to nil, multiple consecutive open braces/brackets/parens
|
||||
result in only one additional indentation level.
|
||||
result in only one additional indentation level. Default is t.
|
||||
|
||||
** Thingatpt
|
||||
|
||||
@ -2003,7 +2008,8 @@ will return the URL for that bug.
|
||||
*** New user option 'Buffer-menu-group-by'.
|
||||
It controls how buffers are divided into groups that are displayed with
|
||||
headings using Outline minor mode. Using commands that mark buffers
|
||||
on the outline heading line will mark all buffers in the outline.
|
||||
on the outline heading line will mark all buffers in the outline. By
|
||||
default, no grouping is performed.
|
||||
|
||||
+++
|
||||
*** New command 'Buffer-menu-toggle-internal'.
|
||||
@ -2025,9 +2031,9 @@ Previously, it was set to t, but this broke remote file name detection.
|
||||
|
||||
---
|
||||
*** More control on automatic update of Proced buffers.
|
||||
The user option 'proced-auto-update-flag' can now be set to two
|
||||
additional values, which control automatic updates of Proced buffers
|
||||
that are not displayed in some window.
|
||||
The user option 'proced-auto-update-flag' can now be set to an
|
||||
additional value 'visible', which controls automatic updates of Proced
|
||||
buffers that are displayed in some window.
|
||||
|
||||
---
|
||||
*** nXML Mode now comes with schemas for Mono/.NET development.
|
||||
@ -2165,7 +2171,8 @@ This is a minor mode for editing regular expressions in the minibuffer,
|
||||
for example in 'query-replace-regexp'. It correctly highlights parens
|
||||
via 'show-paren-mode' and 'blink-matching-paren' in a user-friendly way,
|
||||
avoids reporting alleged paren mismatches and makes sexp navigation more
|
||||
intuitive.
|
||||
intuitive. It is enabled by default, 'minibuffer-regexp-prompts' can be
|
||||
used to tune when it takes effect.
|
||||
|
||||
---
|
||||
** The highly accessible Modus themes collection has eight items.
|
||||
@ -2291,7 +2298,7 @@ unibyte string.
|
||||
buffer-local value from the minibuffer.
|
||||
|
||||
+++
|
||||
** 'minibuffer-allow-text-properties' also affects completions.
|
||||
** 'minibuffer-allow-text-properties' now also affects completions.
|
||||
When it has a non-nil value, then completion functions like
|
||||
'completing-read' don't discard text properties from the returned
|
||||
completion candidate.
|
||||
@ -2321,7 +2328,7 @@ values.
|
||||
|
||||
---
|
||||
** User option 'tramp-completion-reread-directory-timeout' has been removed.
|
||||
This user option has been obsoleted in Emacs 27, use
|
||||
This user option was obsoleted in Emacs 27, use
|
||||
'remote-file-name-inhibit-cache' instead.
|
||||
|
||||
+++
|
||||
@ -2497,7 +2504,7 @@ where arguments after the first are keyword/value pairs, all optional:
|
||||
':key' specifies a function that produces the sorting key from an element,
|
||||
':lessp' specifies the ordering predicate, defaulting to 'value<',
|
||||
':reverse' is used to reverse the sorting order,
|
||||
':in-place is used for in-place sorting, as the default is now to
|
||||
':in-place' is used for in-place sorting, as the default is now to
|
||||
sort a copy of the input.
|
||||
|
||||
The new signature is less error-prone and reduces the need to write
|
||||
@ -2574,7 +2581,8 @@ analogous to 'w32-notification-notify'.
|
||||
** New Haiku specific variable 'haiku-pass-control-tab-to-system'.
|
||||
This sets whether Emacs should pass 'C-TAB' on to the system instead of
|
||||
handling it, fixing a problem where window switching would not activate
|
||||
if an Emacs frame had focus on the Haiku operating system.
|
||||
if an Emacs frame had focus on the Haiku operating system. Default
|
||||
value is t.
|
||||
|
||||
+++
|
||||
** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'.
|
||||
@ -2956,9 +2964,9 @@ default to use 'LANGUAGE'.
|
||||
|
||||
---
|
||||
** New optional argument to 'modify-dir-local-variable'.
|
||||
A 5th argument, optional, has been added to
|
||||
'modify-dir-local-variable'. It can be used to specify which
|
||||
dir-locals file to modify.
|
||||
An optional 5th argument FILE has been added to
|
||||
'modify-dir-local-variable'. It can be used to specify which file to
|
||||
modify instead of the default ".dir-locals.el".
|
||||
|
||||
** Connection local variables
|
||||
|
||||
@ -3012,13 +3020,13 @@ They pertained to the internal storage size which is now irrelevant.
|
||||
** 'treesit-install-language-grammar' can handle local directory instead of URL.
|
||||
It is now possible to pass a directory of a local repository as URL
|
||||
inside 'treesit-language-source-alist', so that calling
|
||||
'treesit-install-language-grammar' would avoid cloning the repository.
|
||||
'treesit-install-language-grammar' will avoid cloning the repository.
|
||||
It may be useful, for example, for the purposes of bisecting a
|
||||
treesitter grammar.
|
||||
|
||||
+++
|
||||
** New buffer-local variable 'tabulated-list-groups'.
|
||||
It controls display and separate sorting of groups of entries.
|
||||
It controls display and separate sorting of groups of entries. By
|
||||
default no grouping or sorting is done.
|
||||
|
||||
+++
|
||||
** New variable 'revert-buffer-restore-functions'.
|
||||
|
@ -286,7 +286,7 @@ when ~org-yank-dnd-method~ is =attach=.
|
||||
|
||||
*** Alignment of image previews can be customized
|
||||
|
||||
Previously, all the image previews where always left-aligned.
|
||||
Previously, all the image previews were always left-aligned.
|
||||
|
||||
Now, you can customize image previews to be left-aligned, centered, or right-aligned.
|
||||
|
||||
|
@ -1053,6 +1053,11 @@ This is like `setq', but is meant for user options instead of
|
||||
plain variables. This means that `setopt' will execute any
|
||||
`custom-set' form associated with VARIABLE.
|
||||
|
||||
Note that `setopt' will emit a warning if the type of a VALUE
|
||||
does not match the type of the corresponding VARIABLE as
|
||||
declared by `defcustom'. (VARIABLE will be assigned the value
|
||||
even if it doesn't match the type.)
|
||||
|
||||
\(fn [VARIABLE VALUE]...)"
|
||||
(declare (debug setq))
|
||||
(unless (zerop (mod (length pairs) 2))
|
||||
|
@ -38,7 +38,8 @@
|
||||
(defmacro easy-menu-define (symbol maps doc menu)
|
||||
"Define a pop-up menu and/or menu bar menu specified by MENU.
|
||||
If SYMBOL is non-nil, define SYMBOL as a function to pop up the
|
||||
submenu defined by MENU, with DOC as its doc string.
|
||||
submenu defined by MENU, with DOC as its doc string. Also define
|
||||
SYMBOL as a variable whose value is the menu.
|
||||
|
||||
MAPS, if non-nil, should be a keymap or a list of keymaps; add
|
||||
the submenu defined by MENU to the keymap or each of the keymaps,
|
||||
|
@ -4420,18 +4420,21 @@ the same set of elements."
|
||||
(unique (or (and (eq prefix t) (setq prefix fixed))
|
||||
(and (stringp prefix)
|
||||
(eq t (try-completion prefix comps))))))
|
||||
;; if the common prefix is unique, it also is a common
|
||||
;; suffix, so we should add it for `prefix' elements
|
||||
(unless (or (and (eq elem 'prefix) (not unique))
|
||||
(equal prefix ""))
|
||||
(push prefix res))
|
||||
;; If there's only one completion, `elem' is not useful
|
||||
;; any more: it can only match the empty string.
|
||||
;; FIXME: in some cases, it may be necessary to turn an
|
||||
;; `any' into a `star' because the surrounding context has
|
||||
;; changed such that string->pattern wouldn't add an `any'
|
||||
;; here any more.
|
||||
(unless unique
|
||||
(if unique
|
||||
;; If the common prefix is unique, it also is a common
|
||||
;; suffix, so we should add it for `prefix' elements.
|
||||
(push prefix res)
|
||||
;; `prefix' only wants to include the fixed part before the
|
||||
;; wildcard, not the result of growing that fixed part.
|
||||
(when (eq elem 'prefix)
|
||||
(setq prefix fixed))
|
||||
(push prefix res)
|
||||
(push elem res)
|
||||
;; Extract common suffix additionally to common prefix.
|
||||
;; Don't do it for `any' since it could lead to a merged
|
||||
|
@ -1325,7 +1325,8 @@ in your init files."
|
||||
;; Create an "for-each" parser, see `c-ts-mode--emacs-set-ranges'
|
||||
;; for more.
|
||||
(when c-ts-mode-emacs-sources-support
|
||||
(treesit-parser-create 'c nil nil 'for-each))
|
||||
(setq-local treesit-primary-parser
|
||||
(treesit-parser-create 'c nil nil 'for-each)))
|
||||
|
||||
(let ((primary-parser (treesit-parser-create 'c)))
|
||||
;; Comments.
|
||||
|
@ -701,7 +701,8 @@ Return nil if NODE is not a defun node or doesn't have a name."
|
||||
(require 'heex-ts-mode)
|
||||
(treesit-parser-create 'heex))
|
||||
|
||||
(treesit-parser-create 'elixir)
|
||||
(setq-local treesit-primary-parser
|
||||
(treesit-parser-create 'elixir))
|
||||
|
||||
(setq-local treesit-language-at-point-function
|
||||
'elixir-ts--treesit-language-at-point)
|
||||
|
@ -1636,7 +1636,7 @@ See `treesit-simple-indent-presets'.")
|
||||
|
||||
(goto-char bol)
|
||||
(setq this-line-has-prefix
|
||||
(and (looking-at-p adaptive-fill-regexp)
|
||||
(and (looking-at adaptive-fill-regexp)
|
||||
(not (string-match-p
|
||||
(rx bos (* whitespace) eos)
|
||||
(match-string 0)))))
|
||||
@ -2938,7 +2938,8 @@ when a major mode sets it.")
|
||||
|
||||
(defun treesit-outline-search (&optional bound move backward looking-at)
|
||||
"Search for the next outline heading in the syntax tree.
|
||||
See the descriptions of arguments in `outline-search-function'."
|
||||
For BOUND, MOVE, BACKWARD, LOOKING-AT, see the descriptions in
|
||||
`outline-search-function'."
|
||||
(if looking-at
|
||||
(when-let* ((node (or (treesit-thing-at (pos-eol) treesit-outline-predicate)
|
||||
(treesit-thing-at (pos-bol) treesit-outline-predicate)))
|
||||
@ -3047,6 +3048,10 @@ If `treesit-defun-name-function' is non-nil, set up
|
||||
|
||||
If `treesit-simple-imenu-settings' is non-nil, set up Imenu.
|
||||
|
||||
If either `treesit-outline-predicate' or `treesit-simple-imenu-settings'
|
||||
are non-nil, and Outline minor mode settings don't alreay exist, setup
|
||||
Outline minor mode.
|
||||
|
||||
If `sexp', `sentence' are defined in `treesit-thing-settings',
|
||||
enable tree-sitter navigation commands for them.
|
||||
|
||||
|
@ -1336,7 +1336,10 @@ nothing is shown in the echo area."
|
||||
(let ((new (widget-tabable-at)))
|
||||
(while (and (eq (widget-tabable-at) new) (not (bobp)))
|
||||
(backward-char)))
|
||||
(unless (bobp) (forward-char)))
|
||||
;; If the widget is at BOB, point is already at the widget's
|
||||
;; starting position; otherwise, advance point to put it at the
|
||||
;; start of the widget (cf. bug#69943 and bug#72995).
|
||||
(unless (and (widget-tabable-at) (bobp)) (forward-char)))
|
||||
(unless suppress-echo
|
||||
(widget-echo-help (point)))
|
||||
(run-hooks 'widget-move-hook))
|
||||
|
@ -1644,10 +1644,24 @@ frame's display, or the first available X display. */)
|
||||
|
||||
if (NILP (val) && FRAME_LIVE_P (f))
|
||||
{
|
||||
Lisp_Object frame;
|
||||
Lisp_Object frame, val;
|
||||
XSETFRAME (frame, f);
|
||||
return pgtk_get_foreign_selection (selection_symbol, target_type,
|
||||
time_stamp, frame);
|
||||
|
||||
val = pgtk_get_foreign_selection (selection_symbol, target_type,
|
||||
time_stamp, frame);
|
||||
|
||||
/* A window property holding just one item is indistinguishable
|
||||
from an array of one element, and is always decoded as the
|
||||
former, producing issues with programs that expect the TARGETS
|
||||
property always to return vectors, even when the toolkit
|
||||
reports just one data type. Though X sidesteps this ambiguity
|
||||
by defining TARGETS as returning at least two properties
|
||||
TARGETS and MULTIPLE, GTK knows no such scruples, and therefore
|
||||
symbol values (or nil) should be enclosed in vectors when
|
||||
TARGETS is being requested. (bug#72254) */
|
||||
if (EQ (target_type, QTARGETS) && (NILP (val) || SYMBOLP (val)))
|
||||
val = make_vector (NILP (val) ? 0 : 1, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
if (CONSP (val) && SYMBOLP (XCAR (val)))
|
||||
|
217
src/treesit.c
217
src/treesit.c
@ -504,7 +504,7 @@ treesit_debug_print_parser_list (char *msg, Lisp_Object parser)
|
||||
SSDATA (SYMBOL_NAME (Vthis_command)),
|
||||
SSDATA (SYMBOL_NAME (XTS_PARSER (parser)->language_symbol)),
|
||||
buf_name, BUF_BEG (buf),
|
||||
BUF_BEGV (buf), BUF_Z (buf), BUF_ZV (buf));
|
||||
BUF_BEGV (buf), BUF_ZV (buf), BUF_Z (buf));
|
||||
Lisp_Object tail = BVAR (buf, ts_parser_list);
|
||||
|
||||
FOR_EACH_TAIL (tail)
|
||||
@ -968,6 +968,9 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte,
|
||||
}
|
||||
}
|
||||
|
||||
static TSRange *treesit_make_ts_ranges (Lisp_Object, Lisp_Object,
|
||||
uint32_t *);
|
||||
|
||||
/* Comment (ref:visible-beg-null) The purpose of visible_beg/end is to
|
||||
keep track of "which part of the buffer does the tree-sitter tree
|
||||
see", in order to update the tree correctly. Visible_beg/end have
|
||||
@ -1096,48 +1099,85 @@ treesit_sync_visible_region (Lisp_Object parser)
|
||||
XTS_PARSER (parser)->visible_end = visible_end;
|
||||
|
||||
/* Fix ranges so that the ranges stays with in visible_end. Here we
|
||||
try to do minimal work so that the ranges is minimally correct such
|
||||
that there's no OOB error. Usually treesit-update-ranges should
|
||||
update the parser with actually correct ranges. */
|
||||
if (NILP (XTS_PARSER (parser)->last_set_ranges)) return;
|
||||
uint32_t len;
|
||||
const TSRange *ranges
|
||||
= ts_parser_included_ranges (XTS_PARSER (parser)->parser, &len);
|
||||
/* We might need to discard some ranges that exceeds visible_end, in
|
||||
that case, new_len is the length of the new ranges array (which
|
||||
will be shorter than len). */
|
||||
uint32_t new_len = 0;
|
||||
uint32_t new_end = 0;
|
||||
for (int idx = 0; idx < len; idx++)
|
||||
{
|
||||
TSRange range = ranges[idx];
|
||||
/* If this range starts after visible_end, we don't include this
|
||||
range and the ranges after it in the new ranges. */
|
||||
if (range.start_byte + visible_beg >= visible_end)
|
||||
try to do minimal work so that the ranges is minimally correct and
|
||||
there's no OOB error. Usually treesit-update-ranges should update
|
||||
the parser with semantically correct ranges.
|
||||
|
||||
We start with the charpos ranges, because for bytepos ranges, after
|
||||
user edits, the ranges start/end might end up inside a multibyte
|
||||
char! See (ref:bytepos-range-pitfall) below. */
|
||||
Lisp_Object lisp_ranges = XTS_PARSER (parser)->last_set_ranges;
|
||||
if (NILP (lisp_ranges)) return;
|
||||
|
||||
Lisp_Object new_ranges_head = lisp_ranges;
|
||||
|
||||
FOR_EACH_TAIL_SAFE (lisp_ranges)
|
||||
{
|
||||
Lisp_Object range = XCAR (lisp_ranges);
|
||||
ptrdiff_t beg = XFIXNUM (XCAR (range));
|
||||
ptrdiff_t end = XFIXNUM (XCDR (range));
|
||||
|
||||
if (end <= visible_beg)
|
||||
/* Even the end is before visible_beg, discard this range. */
|
||||
new_ranges_head = XCDR (new_ranges_head);
|
||||
else if (beg >= visible_end)
|
||||
{
|
||||
/* Even the beg is after visible_end, dicard this range and all
|
||||
the ranges after it. */
|
||||
XSETCDR (range, Qnil);
|
||||
break;
|
||||
/* If this range's end is after visible_end, we don't include any
|
||||
ranges after it, and changes the end of this range to
|
||||
visible_end. */
|
||||
if (range.end_byte + visible_beg > visible_end)
|
||||
{
|
||||
new_end = visible_end - visible_beg;
|
||||
new_len++;
|
||||
break;
|
||||
}
|
||||
new_len++;
|
||||
}
|
||||
if (new_len != len || new_end != 0)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* At this point, the range overlaps with the visible portion of
|
||||
the buffer in some way (in front / in back / completely
|
||||
encased / completely encases). */
|
||||
if (beg < visible_beg)
|
||||
XSETCAR (range, make_fixnum (visible_beg));
|
||||
if (end > visible_end)
|
||||
XSETCDR (range, make_fixnum (visible_end));
|
||||
}
|
||||
}
|
||||
|
||||
XTS_PARSER (parser)->last_set_ranges = new_ranges_head;
|
||||
|
||||
if (NILP (new_ranges_head))
|
||||
{
|
||||
TSRange *new_ranges = xmalloc (sizeof (TSRange) * new_len);
|
||||
memcpy (new_ranges, ranges, sizeof (TSRange) * new_len);
|
||||
new_ranges[new_len - 1].end_byte = new_end;
|
||||
/* TODO: What should we do if this fails? */
|
||||
ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
|
||||
new_ranges, new_len);
|
||||
xfree (new_ranges);
|
||||
bool success;
|
||||
success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
|
||||
NULL, 0);
|
||||
eassert (success);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t len = 0;
|
||||
TSRange *ts_ranges = treesit_make_ts_ranges (new_ranges_head, parser,
|
||||
&len);
|
||||
bool success;
|
||||
success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
|
||||
ts_ranges, len);
|
||||
xfree (ts_ranges);
|
||||
eassert (success);
|
||||
}
|
||||
}
|
||||
|
||||
/* (ref:bytepos-range-pitfall) Suppose we have the following buffer
|
||||
content ([ ] is a unibyte char, [ ] is a multibyte char):
|
||||
|
||||
[a][b][c][d][e][ f ]
|
||||
|
||||
and the following ranges (denoted by braces):
|
||||
|
||||
[a][b][c][d][e][ f ]
|
||||
{ }{ }
|
||||
|
||||
So far so good, now user deletes a unibyte char at the beginning:
|
||||
|
||||
[b][c][d][e][ f ]
|
||||
{ }{ }
|
||||
|
||||
Oops, now our range cuts into the multibyte char, bad! */
|
||||
|
||||
static void
|
||||
treesit_check_buffer_size (struct buffer *buffer)
|
||||
{
|
||||
@ -1274,13 +1314,16 @@ treesit_read_buffer (void *parser, uint32_t byte_index,
|
||||
beg = NULL;
|
||||
len = 0;
|
||||
}
|
||||
/* Normal case, read until the gap or visible end. */
|
||||
/* Normal case, read a character. We can't give tree-sitter the
|
||||
whole buffer range because we move the gap around, realloc the
|
||||
buffer, etc; and there's no way to invalidate the previously
|
||||
given range in tree-sitter. Move over, benchmark shows there's
|
||||
very little difference between passing a whole chunk vs passing a
|
||||
single char at once. The only cost is funcall I guess. */
|
||||
else
|
||||
{
|
||||
beg = (char *) BUF_BYTE_ADDRESS (buffer, byte_pos);
|
||||
ptrdiff_t gap_bytepos = BUF_GPT_BYTE (buffer);
|
||||
len = (byte_pos < gap_bytepos)
|
||||
? gap_bytepos - byte_pos : visible_end - byte_pos;
|
||||
len = BYTES_BY_CHAR_HEAD ((int) *beg);
|
||||
}
|
||||
/* We never let tree-sitter to parse buffers that large so this
|
||||
assertion should never hit. */
|
||||
@ -1831,6 +1874,48 @@ treesit_make_ranges (const TSRange *ranges, uint32_t len,
|
||||
return Fnreverse (list);
|
||||
}
|
||||
|
||||
/* Convert lisp ranges to tree-sitter ranges. Set LEN to the length of
|
||||
the ranges. RANGES must be a valid ranges list, (cons of numbers, no
|
||||
overlap, etc). PARSER must be a parser. This function doesn't check
|
||||
for types. Caller must free the returned ranges. */
|
||||
static TSRange *
|
||||
treesit_make_ts_ranges (Lisp_Object ranges, Lisp_Object parser, uint32_t *len)
|
||||
{
|
||||
ptrdiff_t ranges_len = list_length (ranges);
|
||||
if (ranges_len > UINT32_MAX)
|
||||
xsignal (Qargs_out_of_range, list2 (ranges, Flength (ranges)));
|
||||
|
||||
*len = (uint32_t) ranges_len;
|
||||
TSRange *treesit_ranges = xmalloc (sizeof (TSRange) * ranges_len);
|
||||
|
||||
struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
|
||||
|
||||
for (int idx = 0; idx < ranges_len; idx++, ranges = XCDR (ranges))
|
||||
{
|
||||
Lisp_Object range = XCAR (ranges);
|
||||
ptrdiff_t beg_byte = buf_charpos_to_bytepos (buffer,
|
||||
XFIXNUM (XCAR (range)));
|
||||
ptrdiff_t end_byte = buf_charpos_to_bytepos (buffer,
|
||||
XFIXNUM (XCDR (range)));
|
||||
|
||||
/* Shouldn't violate assertion since we just checked for
|
||||
buffer size at the beginning of this function. */
|
||||
eassert (beg_byte - BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
|
||||
eassert (end_byte - BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
|
||||
|
||||
/* We don't care about points, put in dummy values. */
|
||||
TSRange rg =
|
||||
{
|
||||
{0, 0}, {0, 0},
|
||||
(uint32_t) beg_byte - XTS_PARSER (parser)->visible_beg,
|
||||
(uint32_t) end_byte - XTS_PARSER (parser)->visible_beg
|
||||
};
|
||||
treesit_ranges[idx] = rg;
|
||||
}
|
||||
|
||||
return treesit_ranges;
|
||||
}
|
||||
|
||||
DEFUN ("treesit-parser-set-included-ranges",
|
||||
Ftreesit_parser_set_included_ranges,
|
||||
Streesit_parser_set_included_ranges,
|
||||
@ -1870,33 +1955,8 @@ buffer. */)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set ranges for PARSER. */
|
||||
if (list_length (ranges) > UINT32_MAX)
|
||||
xsignal (Qargs_out_of_range, list2 (ranges, Flength (ranges)));
|
||||
uint32_t len = (uint32_t) list_length (ranges);
|
||||
TSRange *treesit_ranges = xmalloc (sizeof (TSRange) * len);
|
||||
struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
|
||||
|
||||
/* We can use XFIXNUM, XCAR, XCDR freely because we have checked
|
||||
the input by treesit_check_range_argument. */
|
||||
for (int idx = 0; !NILP (ranges); idx++, ranges = XCDR (ranges))
|
||||
{
|
||||
Lisp_Object range = XCAR (ranges);
|
||||
ptrdiff_t beg_byte = buf_charpos_to_bytepos (buffer,
|
||||
XFIXNUM (XCAR (range)));
|
||||
ptrdiff_t end_byte = buf_charpos_to_bytepos (buffer,
|
||||
XFIXNUM (XCDR (range)));
|
||||
/* Shouldn't violate assertion since we just checked for
|
||||
buffer size at the beginning of this function. */
|
||||
eassert (beg_byte - BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
|
||||
eassert (end_byte - BUF_BEGV_BYTE (buffer) <= UINT32_MAX);
|
||||
/* We don't care about start and end points, put in dummy
|
||||
values. */
|
||||
TSRange rg = {{0, 0}, {0, 0},
|
||||
(uint32_t) beg_byte - BUF_BEGV_BYTE (buffer),
|
||||
(uint32_t) end_byte - BUF_BEGV_BYTE (buffer)};
|
||||
treesit_ranges[idx] = rg;
|
||||
}
|
||||
uint32_t len = 0;
|
||||
TSRange *treesit_ranges = treesit_make_ts_ranges (ranges, parser, &len);
|
||||
success = ts_parser_set_included_ranges (XTS_PARSER (parser)->parser,
|
||||
treesit_ranges, len);
|
||||
xfree (treesit_ranges);
|
||||
@ -1923,26 +1983,9 @@ See also `treesit-parser-set-included-ranges'. */)
|
||||
treesit_check_parser (parser);
|
||||
treesit_initialize ();
|
||||
|
||||
/* Our return value depends on the buffer state (BUF_BEGV_BYTE,
|
||||
etc), so we need to sync up. */
|
||||
treesit_check_buffer_size (XBUFFER (XTS_PARSER (parser)->buffer));
|
||||
treesit_sync_visible_region (parser);
|
||||
/* When the parser doesn't have a range set and we call
|
||||
ts_parser_included_ranges on it, it doesn't return an empty list,
|
||||
but rather return DEFAULT_RANGE. (A single range where start_byte
|
||||
= 0, end_byte = UINT32_MAX). So we need to track whether the
|
||||
parser is ranged ourselves. */
|
||||
if (NILP (XTS_PARSER (parser)->last_set_ranges))
|
||||
return Qnil;
|
||||
|
||||
uint32_t len;
|
||||
const TSRange *ranges
|
||||
= ts_parser_included_ranges (XTS_PARSER (parser)->parser, &len);
|
||||
|
||||
struct buffer *buffer = XBUFFER (XTS_PARSER (parser)->buffer);
|
||||
|
||||
|
||||
return treesit_make_ranges (ranges, len, parser, buffer);
|
||||
return XTS_PARSER (parser)->last_set_ranges;
|
||||
}
|
||||
|
||||
DEFUN ("treesit-parser-notifiers", Ftreesit_parser_notifiers,
|
||||
|
@ -45,12 +45,23 @@ struct Lisp_TS_Parser
|
||||
same tag. A tag is primarily used to differentiate between
|
||||
parsers for the same language. */
|
||||
Lisp_Object tag;
|
||||
/* The Lisp ranges last set. This is use to compare to the new ranges
|
||||
the users wants to set, and avoid reparse if the new ranges is the
|
||||
same as the last set one. This might go out of sync with the
|
||||
ranges we return from Ftreesit_parser_included_ranges, if we did a
|
||||
ranges fix in treesit_sync_visible_region, but I don't think
|
||||
that'll cause any harm. */
|
||||
/* The Lisp ranges last set. One purpose for it is to compare to the
|
||||
new ranges the users wants to set, and avoid reparse if the new
|
||||
ranges is the same as the current one. Another purpose is to store
|
||||
the ranges in charpos (ts api returns ranges in bytepos). We need
|
||||
to use charpos so we don't end up having a range cut into a
|
||||
multibyte character. (See (ref:bytepos-range-pitfall) in treesit.c
|
||||
for more detail.)
|
||||
|
||||
treesit-parser-set-included-ranges sets this field;
|
||||
treesit-parser-included-ranges directly returns this field, and
|
||||
before each reparse, treesit_sync_visible_region uses this to
|
||||
calculate a range for the parser that fits in the visible region.
|
||||
|
||||
Trivia: when the parser doesn't have a range set and we call
|
||||
ts_parser_included_ranges on it, it doesn't return an empty list,
|
||||
but rather return DEFAULT_RANGE. (A single range where start_byte
|
||||
= 0, end_byte = UINT32_MAX). */
|
||||
Lisp_Object last_set_ranges;
|
||||
/* The buffer associated with this parser. */
|
||||
Lisp_Object buffer;
|
||||
|
@ -306,13 +306,20 @@
|
||||
6)))
|
||||
|
||||
(ert-deftest completion-substring-test-5 ()
|
||||
;; merge-completions needs to work correctly when
|
||||
;; Normally a `prefix' wildcard ignores the common prefix to its
|
||||
;; left, since it only grows the common suffix; but if that common
|
||||
;; prefix is also a common suffix, it should be included.
|
||||
(should (equal
|
||||
(completion-pcm--merge-completions '("ab" "sab") '(prefix "b"))
|
||||
'("b" "a" prefix)))
|
||||
(completion-pcm--merge-try '(prefix "b") '("ab" "sab") "" "")
|
||||
'("ab" . 2)))
|
||||
(should (equal
|
||||
(completion-pcm--merge-completions '("ab" "ab") '(prefix "b"))
|
||||
'("b" "a")))
|
||||
(completion-pcm--merge-try '(prefix "b") '("ab" "ab") "" "")
|
||||
'("ab" . 2)))
|
||||
;; When there's a fixed string before `prefix', that fixed string
|
||||
;; should always be included.
|
||||
(should (equal
|
||||
(completion-pcm--merge-try '("a" prefix "b") '("axb" "ayb") "" "")
|
||||
'("ab" . 2)))
|
||||
;; substring completion should successfully complete the entire string
|
||||
(should (equal
|
||||
(completion-substring-try-completion "b" '("ab" "ab") nil 0)
|
||||
|
@ -129,6 +129,7 @@ uniquify-trailing-separator-p is ignored"
|
||||
(require 'project)
|
||||
(ert-deftest uniquify-project-transform ()
|
||||
"`project-uniquify-dirname-transform' works"
|
||||
(skip-unless (project-current nil source-directory))
|
||||
(let ((uniquify-dirname-transform #'project-uniquify-dirname-transform)
|
||||
(project-vc-name "foo1/bar")
|
||||
bufs)
|
||||
|
@ -344,6 +344,23 @@ return nil, even with a non-nil bubblep argument."
|
||||
(should (string= "Third" (widget-value (widget-at))))
|
||||
(widget-forward 1))) ; Should not signal beginning-of-buffer error.
|
||||
|
||||
(ert-deftest widget-test-widget-move-bug72995 ()
|
||||
"Test moving to a widget that starts at buffer position 2."
|
||||
(with-temp-buffer
|
||||
;; The first tabable widget begins at position 2 (bug#72995).
|
||||
(widget-insert " ")
|
||||
(dolist (el '("First" "Second" "Third"))
|
||||
(widget-create 'push-button el))
|
||||
(widget-insert "\n")
|
||||
(use-local-map widget-keymap)
|
||||
(widget-setup)
|
||||
;; Make sure there is no tabable widget at BOB.
|
||||
(goto-char (point-min))
|
||||
(should-not (widget-tabable-at))
|
||||
;; Check that we can move to the first widget after BOB.
|
||||
(widget-forward 1)
|
||||
(should (widget-tabable-at))))
|
||||
|
||||
(ert-deftest widget-test-color-match ()
|
||||
"Test that the :match function for the color widget works."
|
||||
(let ((widget (widget-convert 'color)))
|
||||
|
@ -686,6 +686,33 @@ visible_end.)"
|
||||
(should (equal '((16 . 28)) (treesit-query-range
|
||||
'javascript query nil nil '(1 . -1)))))))
|
||||
|
||||
(ert-deftest treesit-range-fixup-after-edit ()
|
||||
"Tests if Emacs can fix OOB ranges after deleting text or narrowing."
|
||||
(skip-unless (treesit-language-available-p 'json))
|
||||
(with-temp-buffer
|
||||
(let ((parser (treesit-parser-create 'json)))
|
||||
(insert "11111111111111111111")
|
||||
(treesit-parser-set-included-ranges parser '((1 . 20)))
|
||||
(treesit-parser-root-node parser)
|
||||
(should (equal (treesit-parser-included-ranges parser)
|
||||
'((1 . 20))))
|
||||
|
||||
(narrow-to-region 5 15)
|
||||
(should (equal (treesit-parser-included-ranges parser)
|
||||
'((5 . 15))))
|
||||
|
||||
(widen)
|
||||
;; Trickier ranges
|
||||
;; 11111111111111111111
|
||||
;; [ ] [ ]
|
||||
;; { narrow }
|
||||
(treesit-parser-set-included-ranges parser '((1 . 7) (10 . 15)))
|
||||
(should (equal (treesit-parser-included-ranges parser)
|
||||
'((1 . 7) (10 . 15))))
|
||||
(narrow-to-region 5 13)
|
||||
(should (equal (treesit-parser-included-ranges parser)
|
||||
'((5 . 7) (10 . 13)))))))
|
||||
|
||||
;;; Multiple language
|
||||
|
||||
(ert-deftest treesit-multi-lang ()
|
||||
|
Loading…
Reference in New Issue
Block a user