mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-16 17:24:23 +00:00
Merge from origin/emacs-29
ab1f245f1aShow tree-sitter query source when signaling query error0b58ea0e60; * lisp/treesit.el (treesit--install-language-grammar-1)...724da28763Add version tags and mention the new options in NEWS8675f4136cAdd new options for Ruby code indentation4922de626f; Fix doc strings of 'treesit-install-language-grammar'69b2aaaade; Fix recently modified docs of 'set-face-attribute' (bug...0248fc9e1aAdd treesit-install-language-grammar0237c5927eAdd treesit-language-abi-version312f82d36fChange "language definition" to "language grammar" in man...fba35657da; * lisp/progmodes/c-ts-mode.el (c-ts-mode--fill-paragrap...dec1b37a32; * doc/lispref/parsing.texi (Accessing Node Information)...39265abf0c* test/lisp/net/tramp-tests.el (tramp-test32-shell-comman...ebf65c7e7e* lisp/eshell/em-tramp.el (tramp): Require also at runtim... # Conflicts: # etc/NEWS
This commit is contained in:
commit
2ec4e187c9
18 changed files with 503 additions and 85 deletions
|
|
@ -3059,16 +3059,23 @@ values specified by @code{defface}. If @var{frame} is @code{nil},
|
|||
this function sets the attributes for all existing frames, as well as
|
||||
for newly created frames.
|
||||
|
||||
To @emph{unset} the value of an attribute, that is, to indicate that
|
||||
the face doesn't by itself specify a value for the attribute, the
|
||||
special value @code{unspecified} (@emph{not} @code{nil}!@:) must be
|
||||
used.
|
||||
To @emph{reset} the value of an attribute, that is, to indicate that
|
||||
the face doesn't by itself specify a value for the attribute, use the
|
||||
special value @code{unspecified} (@emph{not} @code{nil}!@:) for the
|
||||
attribute, and set the @var{frame} argument to @code{t}, in addition
|
||||
to the call with @var{frame} set to @code{nil}. This is because the
|
||||
default attributes for newly created frames are merged with the face's
|
||||
spec in @code{defface} when a new frame is created, and so having
|
||||
@code{unspecified} in the default attributes for new frames will be
|
||||
unable to override @code{defface}; the special call to this function
|
||||
as described above will arrange for @code{defface} to be overridden.
|
||||
|
||||
Note that the attribute-value pairs are evaluated in the order they
|
||||
are specified, except the @code{:family} and @code{:foundry}
|
||||
attributes, which are evaluated first. This means both that only the
|
||||
last value of a given attribute will be used, and that in some cases a
|
||||
different order will give different results. For example, when
|
||||
are specified, with the exception of the @code{:family} and
|
||||
@code{:foundry} attributes, which are evaluated first. This means
|
||||
that if a certain attribute is specified more than once, only the last
|
||||
value will be used. It also means that in some cases a different
|
||||
order of attributes will produce different results. For example, when
|
||||
@code{:weight} is placed before @code{:font}, the weight value is
|
||||
applied to the current font of the face, and might be rounded to the
|
||||
closest available weight of that font, whereas when @code{:font} is
|
||||
|
|
|
|||
|
|
@ -1364,7 +1364,7 @@ Syntax Tables
|
|||
|
||||
Parsing Program Source
|
||||
|
||||
* Language Definitions:: Loading tree-sitter language definitions.
|
||||
* Language Grammar:: Loading tree-sitter language grammar.
|
||||
* Using Parser:: Introduction to parsers.
|
||||
* Retrieving Nodes:: Retrieving nodes from a syntax tree.
|
||||
* Accessing Node Information:: Accessing node information.
|
||||
|
|
|
|||
|
|
@ -5082,7 +5082,7 @@ shown in red color. @c Are colors customizable? faces?
|
|||
@end defun
|
||||
|
||||
It is also helpful to use @code{treesit-inspect-mode} (@pxref{Language
|
||||
Definitions}) when writing indentation rules.
|
||||
Grammar}) when writing indentation rules.
|
||||
|
||||
@node Desktop Save Mode
|
||||
@section Desktop Save Mode
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ available for the current Emacs session.
|
|||
|
||||
To be able to parse the program source using the tree-sitter library
|
||||
and access the syntax tree of the program, a Lisp program needs to
|
||||
load a language definition library, and create a parser for that
|
||||
load a language grammar library, and create a parser for that
|
||||
language and the current buffer. After that, the Lisp program can
|
||||
query the parser about specific nodes of the syntax tree. Then, it
|
||||
can access various kinds of information about each node, and search
|
||||
|
|
@ -39,7 +39,7 @@ explains how to do all this, and also how a Lisp program can work with
|
|||
source files that mix multiple programming languages.
|
||||
|
||||
@menu
|
||||
* Language Definitions:: Loading tree-sitter language definitions.
|
||||
* Language Grammar:: Loading tree-sitter language grammar.
|
||||
* Using Parser:: Introduction to parsers.
|
||||
* Retrieving Nodes:: Retrieving nodes from a syntax tree.
|
||||
* Accessing Node Information:: Accessing node information.
|
||||
|
|
@ -49,27 +49,27 @@ source files that mix multiple programming languages.
|
|||
* Tree-sitter C API:: Compare the C API and the ELisp API.
|
||||
@end menu
|
||||
|
||||
@node Language Definitions
|
||||
@section Tree-sitter Language Definitions
|
||||
@cindex language definitions, for tree-sitter
|
||||
@node Language Grammar
|
||||
@section Tree-sitter Language Grammar
|
||||
@cindex language grammar, for tree-sitter
|
||||
|
||||
@heading Loading a language definition
|
||||
@cindex loading language definition for tree-sitter
|
||||
@heading Loading a language grammar
|
||||
@cindex loading language grammar for tree-sitter
|
||||
|
||||
@cindex language argument, for tree-sitter
|
||||
Tree-sitter relies on language definitions to parse text in that
|
||||
language. In Emacs, a language definition is represented by a symbol.
|
||||
For example, the C language definition is represented as the symbol
|
||||
Tree-sitter relies on language grammar to parse text in that
|
||||
language. In Emacs, a language grammar is represented by a symbol.
|
||||
For example, the C language grammar is represented as the symbol
|
||||
@code{c}, and @code{c} can be passed to tree-sitter functions as the
|
||||
@var{language} argument.
|
||||
|
||||
@vindex treesit-extra-load-path
|
||||
@vindex treesit-load-language-error
|
||||
@vindex treesit-load-suffixes
|
||||
Tree-sitter language definitions are distributed as dynamic libraries.
|
||||
In order to use a language definition in Emacs, you need to make sure
|
||||
Tree-sitter language grammar are distributed as dynamic libraries.
|
||||
In order to use a language grammar in Emacs, you need to make sure
|
||||
that the dynamic library is installed on the system. Emacs looks for
|
||||
language definitions in several places, in the following order:
|
||||
language grammar in several places, in the following order:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
|
|
@ -91,12 +91,12 @@ that signal could be one of the following:
|
|||
|
||||
@table @code
|
||||
@item (not-found @var{error-msg} @dots{})
|
||||
This means that Emacs could not find the language definition library.
|
||||
This means that Emacs could not find the language grammar library.
|
||||
@item (symbol-error @var{error-msg})
|
||||
This means that Emacs could not find in the library the expected function
|
||||
that every language definition library should export.
|
||||
that every language grammar library should export.
|
||||
@item (version-mismatch @var{error-msg})
|
||||
This means that the version of language definition library is incompatible
|
||||
This means that the version of language grammar library is incompatible
|
||||
with that of the tree-sitter library.
|
||||
@end table
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ In all of these cases, @var{error-msg} might provide additional
|
|||
details about the failure.
|
||||
|
||||
@defun treesit-language-available-p language &optional detail
|
||||
This function returns non-@code{nil} if the language definitions for
|
||||
This function returns non-@code{nil} if the language grammar for
|
||||
@var{language} exist and can be loaded.
|
||||
|
||||
If @var{detail} is non-@code{nil}, return @code{(t . nil)} when
|
||||
|
|
@ -119,7 +119,7 @@ By convention, the file name of the dynamic library for @var{language} is
|
|||
@file{libtree-sitter-@var{language}.@var{ext}}, where @var{ext} is the
|
||||
system-specific extension for dynamic libraries. Also by convention,
|
||||
the function provided by that library is named
|
||||
@code{tree_sitter_@var{language}}. If a language definition library
|
||||
@code{tree_sitter_@var{language}}. If a language grammar library
|
||||
doesn't follow this convention, you should add an entry
|
||||
|
||||
@example
|
||||
|
|
@ -140,19 +140,25 @@ to the list in the variable @code{treesit-load-name-override-list}, where
|
|||
for a language that considers itself too ``cool'' to abide by
|
||||
conventions.
|
||||
|
||||
@cindex language-definition version, compatibility
|
||||
@defun treesit-language-version &optional min-compatible
|
||||
This function returns the version of the language-definition
|
||||
@cindex language grammar version, compatibility
|
||||
@defun treesit-library-abi-version &optional min-compatible
|
||||
This function returns the version of the language grammar
|
||||
Application Binary Interface (@acronym{ABI}) supported by the
|
||||
tree-sitter library. By default, it returns the latest ABI version
|
||||
supported by the library, but if @var{min-compatible} is
|
||||
non-@code{nil}, it returns the oldest ABI version which the library
|
||||
still can support. Language definition libraries must be built for
|
||||
still can support. language grammar libraries must be built for
|
||||
ABI versions between the oldest and the latest versions supported by
|
||||
the tree-sitter library, otherwise the library will be unable to load
|
||||
them.
|
||||
@end defun
|
||||
|
||||
@defun treesit-language-abi-version language
|
||||
This function returns the language grammar @acronym{ABI} version of
|
||||
language grammar for @var{language} loaded by Emacs. If
|
||||
@var{language} is unavailable, this function returns @code{nil}.
|
||||
@end defun
|
||||
|
||||
@heading Concrete syntax tree
|
||||
@cindex syntax tree, concrete
|
||||
|
||||
|
|
@ -210,7 +216,7 @@ punctuation characters like bracket @samp{]}, and keywords like
|
|||
@cindex field name, tree-sitter
|
||||
@cindex tree-sitter node field name
|
||||
@anchor{tree-sitter node field name}
|
||||
To make the syntax tree easier to analyze, many language definitions
|
||||
To make the syntax tree easier to analyze, many language grammar
|
||||
assign @dfn{field names} to child nodes. For example, a
|
||||
@code{function_definition} node could have a @code{declarator} and a
|
||||
@code{body}:
|
||||
|
|
@ -266,13 +272,13 @@ parser in @code{(treesit-parser-list)} (@pxref{Using Parser}).
|
|||
@heading Reading the grammar definition
|
||||
@cindex reading grammar definition, tree-sitter
|
||||
|
||||
Authors of language definitions define the @dfn{grammar} of a
|
||||
Authors of language grammar define the @dfn{grammar} of a
|
||||
programming language, which determines how a parser constructs a
|
||||
concrete syntax tree out of the program text. In order to use the
|
||||
syntax tree effectively, you need to consult the @dfn{grammar file}.
|
||||
|
||||
The grammar file is usually @file{grammar.js} in a language
|
||||
definition's project repository. The link to a language definition's
|
||||
grammar's project repository. The link to a language grammar's
|
||||
home page can be found on
|
||||
@uref{https://tree-sitter.github.io/tree-sitter, tree-sitter's
|
||||
homepage}.
|
||||
|
|
@ -350,7 +356,7 @@ makes any node matched by @code{preprocessor_call_exp} appear as
|
|||
@end table
|
||||
|
||||
Below are grammar functions of lesser importance for reading a
|
||||
language definition.
|
||||
language grammar.
|
||||
|
||||
@table @code
|
||||
@item token(@var{rule})
|
||||
|
|
@ -397,7 +403,7 @@ when deciding whether to enable tree-sitter features.
|
|||
@cindex tree-sitter parser, creating
|
||||
@defun treesit-parser-create language &optional buffer no-reuse
|
||||
Create a parser for the specified @var{buffer} and @var{language}
|
||||
(@pxref{Language Definitions}). If @var{buffer} is omitted or
|
||||
(@pxref{Language Grammar}). If @var{buffer} is omitted or
|
||||
@code{nil}, it stands for the current buffer.
|
||||
|
||||
By default, this function reuses a parser if one already exists for
|
||||
|
|
@ -685,7 +691,7 @@ This function finds the previous sibling of @var{node}. If
|
|||
@cindex nodes, by field name
|
||||
@cindex syntax tree nodes, by field name
|
||||
|
||||
To make the syntax tree easier to analyze, many language definitions
|
||||
To make the syntax tree easier to analyze, many language grammar
|
||||
assign @dfn{field names} to child nodes (@pxref{tree-sitter node field
|
||||
name, field name}). For example, a @code{function_definition} node
|
||||
could have a @code{declarator} node and a @code{body} node.
|
||||
|
|
@ -929,7 +935,7 @@ tree.
|
|||
|
||||
In general, nodes in a concrete syntax tree fall into two categories:
|
||||
@dfn{named nodes} and @dfn{anonymous nodes}. Whether a node is named
|
||||
or anonymous is determined by the language definition
|
||||
or anonymous is determined by the language grammar
|
||||
(@pxref{tree-sitter named node, named node}).
|
||||
|
||||
@cindex tree-sitter missing node
|
||||
|
|
@ -968,7 +974,7 @@ Named nodes have ``types'' (@pxref{tree-sitter node type, node type}).
|
|||
For example, a named node can be a @code{string_literal} node, where
|
||||
@code{string_literal} is its type. The type of an anonymous node is
|
||||
just the text that the node represents; e.g., the type of a @samp{,}
|
||||
node 480is just @samp{,}.
|
||||
node is just @samp{,}.
|
||||
|
||||
This function returns @var{node}'s type as a string.
|
||||
@end defun
|
||||
|
|
@ -1704,8 +1710,8 @@ whether tree-sitter can be activated in this mode.
|
|||
This function checks for conditions for activating tree-sitter. It
|
||||
checks whether Emacs was built with tree-sitter, whether the buffer's
|
||||
size is not too large for tree-sitter to handle it, and whether the
|
||||
language definition for @var{language} is available on the system
|
||||
(@pxref{Language Definitions}).
|
||||
language grammar for @var{language} is available on the system
|
||||
(@pxref{Language Grammar}).
|
||||
|
||||
This function emits a warning if tree-sitter cannot be activated. If
|
||||
@var{quiet} is @code{message}, the warning is turned into a message;
|
||||
|
|
@ -1826,7 +1832,7 @@ Using (row, column) coordinates as position.
|
|||
Updating a node with changes. (In Emacs, retrieve a new node instead
|
||||
of updating the existing one.)
|
||||
@item
|
||||
Querying statics of a language definition.
|
||||
Querying statics of a language grammar.
|
||||
@end itemize
|
||||
|
||||
In addition, Emacs makes some changes to the C API to make the API more
|
||||
|
|
|
|||
|
|
@ -2832,7 +2832,11 @@ project-dedicated or global) is specified by the new
|
|||
*** Support for endless methods.
|
||||
|
||||
---
|
||||
*** New user option 'ruby-method-params-indent'.
|
||||
*** New user options that determine indentation logic.
|
||||
'ruby-method-params-indent', 'ruby-block-indent',
|
||||
'ruby-after-operator-indent', 'ruby-method-call-indent',
|
||||
'ruby-parenless-call-arguments-indent'. See the docstrings for
|
||||
explanations and examples.
|
||||
|
||||
** Eshell
|
||||
|
||||
|
|
|
|||
|
|
@ -30,8 +30,9 @@
|
|||
|
||||
(eval-when-compile
|
||||
(require 'esh-mode)
|
||||
(require 'eshell)
|
||||
(require 'tramp))
|
||||
(require 'eshell))
|
||||
|
||||
(require 'tramp)
|
||||
|
||||
;; There are no items in this custom group, but eshell modules (ab)use
|
||||
;; custom groups.
|
||||
|
|
|
|||
|
|
@ -691,8 +691,8 @@ what the FACE's face spec says, call this function with FRAME set to
|
|||
t and the ATTRIBUTE's value set to `unspecified'.
|
||||
|
||||
Note that the ATTRIBUTE VALUE pairs are evaluated in the order
|
||||
they are specified, except the `:family' and `:foundry'
|
||||
attributes which are evaluated first.
|
||||
they are specified, except that the `:family' and `:foundry'
|
||||
attributes are evaluated first.
|
||||
|
||||
The following attributes are recognized:
|
||||
|
||||
|
|
|
|||
|
|
@ -595,7 +595,9 @@ ARG is passed to `fill-paragraph'."
|
|||
(start-marker nil)
|
||||
(end-marker nil)
|
||||
(end-len 0))
|
||||
(when (equal (treesit-node-type node) "comment")
|
||||
;; These covers C/C++, Java, JavaScript, TypeScript, Rust, C#.
|
||||
(when (member (treesit-node-type node)
|
||||
'("comment" "line_comment" "block_comment"))
|
||||
;; We mask "/*" and the space before "*/" like
|
||||
;; `c-fill-paragraph' does.
|
||||
(atomic-change-group
|
||||
|
|
|
|||
|
|
@ -285,6 +285,96 @@ Only has effect when `ruby-use-smie' is t."
|
|||
:safe (lambda (val) (or (memq val '(t nil)) (numberp val)))
|
||||
:version "29.1")
|
||||
|
||||
(defcustom ruby-block-indent t
|
||||
"Non-nil to align the body of a block to the statement's start.
|
||||
|
||||
The body and the closer will be aligned to the column where the
|
||||
statement containing the block starts. Example:
|
||||
|
||||
foo.bar
|
||||
.each do
|
||||
baz
|
||||
end
|
||||
|
||||
If nil, it will be aligned instead to the beginning of the line
|
||||
containing the block's opener:
|
||||
|
||||
foo.bar
|
||||
.each do
|
||||
baz
|
||||
end
|
||||
|
||||
Only has effect when `ruby-use-smie' is t."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:version "29.1")
|
||||
|
||||
(defcustom ruby-after-operator-indent t
|
||||
"Non-nil to use structural indentation after binary operators.
|
||||
|
||||
The code will be aligned to the implicit parent expression,
|
||||
according to the operator precedence:
|
||||
|
||||
qux = 4 + 5 *
|
||||
6 +
|
||||
7
|
||||
|
||||
Set it to nil to align to the beginning of the statement:
|
||||
|
||||
qux = 4 + 5 *
|
||||
6 +
|
||||
7
|
||||
|
||||
Only has effect when `ruby-use-smie' is t."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:version "29.1")
|
||||
|
||||
(defcustom ruby-method-call-indent t
|
||||
"Non-nil to use the structural indentation algorithm.
|
||||
|
||||
The method call will be aligned to the implicit parent
|
||||
expression, according to the operator precedence:
|
||||
|
||||
foo = subject
|
||||
.update(
|
||||
1
|
||||
)
|
||||
|
||||
Set it to nil to align to the beginning of the statement:
|
||||
|
||||
foo = subject
|
||||
.update(
|
||||
1
|
||||
)
|
||||
|
||||
Only has effect when `ruby-use-smie' is t."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:version "29.1")
|
||||
|
||||
(defcustom ruby-parenless-call-arguments-indent t
|
||||
"Non-nil to align arguments in a parenless call vertically.
|
||||
|
||||
Example:
|
||||
|
||||
qux :+,
|
||||
bar,
|
||||
:[]=,
|
||||
bar
|
||||
|
||||
Set it to nil to align to the beginning of the statement:
|
||||
|
||||
qux :+,
|
||||
bar,
|
||||
:[]=,
|
||||
bar
|
||||
|
||||
Only has effect when `ruby-use-smie' is t."
|
||||
:type 'boolean
|
||||
:safe 'booleanp
|
||||
:version "29.1")
|
||||
|
||||
(defcustom ruby-deep-arglist t
|
||||
"Deep indent lists in parenthesis when non-nil.
|
||||
Also ignores spaces after parenthesis when `space'.
|
||||
|
|
@ -416,6 +506,7 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
'((right "=")
|
||||
(right "+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^="
|
||||
"<<=" ">>=" "&&=" "||=")
|
||||
(right "?")
|
||||
(nonassoc ".." "...")
|
||||
(left "&&" "||")
|
||||
(nonassoc "<=>")
|
||||
|
|
@ -608,10 +699,10 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
"def=")
|
||||
(t tok)))))))
|
||||
|
||||
(defun ruby-smie--indent-to-stmt ()
|
||||
(defun ruby-smie--indent-to-stmt (&optional offset)
|
||||
(save-excursion
|
||||
(smie-backward-sexp ";")
|
||||
(cons 'column (smie-indent-virtual))))
|
||||
(cons 'column (+ (smie-indent-virtual) (or offset 0)))))
|
||||
|
||||
(defun ruby-smie--indent-to-stmt-p (keyword)
|
||||
(or (eq t ruby-align-to-stmt-keywords)
|
||||
|
|
@ -642,7 +733,9 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(forward-comment -1)
|
||||
(not (eq (preceding-char) ?:))))
|
||||
;; Curly block opener.
|
||||
(ruby-smie--indent-to-stmt))
|
||||
(if ruby-block-indent
|
||||
(ruby-smie--indent-to-stmt)
|
||||
(cons 'column (current-indentation))))
|
||||
((smie-rule-hanging-p)
|
||||
;; Treat purely syntactic block-constructs as being part of their parent,
|
||||
;; when the opening token is hanging and the parent is not an
|
||||
|
|
@ -677,13 +770,20 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(unless (or (eolp) (forward-comment 1))
|
||||
(cons 'column (current-column)))))
|
||||
('(:before . " @ ")
|
||||
(if (or (eq ruby-method-params-indent t)
|
||||
(not (smie-rule-parent-p "def" "def=")))
|
||||
(save-excursion
|
||||
(skip-chars-forward " \t")
|
||||
(cons 'column (current-column)))
|
||||
(smie-rule-parent (or ruby-method-params-indent 0))))
|
||||
('(:before . "do") (ruby-smie--indent-to-stmt))
|
||||
(cond
|
||||
((and (not ruby-parenless-call-arguments-indent)
|
||||
(not (smie-rule-parent-p "def" "def=")))
|
||||
(ruby-smie--indent-to-stmt ruby-indent-level))
|
||||
((or (eq ruby-method-params-indent t)
|
||||
(not (smie-rule-parent-p "def" "def=")))
|
||||
(save-excursion
|
||||
(skip-chars-forward " \t")
|
||||
(cons 'column (current-column))))
|
||||
(t (smie-rule-parent (or ruby-method-params-indent 0)))))
|
||||
('(:before . "do")
|
||||
(if ruby-block-indent
|
||||
(ruby-smie--indent-to-stmt)
|
||||
(cons 'column (current-indentation))))
|
||||
('(:before . ".")
|
||||
(if (smie-rule-sibling-p)
|
||||
(when ruby-align-chained-calls
|
||||
|
|
@ -696,8 +796,10 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(not (smie-rule-bolp)))))
|
||||
(cons 'column (current-column)))
|
||||
(smie-backward-sexp ".")
|
||||
(cons 'column (+ (current-column)
|
||||
ruby-indent-level))))
|
||||
(if ruby-method-call-indent
|
||||
(cons 'column (+ (current-column)
|
||||
ruby-indent-level))
|
||||
(ruby-smie--indent-to-stmt ruby-indent-level))))
|
||||
(`(:before . ,(or "else" "then" "elsif" "rescue" "ensure"))
|
||||
(smie-rule-parent))
|
||||
(`(:before . ,(or "when" "in"))
|
||||
|
|
@ -708,16 +810,22 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
"<=>" ">" "<" ">=" "<=" "==" "===" "!=" "<<" ">>"
|
||||
"+=" "-=" "*=" "/=" "%=" "**=" "&=" "|=" "^=" "|"
|
||||
"<<=" ">>=" "&&=" "||=" "and" "or"))
|
||||
(and (smie-rule-parent-p ";" nil)
|
||||
(smie-indent--hanging-p)
|
||||
ruby-indent-level))
|
||||
(cond
|
||||
((not ruby-after-operator-indent)
|
||||
(ruby-smie--indent-to-stmt ruby-indent-level))
|
||||
((and (smie-rule-parent-p ";" nil)
|
||||
(smie-indent--hanging-p))
|
||||
ruby-indent-level)))
|
||||
(`(:before . "=")
|
||||
(save-excursion
|
||||
(and (smie-rule-parent-p " @ ")
|
||||
(goto-char (nth 1 (smie-indent--parent)))
|
||||
(smie-rule-prev-p "def=")
|
||||
(cons 'column (+ (current-column) ruby-indent-level -3)))))
|
||||
(`(:after . ,(or "?" ":")) ruby-indent-level)
|
||||
(`(:after . ,(or "?" ":"))
|
||||
(if ruby-after-operator-indent
|
||||
ruby-indent-level
|
||||
(ruby-smie--indent-to-stmt ruby-indent-level)))
|
||||
(`(:before . ,(guard (memq (intern-soft token) ruby-alignable-keywords)))
|
||||
(when (not (ruby--at-indentation-p))
|
||||
(if (ruby-smie--indent-to-stmt-p token)
|
||||
|
|
@ -725,7 +833,10 @@ This only affects the output of the command `ruby-toggle-block'."
|
|||
(cons 'column (current-column)))))
|
||||
('(:before . "iuwu-mod")
|
||||
(smie-rule-parent ruby-indent-level))
|
||||
))
|
||||
(`(:before . ",")
|
||||
(and (not ruby-parenless-call-arguments-indent)
|
||||
(smie-rule-parent-p " @ ")
|
||||
(ruby-smie--indent-to-stmt ruby-indent-level)))))
|
||||
|
||||
(defun ruby--at-indentation-p (&optional point)
|
||||
(save-excursion
|
||||
|
|
|
|||
142
lisp/treesit.el
142
lisp/treesit.el
|
|
@ -36,6 +36,7 @@
|
|||
(eval-when-compile (require 'subr-x)) ; For `string-join'.
|
||||
(require 'cl-seq)
|
||||
(require 'font-lock)
|
||||
(require 'seq)
|
||||
|
||||
;;; Function declarations
|
||||
|
||||
|
|
@ -2163,7 +2164,7 @@ instead of emitting a warning."
|
|||
(pcase-let ((`(,available . ,err)
|
||||
(treesit-language-available-p lang t)))
|
||||
(when (not available)
|
||||
(setq msg (format "language definition for %s is unavailable (%s): %s"
|
||||
(setq msg (format "language grammar for %s is unavailable (%s): %s"
|
||||
lang (nth 0 err)
|
||||
(string-join
|
||||
(mapcar (lambda (x) (format "%s" x))
|
||||
|
|
@ -2310,7 +2311,7 @@ When this mode is enabled, the mode-line displays
|
|||
where NODE, CHILD, etc, are nodes which begin at point. PARENT
|
||||
is the parent of NODE. NODE is displayed in bold typeface.
|
||||
FIELD-NAMEs are field names of NODE and CHILD, etc (see Info
|
||||
node `(elisp)Language Definitions', heading \"Field names\").
|
||||
node `(elisp)Language Grammar', heading \"Field names\").
|
||||
|
||||
If no node starts at point, i.e., point is in the middle of a
|
||||
node, then the mode line displays the earliest node that spans point,
|
||||
|
|
@ -2649,6 +2650,143 @@ window."
|
|||
#'treesit--explorer-post-command t)
|
||||
(kill-buffer treesit--explorer-buffer)))
|
||||
|
||||
;;; Install & build language grammar
|
||||
|
||||
(defvar treesit-language-source-alist nil
|
||||
"Configures how to download tree-sitter language grammars.
|
||||
This should be an alist of
|
||||
|
||||
(LANG . (URL SOURCE-DIR GRAMMAR-DIR CC C++))
|
||||
|
||||
Only LANG and URL are mandatory. LANG is the language symbol.
|
||||
URL is the repository's url.
|
||||
|
||||
SOURCE-DIR is the relative directory in the repository in which
|
||||
the grammar.c file resides, default to \"src\".
|
||||
|
||||
GRAMMAR-DIR is the relative grammar directory in the repository
|
||||
in which the grammar.js file resides, default to \"\".
|
||||
|
||||
CC and C++ are C and C++ compilers, default to \"cc\" and
|
||||
\"c++\", respectively.")
|
||||
|
||||
(defun treesit-install-language-grammar (lang)
|
||||
"Build and install the tree-sitter language grammar library for LANG.
|
||||
|
||||
This command requires Git, a C compiler and (sometimes) a C++ compiler,
|
||||
and the linker to be installed and on PATH. It also requires that the
|
||||
recipe for LANG exists in `treesit-language-source-alist'.
|
||||
|
||||
See `exec-path' for the current path where Emacs looks for
|
||||
executable programs, such as the C/C++ compiler and linker."
|
||||
(interactive (list (intern
|
||||
(completing-read
|
||||
"Language: "
|
||||
(mapcar #'car treesit-language-source-alist)
|
||||
nil t))))
|
||||
(condition-case err
|
||||
(apply #'treesit--install-language-grammar-1
|
||||
;; The nil is OUT-DIR.
|
||||
(cons nil (assoc lang treesit-language-source-alist)))
|
||||
(error
|
||||
(display-warning
|
||||
'treesit
|
||||
(format "Error encountered when installing language grammar: %s"
|
||||
err))))
|
||||
;; Check that the installed language grammar is loadable.
|
||||
(pcase-let ((`(,available . ,err)
|
||||
(treesit-language-available-p lang t)))
|
||||
(when (not available)
|
||||
(display-warning
|
||||
'treesit
|
||||
(format "The installed language grammar for %s cannot be located or has problems (%s): %s"
|
||||
lang (nth 0 err)
|
||||
(string-join
|
||||
(mapcar (lambda (x) (format "%s" x))
|
||||
(cdr err))
|
||||
" "))))))
|
||||
|
||||
(defun treesit--call-process-signal (&rest args)
|
||||
"Run `call-process' with ARGS.
|
||||
If it returns anything but 0, signal an error. Use the buffer
|
||||
content as signal data, and erase buffer afterwards."
|
||||
(unless (eq 0 (apply #'call-process args))
|
||||
(signal 'treesit-error (list "Command:"
|
||||
(string-join (cons (car args)
|
||||
(nthcdr 4 args))
|
||||
" ")
|
||||
"Error output:"
|
||||
(buffer-string)))
|
||||
(erase-buffer)))
|
||||
|
||||
(defun treesit--install-language-grammar-1
|
||||
(out-dir lang url &optional source-dir grammar-dir cc c++)
|
||||
"Install and compile a tree-sitter language grammar library.
|
||||
|
||||
OUT-DIR is the directory to put the compiled library file. If it
|
||||
is nil, the \"tree-sitter\" directory under user's Emacs
|
||||
configuration directory is used (and automatically created if not
|
||||
exist).
|
||||
|
||||
For LANG, URL, SOURCE-DIR, GRAMMAR-DIR, CC, C++, see
|
||||
`treesit-language-source-alist'. If anything goes wrong, this
|
||||
function signals an error."
|
||||
(let* ((lang (symbol-name lang))
|
||||
(default-directory (make-temp-file "treesit-workdir" t))
|
||||
(workdir (expand-file-name "repo"))
|
||||
(source-dir (expand-file-name (or source-dir "src") workdir))
|
||||
(grammar-dir (expand-file-name (or grammar-dir "") workdir))
|
||||
(cc (or cc (seq-find #'executable-find '("cc" "gcc" "c99"))
|
||||
;; If no C compiler found, just use cc and let
|
||||
;; `call-process' signal the error.
|
||||
"cc"))
|
||||
(c++ (or c++ (seq-find #'executable-find '("c++" "g++"))
|
||||
"c++"))
|
||||
(soext (or (car dynamic-library-suffixes)
|
||||
(signal 'treesit-error '("Emacs cannot figure out the file extension for dynamic libraries for this system, because `dynamic-library-suffixes' is nil"))))
|
||||
(out-dir (or (and out-dir (expand-file-name out-dir))
|
||||
(locate-user-emacs-file "tree-sitter")))
|
||||
(lib-name (concat "libtree-sitter-" lang soext)))
|
||||
(unwind-protect
|
||||
(with-temp-buffer
|
||||
(message "Cloning repository")
|
||||
;; git clone xxx --depth 1 --quiet workdir
|
||||
(treesit--call-process-signal
|
||||
"git" nil t nil "clone" url "--depth" "1" "--quiet"
|
||||
workdir)
|
||||
;; cp "${grammardir}"/grammar.js "${sourcedir}"
|
||||
(copy-file (expand-file-name "grammar.js" grammar-dir)
|
||||
(expand-file-name "grammar.js" source-dir)
|
||||
t t)
|
||||
;; cd "${sourcedir}"
|
||||
(setq default-directory source-dir)
|
||||
(message "Compiling library")
|
||||
;; cc -fPIC -c -I. parser.c
|
||||
(treesit--call-process-signal
|
||||
cc nil t nil "-fPIC" "-c" "-I." "parser.c")
|
||||
;; cc -fPIC -c -I. scanner.c
|
||||
(when (file-exists-p "scanner.c")
|
||||
(treesit--call-process-signal
|
||||
cc nil t nil "-fPIC" "-c" "-I." "scanner.c"))
|
||||
;; c++ -fPIC -I. -c scanner.cc
|
||||
(when (file-exists-p "scanner.cc")
|
||||
(treesit--call-process-signal
|
||||
c++ nil t nil "-fPIC" "-c" "-I." "scanner.cc"))
|
||||
;; cc/c++ -fPIC -shared *.o -o "libtree-sitter-${lang}.${soext}"
|
||||
(apply #'treesit--call-process-signal
|
||||
(if (file-exists-p "scanner.cc") c++ cc)
|
||||
nil t nil
|
||||
`("-fPIC" "-shared"
|
||||
,@(directory-files
|
||||
default-directory nil
|
||||
(rx bos (+ anychar) ".o" eos))
|
||||
"-o" ,lib-name))
|
||||
;; Copy out.
|
||||
(copy-file lib-name (file-name-as-directory out-dir) t t)
|
||||
(message "Library installed to %s/%s" out-dir lib-name))
|
||||
(when (file-exists-p workdir)
|
||||
(delete-directory workdir t)))))
|
||||
|
||||
;;; Etc
|
||||
|
||||
(declare-function find-library-name "find-func.el")
|
||||
|
|
|
|||
|
|
@ -662,9 +662,8 @@ If DETAIL is non-nil, return (t . nil) when LANGUAGE is available,
|
|||
}
|
||||
}
|
||||
|
||||
DEFUN ("treesit-language-version",
|
||||
Ftreesit_language_version,
|
||||
Streesit_language_version,
|
||||
DEFUN ("treesit-library-abi-version", Ftreesit_library_abi_version,
|
||||
Streesit_library_abi_version,
|
||||
0, 1, 0,
|
||||
doc: /* Return the language ABI version of the tree-sitter library.
|
||||
|
||||
|
|
@ -680,6 +679,29 @@ is non-nil, return the oldest compatible ABI version. */)
|
|||
return make_fixnum (TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION);
|
||||
}
|
||||
|
||||
DEFUN ("treesit-language-version", Ftreesit_language_abi_version,
|
||||
Streesit_language_abi_version,
|
||||
0, 1, 0,
|
||||
doc: /* Return the language ABI version of the tree-sitter LANGUAGE.
|
||||
Return nil if LANGUAGE is not available. */)
|
||||
(Lisp_Object language)
|
||||
{
|
||||
if (NILP (Ftreesit_langauge_available_p (language, Qnil)))
|
||||
return Qnil;
|
||||
else
|
||||
{
|
||||
Lisp_Object signal_symbol = Qnil;
|
||||
Lisp_Object signal_data = Qnil;
|
||||
TSLanguage *ts_language = treesit_load_language (language,
|
||||
&signal_symbol,
|
||||
&signal_data);
|
||||
if (ts_language == NULL)
|
||||
return Qnil;
|
||||
uint32_t version = ts_language_version (ts_language);
|
||||
return make_fixnum((ptrdiff_t) version);
|
||||
}
|
||||
}
|
||||
|
||||
/*** Parsing functions */
|
||||
|
||||
static void
|
||||
|
|
@ -1172,10 +1194,12 @@ treesit_query_error_to_string (TSQueryError error)
|
|||
|
||||
static Lisp_Object
|
||||
treesit_compose_query_signal_data (uint32_t error_offset,
|
||||
TSQueryError error_type)
|
||||
TSQueryError error_type,
|
||||
Lisp_Object query_source)
|
||||
{
|
||||
return list3 (build_string (treesit_query_error_to_string (error_type)),
|
||||
return list4 (build_string (treesit_query_error_to_string (error_type)),
|
||||
make_fixnum (error_offset + 1),
|
||||
query_source,
|
||||
build_pure_c_string ("Debug the query with `treesit-query-validate'"));
|
||||
}
|
||||
|
||||
|
|
@ -1217,7 +1241,8 @@ treesit_ensure_query_compiled (Lisp_Object query, Lisp_Object *signal_symbol,
|
|||
{
|
||||
*signal_symbol = Qtreesit_query_error;
|
||||
*signal_data = treesit_compose_query_signal_data (error_offset,
|
||||
error_type);
|
||||
error_type,
|
||||
source);
|
||||
}
|
||||
XTS_COMPILED_QUERY (query)->query = treesit_query;
|
||||
return treesit_query;
|
||||
|
|
@ -2605,7 +2630,7 @@ the query. */)
|
|||
if (treesit_query == NULL)
|
||||
xsignal (Qtreesit_query_error,
|
||||
treesit_compose_query_signal_data (error_offset,
|
||||
error_type));
|
||||
error_type, query));
|
||||
cursor = ts_query_cursor_new ();
|
||||
needs_to_free_query_and_cursor = true;
|
||||
}
|
||||
|
|
@ -3345,7 +3370,8 @@ then in the system default locations for dynamic libraries, in that order. */);
|
|||
Vtreesit_extra_load_path = Qnil;
|
||||
|
||||
defsubr (&Streesit_language_available_p);
|
||||
defsubr (&Streesit_language_version);
|
||||
defsubr (&Streesit_library_abi_version);
|
||||
defsubr (&Streesit_language_abi_version);
|
||||
|
||||
defsubr (&Streesit_parser_p);
|
||||
defsubr (&Streesit_node_p);
|
||||
|
|
|
|||
|
|
@ -5510,15 +5510,11 @@ INPUT, if non-nil, is a string sent to the process."
|
|||
;; String to be sent.
|
||||
(format "%s\n" (file-name-nondirectory tmp-name)))
|
||||
(should
|
||||
(string-equal
|
||||
;; tramp-adb.el echoes, so we must add the string.
|
||||
(if (and (tramp--test-adb-p)
|
||||
(not (tramp-direct-async-process-p)))
|
||||
(format
|
||||
"%s\n%s\n"
|
||||
(file-name-nondirectory tmp-name)
|
||||
(file-name-nondirectory tmp-name))
|
||||
(format "%s\n" (file-name-nondirectory tmp-name)))
|
||||
(string-match-p
|
||||
;; Some shells echo, for example the "adb" or "docker" methods.
|
||||
(tramp-compat-rx
|
||||
bos (** 1 2 (literal (file-name-nondirectory tmp-name)) "\n")
|
||||
eos)
|
||||
(buffer-string))))
|
||||
|
||||
;; Cleanup.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
4 +
|
||||
5 +
|
||||
6 +
|
||||
7
|
||||
|
||||
qux = 4 + 5 *
|
||||
6 +
|
||||
7
|
||||
|
||||
foo = obj.bar { |m| tee(m) } +
|
||||
obj.qux { |m| hum(m) }
|
||||
|
||||
foo.
|
||||
bar
|
||||
.baz
|
||||
|
||||
qux = foo.fee ?
|
||||
bar :
|
||||
tee
|
||||
|
||||
# Endless methods.
|
||||
class Bar
|
||||
def foo(abc) = bar +
|
||||
baz
|
||||
end
|
||||
|
||||
# Local Variables:
|
||||
# ruby-after-operator-indent: nil
|
||||
# End:
|
||||
33
test/lisp/progmodes/ruby-mode-resources/ruby-block-indent.rb
Normal file
33
test/lisp/progmodes/ruby-mode-resources/ruby-block-indent.rb
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
foo
|
||||
.asdasd
|
||||
.proc do |**args|
|
||||
p(**args)
|
||||
end
|
||||
|
||||
foo
|
||||
.asdasd
|
||||
.proc { |**args|
|
||||
p(**args)
|
||||
}
|
||||
|
||||
bar.foo do
|
||||
bar
|
||||
end
|
||||
|
||||
bar.foo(tee) do
|
||||
bar
|
||||
end
|
||||
|
||||
bar.foo(tee) {
|
||||
bar
|
||||
}
|
||||
|
||||
x.foo do
|
||||
foo
|
||||
end.bar do
|
||||
bar
|
||||
end
|
||||
|
||||
# Local Variables:
|
||||
# ruby-block-indent: nil
|
||||
# End:
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
foo2 =
|
||||
subject.
|
||||
update(
|
||||
2
|
||||
)
|
||||
|
||||
foo3 =
|
||||
subject
|
||||
.update(
|
||||
2
|
||||
)
|
||||
|
||||
# Local Variables:
|
||||
# ruby-method-call-indent: nil
|
||||
# End:
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
method arg1,
|
||||
method2 arg2,
|
||||
arg3, [
|
||||
arg4,
|
||||
arg5
|
||||
]
|
||||
|
||||
zzz = method (a + b),
|
||||
c, :d => :e,
|
||||
f: g
|
||||
|
||||
return render json: {
|
||||
errors: { base: [message] },
|
||||
copying: copying
|
||||
},
|
||||
status: 400
|
||||
|
||||
foo(a,
|
||||
b)
|
||||
|
||||
# Local Variables:
|
||||
# ruby-parenless-call-arguments-indent: nil
|
||||
# End:
|
||||
|
|
@ -226,6 +226,7 @@ def begin
|
|||
|
||||
foo.
|
||||
bar
|
||||
.baz
|
||||
|
||||
# https://github.com/rails/rails/blob/17f5d8e062909f1fcae25351834d8e89967b645e/activesupport/lib/active_support/time_with_zone.rb#L206
|
||||
foo # comment intended to confuse the tokenizer
|
||||
|
|
@ -380,6 +381,18 @@ def bar
|
|||
i + 1
|
||||
end
|
||||
|
||||
m1 = foo
|
||||
.asdasd
|
||||
.proc do |**args|
|
||||
p(**args)
|
||||
end
|
||||
|
||||
m2 = foo
|
||||
.asdasd
|
||||
.proc { |**args|
|
||||
p(**args)
|
||||
}
|
||||
|
||||
bar.foo do
|
||||
bar
|
||||
end
|
||||
|
|
@ -398,6 +411,12 @@ def bar
|
|||
end
|
||||
end
|
||||
|
||||
x.foo do
|
||||
foo
|
||||
end.bar do
|
||||
bar
|
||||
end
|
||||
|
||||
foo |
|
||||
bar
|
||||
|
||||
|
|
@ -540,5 +559,9 @@ def baz.full_name = "#{bar} 3"
|
|||
end
|
||||
|
||||
# Local Variables:
|
||||
# ruby-after-operator-indent: t
|
||||
# ruby-block-indent: t
|
||||
# ruby-method-call-indent: t
|
||||
# ruby-method-params-indent: t
|
||||
# ruby-parenless-call-arguments-indent: t
|
||||
# End:
|
||||
|
|
|
|||
|
|
@ -956,7 +956,11 @@ VALUES-PLIST is a list with alternating index and value elements."
|
|||
(kill-buffer buf)))))
|
||||
|
||||
(ruby-deftest-indent "ruby.rb")
|
||||
(ruby-deftest-indent "ruby-after-operator-indent.rb")
|
||||
(ruby-deftest-indent "ruby-block-indent.rb")
|
||||
(ruby-deftest-indent "ruby-method-call-indent.rb")
|
||||
(ruby-deftest-indent "ruby-method-params-indent.rb")
|
||||
(ruby-deftest-indent "ruby-parenless-call-arguments-indent.rb")
|
||||
|
||||
(ert-deftest ruby--test-chained-indentation ()
|
||||
(with-temp-buffer
|
||||
|
|
|
|||
Loading…
Reference in a new issue