Merge remote-tracking branch 'origin/master' into feature/android
This commit is contained in:
commit
7b5d32fa87
37 changed files with 2607 additions and 859 deletions
999
ChangeLog.4
999
ChangeLog.4
File diff suppressed because it is too large
Load diff
|
@ -6761,16 +6761,13 @@ The name of the @code{cons} function is not unreasonable: it is an
|
|||
abbreviation of the word ``construct''. The origins of the names for
|
||||
@code{car} and @code{cdr}, on the other hand, are esoteric: @code{car}
|
||||
is an acronym from the phrase ``Contents of the Address part of the
|
||||
Register''; and @code{cdr} (pronounced ``could-er'') is an acronym from
|
||||
the phrase ``Contents of the Decrement part of the Register''. These
|
||||
phrases refer to specific pieces of hardware on the very early
|
||||
computer on which the original Lisp was developed. Besides being
|
||||
obsolete, the phrases have been completely irrelevant for more than 25
|
||||
years to anyone thinking about Lisp. Nonetheless, although a few
|
||||
brave scholars have begun to use more reasonable names for these
|
||||
functions, the old terms are still in use. In particular, since the
|
||||
terms are used in the Emacs Lisp source code, we will use them in this
|
||||
introduction.
|
||||
Register''; and @code{cdr} (pronounced ``could-er'') is an acronym
|
||||
from the phrase ``Contents of the Decrement part of the Register''.
|
||||
These phrases refer to the IBM 704 computer on which the original Lisp
|
||||
was developed.
|
||||
|
||||
The IBM 704 is a footnote in history, but these names are now beloved
|
||||
traditions of Lisp.
|
||||
|
||||
@node car & cdr
|
||||
@section @code{car} and @code{cdr}
|
||||
|
@ -6791,9 +6788,6 @@ evaluating the following:
|
|||
After evaluating the expression, @code{rose} will appear in the echo
|
||||
area.
|
||||
|
||||
Clearly, a more reasonable name for the @code{car} function would be
|
||||
@code{first} and this is often suggested.
|
||||
|
||||
@code{car} does not remove the first item from the list; it only reports
|
||||
what it is. After @code{car} has been applied to a list, the list is
|
||||
still the same as it was. In the jargon, @code{car} is
|
||||
|
@ -6825,6 +6819,22 @@ Incidentally, in the example, the list of flowers is quoted. If it were
|
|||
not, the Lisp interpreter would try to evaluate the list by calling
|
||||
@code{rose} as a function. In this example, we do not want to do that.
|
||||
|
||||
For operating on lists, the names @code{first} and @code{rest} would
|
||||
make more sense than the names @code{car} and @code{cdr}. Indeed,
|
||||
some programmers define @code{first} and @code{rest} as aliases for
|
||||
@code{car} and @code{cdr}, then write @code{first} and @code{rest} in
|
||||
their code.
|
||||
|
||||
However, lists in Lisp are built using a lower-level structure known
|
||||
as ``cons cells'' (@pxref{List Implementation}), in which there is no
|
||||
such thing as ``first'' or ``rest,''and the @sc{car} and the @sc{cdr}
|
||||
are symmetrical. Lisp does not try to hide the existence of cons
|
||||
cells, and programs do use them for things other than lists. For this
|
||||
reason, the names are helpful for reminding programmers that
|
||||
@code{car} and @code{cdr} are in fact symmetrical, despite the
|
||||
asymmetrical way they are used in lists.
|
||||
|
||||
@ignore
|
||||
Clearly, a more reasonable name for @code{cdr} would be @code{rest}.
|
||||
|
||||
(There is a lesson here: when you name new functions, consider very
|
||||
|
@ -6834,6 +6844,7 @@ these names is that the Emacs Lisp source code uses them, and if I did
|
|||
not use them, you would have a hard time reading the code; but do,
|
||||
please, try to avoid using these terms yourself. The people who come
|
||||
after you will be grateful to you.)
|
||||
@end ignore
|
||||
|
||||
When @code{car} and @code{cdr} are applied to a list made up of symbols,
|
||||
such as the list @code{(pine fir oak maple)}, the element of the list
|
||||
|
@ -9429,13 +9440,15 @@ pointed to. Hence, a list is kept as a series of electronic addresses.
|
|||
@unnumberedsec Lists diagrammed
|
||||
@end ifnottex
|
||||
|
||||
For example, the list @code{(rose violet buttercup)} has three elements,
|
||||
@samp{rose}, @samp{violet}, and @samp{buttercup}. In the computer, the
|
||||
electronic address of @samp{rose} is recorded in a segment of computer
|
||||
memory along with the address that gives the electronic address of where
|
||||
the atom @samp{violet} is located; and that address (the one that tells
|
||||
where @samp{violet} is located) is kept along with an address that tells
|
||||
where the address for the atom @samp{buttercup} is located.
|
||||
For example, the list @code{(rose violet buttercup)} has three
|
||||
elements, @samp{rose}, @samp{violet}, and @samp{buttercup}. In the
|
||||
computer, the electronic address of @samp{rose} is recorded in a
|
||||
segment of computer memory called a @dfn{cons cell} (because it's what
|
||||
the function @code{cons} actually creates). That cons cell also holds
|
||||
the address of a second cons cell, whose @sc{car} is the atom
|
||||
@samp{violet}; and that address (the one that tells where to find
|
||||
@samp{violet}) is kept along with the address of a third cons cell
|
||||
which holds the address for the atom @samp{buttercup}.
|
||||
|
||||
@need 1200
|
||||
This sounds more complicated than it is and is easier seen in a diagram:
|
||||
|
@ -9652,6 +9665,8 @@ to say, the symbol @code{flowers} holds the address of the pair of
|
|||
address-boxes, the first of which holds the address of @code{violet},
|
||||
and the second of which holds the address of @code{buttercup}.
|
||||
|
||||
@cindex dotted pair
|
||||
@cindex cons cell
|
||||
A pair of address-boxes is called a @dfn{cons cell} or @dfn{dotted
|
||||
pair}. @xref{Cons Cell Type, , Cons Cell and List Types, elisp, The GNU Emacs Lisp
|
||||
Reference Manual}, and @ref{Dotted Pair Notation, , Dotted Pair
|
||||
|
|
|
@ -1792,34 +1792,43 @@ of them:
|
|||
@table @code
|
||||
@item priority
|
||||
@kindex priority @r{(overlay property)}
|
||||
This property's value determines the priority of the overlay.
|
||||
If you want to specify a priority value, use either @code{nil}
|
||||
(or zero), or a positive integer. Any other value has undefined behavior.
|
||||
This property's value determines the priority of the overlay. If you
|
||||
want to specify a priority value, use either @code{nil} (or zero), or
|
||||
a positive integer, or a cons of two values. Any other value triggers
|
||||
undefined behavior.
|
||||
|
||||
The priority matters when two or more overlays cover the same
|
||||
character and both specify the same property with different values;
|
||||
the one whose @code{priority} value is larger overrides the other.
|
||||
the one whose @code{priority} value is higher overrides the other.
|
||||
(For the @code{face} property, the higher priority overlay's value
|
||||
does not completely override the other value; instead, its face
|
||||
attributes override the face attributes of the @code{face} property
|
||||
whose priority is lower.) If two overlays have the same priority
|
||||
value, and one is nested in the other, then the inner one will prevail
|
||||
over the outer one. If neither is nested in the other then you should
|
||||
not make assumptions about which overlay will prevail.
|
||||
does not completely override the other value; instead, its individual
|
||||
face attributes override the corresponding face attributes of the
|
||||
@code{face} property whose priority is lower.) If two overlays have
|
||||
the same priority value, and one is ``nested'' in the other (i.e.,
|
||||
covers fewer buffer or string positions), then the inner one will
|
||||
prevail over the outer one. If neither is nested in the other then
|
||||
you should not make assumptions about which overlay will prevail.
|
||||
|
||||
When a Lisp program puts overlays with defined priorities on text that
|
||||
might have overlays without priorities, this could cause undesirable
|
||||
results, because any overlay with a positive priority value will
|
||||
override all the overlays without a priority. Since most Emacs
|
||||
features that use overlays don't specify priorities for their
|
||||
overlays, integer priorities should be used with care. Instead of
|
||||
using integer priorities and risk overriding other overlays, you can
|
||||
use priority values of the form @w{@code{(@var{primary} . @var{secondary})}},
|
||||
where the @var{primary} value is used as described above, and
|
||||
@var{secondary} is the fallback value used when @var{primary} and the
|
||||
nesting considerations fail to resolve the precedence between
|
||||
overlays. In particular, priority value @w{@code{(nil . @var{n})}},
|
||||
with @var{n} a positive integer, allows to have the overlays ordered
|
||||
by priority when necessary without completely overriding other
|
||||
overlays.
|
||||
|
||||
Currently, all overlays take priority over text properties.
|
||||
|
||||
Note that Emacs sometimes uses non-numeric priority values for some of
|
||||
its internal overlays, so do not try to do arithmetic on the priority
|
||||
of an overlay (unless it is one that you created). In particular, the
|
||||
overlay used for showing the region uses a priority value of the form
|
||||
@w{@code{(@var{primary} . @var{secondary})}}, where the @var{primary}
|
||||
value is used as described above, and @var{secondary} is the fallback
|
||||
value used when @var{primary} and the nesting considerations fail to
|
||||
resolve the precedence between overlays. However, you are advised not
|
||||
to design Lisp programs based on this implementation detail; if you
|
||||
need to put overlays in priority order, use the @var{sorted} argument
|
||||
of @code{overlays-at}. @xref{Finding Overlays}.
|
||||
If you need to put overlays in priority order, use the @var{sorted}
|
||||
argument of @code{overlays-at}. @xref{Finding Overlays}.
|
||||
|
||||
@item window
|
||||
@kindex window @r{(overlay property)}
|
||||
|
@ -3330,8 +3339,8 @@ enough to the overlay, Emacs applies the face or face attributes
|
|||
specified by the @code{mouse-face} property instead. @xref{Overlay
|
||||
Properties}.
|
||||
|
||||
When multiple overlays cover one character, an overlay with higher
|
||||
priority overrides those with lower priority. @xref{Overlays}.
|
||||
When multiple overlays cover the same character, an overlay with
|
||||
higher priority overrides those with lower priority. @xref{Overlays}.
|
||||
|
||||
@item
|
||||
If the text contains a @code{face} or @code{mouse-face} property,
|
||||
|
|
|
@ -2813,13 +2813,23 @@ minibuffer window, it returns @code{nil}.
|
|||
|
||||
@vindex minibuffer-message-timeout
|
||||
@defun minibuffer-message string &rest args
|
||||
This function displays @var{string} temporarily at the end of the
|
||||
minibuffer text, for a few seconds, or until the next input event
|
||||
arrives, whichever comes first. The variable
|
||||
@code{minibuffer-message-timeout} specifies the number of seconds to
|
||||
wait in the absence of input. It defaults to 2. If @var{args} is
|
||||
non-@code{nil}, the actual message is obtained by passing @var{string}
|
||||
and @var{args} through @code{format-message}. @xref{Formatting Strings}.
|
||||
This function is like @code{message} (@pxref{Displaying Messages}),
|
||||
but it displays the messages specially when the user types in the
|
||||
minibuffer, typically because Emacs prompted the user for some input.
|
||||
When the minibuffer is the current buffer, this function displays the
|
||||
message specified by @var{string} temporarily at the end of the
|
||||
minibuffer text, and thus avoids hiding the minibuffer text by the
|
||||
echo-area display of the message. It leaves the message on display
|
||||
for a few seconds, or until the next input event arrives, whichever
|
||||
comes first. The variable @code{minibuffer-message-timeout} specifies
|
||||
the number of seconds to wait in the absence of input. It defaults to
|
||||
2. If @var{args} is non-@code{nil}, the actual message is obtained by
|
||||
passing @var{string} and @var{args} through @code{format-message}.
|
||||
@xref{Formatting Strings}.
|
||||
|
||||
If called when the minibuffer is not the current buffer, this function
|
||||
just calls @code{message}, and thus @var{string} will be shown in the
|
||||
echo-area.
|
||||
@end defun
|
||||
|
||||
@deffn Command minibuffer-inactive-mode
|
||||
|
|
|
@ -1888,11 +1888,14 @@ user option called the same as the global mode variable, but with
|
|||
@code{-modes} instead of @code{-mode} at the end, i.e.@:
|
||||
@code{@var{global-mode}s}. This variable will be used in a predicate
|
||||
function that determines whether the minor mode should be activated in
|
||||
a particular major mode. Valid values of @code{:predicate} include
|
||||
@code{t} (use in all major modes), @code{nil} (don't use in any major
|
||||
modes), or a list of mode names, optionally preceded with @code{not}
|
||||
(as in @w{@code{(not @var{mode-name} @dots{})}}). These elements can
|
||||
be mixed, as shown in the following examples.
|
||||
a particular major mode, and users can customize the value of the
|
||||
variable to control the modes in which the minor mode will be switched
|
||||
on. Valid values of @code{:predicate} (and thus valid values of the
|
||||
user option it creates) include @code{t} (use in all major modes),
|
||||
@code{nil} (don't use in any major modes), or a list of mode names,
|
||||
optionally preceded with @code{not} (as in @w{@code{(not
|
||||
@var{mode-name} @dots{})}}). These elements can be mixed, as shown in
|
||||
the following examples.
|
||||
|
||||
@example
|
||||
(c-mode (not mail-mode message-mode) text-mode)
|
||||
|
|
|
@ -1131,9 +1131,9 @@ Now we can introduce the @dfn{query functions}.
|
|||
|
||||
@defun treesit-query-capture node query &optional beg end node-only
|
||||
This function matches patterns in @var{query} within @var{node}. The
|
||||
argument @var{query} can be either a string, an s-expression, or a
|
||||
compiled query object. For now, we focus on the string syntax;
|
||||
s-expression syntax and compiled queries are described at the end of
|
||||
argument @var{query} can be either an s-expression, a string, or a
|
||||
compiled query object. For now, we focus on the s-expression syntax;
|
||||
string syntax and compiled queries are described at the end of
|
||||
the section.
|
||||
|
||||
The argument @var{node} can also be a parser or a language symbol. A
|
||||
|
@ -1165,8 +1165,8 @@ For example, suppose @var{node}'s text is @code{1 + 2}, and
|
|||
@example
|
||||
@group
|
||||
(setq query
|
||||
"(binary_expression
|
||||
(number_literal) @@number-in-exp) @@biexp")
|
||||
'((binary_expression
|
||||
(number_literal) @@number-in-exp) @@biexp)
|
||||
@end group
|
||||
@end example
|
||||
|
||||
|
@ -1187,8 +1187,8 @@ For example, it could have two top-level patterns:
|
|||
@example
|
||||
@group
|
||||
(setq query
|
||||
"(binary_expression) @@biexp
|
||||
(number_literal) @@number @@biexp")
|
||||
'((binary_expression) @@biexp
|
||||
(number_literal) @@number @@biexp)
|
||||
@end group
|
||||
@end example
|
||||
|
||||
|
@ -1246,23 +1246,23 @@ field, say, a @code{function_definition} without a @code{body} field:
|
|||
@subheading Quantify node
|
||||
|
||||
@cindex quantify node, tree-sitter
|
||||
Tree-sitter recognizes quantification operators @samp{*}, @samp{+},
|
||||
and @samp{?}. Their meanings are the same as in regular expressions:
|
||||
@samp{*} matches the preceding pattern zero or more times, @samp{+}
|
||||
matches one or more times, and @samp{?} matches zero or one times.
|
||||
Tree-sitter recognizes quantification operators @samp{:*}, @samp{:+},
|
||||
and @samp{:?}. Their meanings are the same as in regular expressions:
|
||||
@samp{:*} matches the preceding pattern zero or more times, @samp{:+}
|
||||
matches one or more times, and @samp{:?} matches zero or one times.
|
||||
|
||||
For example, the following pattern matches @code{type_declaration}
|
||||
nodes that have @emph{zero or more} @code{long} keywords.
|
||||
|
||||
@example
|
||||
(type_declaration "long"*) @@long-type
|
||||
(type_declaration "long" :*) @@long-type
|
||||
@end example
|
||||
|
||||
The following pattern matches a type declaration that may or may not
|
||||
have a @code{long} keyword:
|
||||
|
||||
@example
|
||||
(type_declaration "long"?) @@long-type
|
||||
(type_declaration "long" :?) @@long-type
|
||||
@end example
|
||||
|
||||
@subheading Grouping
|
||||
|
@ -1272,15 +1272,14 @@ groups and apply quantification operators to them. For example, to
|
|||
express a comma-separated list of identifiers, one could write
|
||||
|
||||
@example
|
||||
(identifier) ("," (identifier))*
|
||||
(identifier) ("," (identifier)) :*
|
||||
@end example
|
||||
|
||||
@subheading Alternation
|
||||
|
||||
Again, similar to regular expressions, we can express ``match any one
|
||||
of these patterns'' in a pattern. The syntax is a list of patterns
|
||||
enclosed in square brackets. For example, to capture some keywords in
|
||||
C, the pattern would be
|
||||
of these patterns'' in a pattern. The syntax is a vector of patterns.
|
||||
For example, to capture some keywords in C, the pattern would be
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -1295,7 +1294,7 @@ C, the pattern would be
|
|||
|
||||
@subheading Anchor
|
||||
|
||||
The anchor operator @samp{.} can be used to enforce juxtaposition,
|
||||
The anchor operator @code{:anchor} can be used to enforce juxtaposition,
|
||||
i.e., to enforce two things to be directly next to each other. The
|
||||
two ``things'' can be two nodes, or a child and the end of its parent.
|
||||
For example, to capture the first child, the last child, or two
|
||||
|
@ -1304,19 +1303,19 @@ adjacent children:
|
|||
@example
|
||||
@group
|
||||
;; Anchor the child with the end of its parent.
|
||||
(compound_expression (_) @@last-child .)
|
||||
(compound_expression (_) @@last-child :anchor)
|
||||
@end group
|
||||
|
||||
@group
|
||||
;; Anchor the child with the beginning of its parent.
|
||||
(compound_expression . (_) @@first-child)
|
||||
(compound_expression :anchor (_) @@first-child)
|
||||
@end group
|
||||
|
||||
@group
|
||||
;; Anchor two adjacent children.
|
||||
(compound_expression
|
||||
(_) @@prev-child
|
||||
.
|
||||
:anchor
|
||||
(_) @@next-child)
|
||||
@end group
|
||||
@end example
|
||||
|
@ -1332,8 +1331,8 @@ example, with the following pattern:
|
|||
@example
|
||||
@group
|
||||
(
|
||||
(array . (_) @@first (_) @@last .)
|
||||
(#equal @@first @@last)
|
||||
(array :anchor (_) @@first (_) @@last :anchor)
|
||||
(:equal @@first @@last)
|
||||
)
|
||||
@end group
|
||||
@end example
|
||||
|
@ -1341,22 +1340,22 @@ example, with the following pattern:
|
|||
@noindent
|
||||
tree-sitter only matches arrays where the first element is equal to
|
||||
the last element. To attach a predicate to a pattern, we need to
|
||||
group them together. A predicate always starts with a @samp{#}.
|
||||
Currently there are three predicates: @code{#equal}, @code{#match},
|
||||
and @code{#pred}.
|
||||
group them together. Currently there are three predicates:
|
||||
@code{:equal}, @code{:match}, and @code{:pred}.
|
||||
|
||||
@deffn Predicate equal arg1 arg2
|
||||
@deffn Predicate :equal arg1 arg2
|
||||
Matches if @var{arg1} is equal to @var{arg2}. Arguments can be either
|
||||
strings or capture names. Capture names represent the text that the
|
||||
captured node spans in the buffer.
|
||||
@end deffn
|
||||
|
||||
@deffn Predicate match regexp capture-name
|
||||
@deffn Predicate :match regexp capture-name
|
||||
Matches if the text that @var{capture-name}'s node spans in the buffer
|
||||
matches regular expression @var{regexp}. Matching is case-sensitive.
|
||||
matches regular expression @var{regexp}, given as a string literal.
|
||||
Matching is case-sensitive.
|
||||
@end deffn
|
||||
|
||||
@deffn Predicate pred fn &rest nodes
|
||||
@deffn Predicate :pred fn &rest nodes
|
||||
Matches if function @var{fn} returns non-@code{nil} when passed each
|
||||
node in @var{nodes} as arguments. The function runs with the current
|
||||
buffer set to the buffer of node being queried.
|
||||
|
@ -1366,28 +1365,13 @@ Note that a predicate can only refer to capture names that appear in
|
|||
the same pattern. Indeed, it makes little sense to refer to capture
|
||||
names in other patterns.
|
||||
|
||||
@heading S-expression patterns
|
||||
@heading String patterns
|
||||
|
||||
@cindex tree-sitter patterns as sexps
|
||||
@cindex patterns, tree-sitter, in sexp form
|
||||
Besides strings, Emacs provides an s-expression based syntax for
|
||||
tree-sitter patterns. It largely resembles the string-based syntax.
|
||||
For example, the following query
|
||||
|
||||
@example
|
||||
@group
|
||||
(treesit-query-capture
|
||||
node "(addition_expression
|
||||
left: (_) @@left
|
||||
\"+\" @@plus-sign
|
||||
right: (_) @@right) @@addition
|
||||
|
||||
[\"return\" \"break\"] @@keyword")
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
is equivalent to
|
||||
@cindex tree-sitter patterns as strings
|
||||
@cindex patterns, tree-sitter, in string form
|
||||
Besides s-expressions, Emacs allows the tree-sitter's native query
|
||||
syntax to be used by writing them as strings. It largely resembles
|
||||
the s-expression syntax. For example, the following query
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -1401,36 +1385,40 @@ is equivalent to
|
|||
@end group
|
||||
@end example
|
||||
|
||||
Most patterns can be written directly as strange but nevertheless
|
||||
valid s-expressions. Only a few of them need modification:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Anchor @samp{.} is written as @code{:anchor}.
|
||||
@item
|
||||
@samp{?} is written as @samp{:?}.
|
||||
@item
|
||||
@samp{*} is written as @samp{:*}.
|
||||
@item
|
||||
@samp{+} is written as @samp{:+}.
|
||||
@item
|
||||
@code{#equal} is written as @code{:equal}. In general, predicates
|
||||
change their @samp{#} to @samp{:}.
|
||||
@end itemize
|
||||
|
||||
For example,
|
||||
@noindent
|
||||
is equivalent to
|
||||
|
||||
@example
|
||||
@group
|
||||
"(
|
||||
(compound_expression . (_) @@first (_)* @@rest)
|
||||
(#match \"love\" @@first)
|
||||
)"
|
||||
(treesit-query-capture
|
||||
node "(addition_expression
|
||||
left: (_) @@left
|
||||
\"+\" @@plus-sign
|
||||
right: (_) @@right) @@addition
|
||||
|
||||
[\"return\" \"break\"] @@keyword")
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
is written in s-expression syntax as
|
||||
Most patterns can be written directly as s-expressions inside a string.
|
||||
Only a few of them need modification:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
Anchor @code{:anchor} is written as @samp{.}.
|
||||
@item
|
||||
@samp{:?} is written as @samp{?}.
|
||||
@item
|
||||
@samp{:*} is written as @samp{*}.
|
||||
@item
|
||||
@samp{:+} is written as @samp{+}.
|
||||
@item
|
||||
@code{:equal}, @code{:match} and @code{:pred} are written as
|
||||
@code{#equal}, @code{#match} and @code{#pred}, respectively.
|
||||
In general, predicates change their @samp{:} to @samp{#}.
|
||||
@end itemize
|
||||
|
||||
For example,
|
||||
|
||||
@example
|
||||
@group
|
||||
|
@ -1441,6 +1429,18 @@ is written in s-expression syntax as
|
|||
@end group
|
||||
@end example
|
||||
|
||||
@noindent
|
||||
is written in string form as
|
||||
|
||||
@example
|
||||
@group
|
||||
"(
|
||||
(compound_expression . (_) @@first (_)* @@rest)
|
||||
(#match \"love\" @@first)
|
||||
)"
|
||||
@end group
|
||||
@end example
|
||||
|
||||
@heading Compiling queries
|
||||
|
||||
@cindex compiling tree-sitter queries
|
||||
|
@ -1461,7 +1461,7 @@ validate and debug the query.
|
|||
@end defun
|
||||
|
||||
@defun treesit-query-language query
|
||||
This function return the language of @var{query}.
|
||||
This function returns the language of @var{query}.
|
||||
@end defun
|
||||
|
||||
@defun treesit-query-expand query
|
||||
|
@ -1653,7 +1653,7 @@ ranges for @acronym{CSS} and JavaScript parsers:
|
|||
(setq css-range
|
||||
(treesit-query-range
|
||||
'html
|
||||
"(style_element (raw_text) @@capture)"))
|
||||
'((style_element (raw_text) @@capture))))
|
||||
(treesit-parser-set-included-ranges css css-range)
|
||||
@end group
|
||||
|
||||
|
@ -1662,7 +1662,7 @@ ranges for @acronym{CSS} and JavaScript parsers:
|
|||
(setq js-range
|
||||
(treesit-query-range
|
||||
'html
|
||||
"(script_element (raw_text) @@capture)"))
|
||||
'((script_element (raw_text) @@capture))))
|
||||
(treesit-parser-set-included-ranges js js-range)
|
||||
@end group
|
||||
@end example
|
||||
|
|
|
@ -115,6 +115,21 @@ web page hit @kbd{g} (@code{eww-reload}).
|
|||
@kbd{w} calls @code{eww-copy-page-url}, which will copy the current
|
||||
page's URL to the kill ring instead.
|
||||
|
||||
@findex eww-copy-alternate-url
|
||||
@kindex A
|
||||
The @kbd{A} command (@code{eww-copy-alternate-url}) copies the URL
|
||||
of an alternate link on the current page into the kill ring. If the
|
||||
page specifies multiple alternate links, this command prompts for one
|
||||
of them in the minibuffer, with completion. Alternate links are
|
||||
references that an @acronym{HTML} page may include to point to other
|
||||
documents that act as its alternative representations. Notably,
|
||||
@acronym{HTML} pages can use alternate links to point to their
|
||||
translated versions and to @acronym{RSS} feeds. Alternate links
|
||||
appear in the @samp{<head>} section of @acronym{HTML} pages as
|
||||
@samp{<link>} elements with @samp{rel} attribute equal to
|
||||
@samp{``alternate''}; they are part of the page's metadata and are not
|
||||
visible in its rendered content.
|
||||
|
||||
@findex eww-open-in-new-buffer
|
||||
@kindex M-RET
|
||||
The @kbd{M-@key{RET}} command (@code{eww-open-in-new-buffer}) opens the
|
||||
|
|
1370
etc/AUTHORS
1370
etc/AUTHORS
File diff suppressed because it is too large
Load diff
7
etc/NEWS
7
etc/NEWS
|
@ -283,6 +283,13 @@ The interactive minibuffer prompt when invoking 'eww' now provides
|
|||
completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes
|
||||
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.
|
||||
|
||||
** go-ts-mode
|
||||
|
||||
+++
|
||||
|
|
33
etc/PROBLEMS
33
etc/PROBLEMS
|
@ -3492,6 +3492,39 @@ See
|
|||
|
||||
https://lists.gnu.org/r/emacs-devel/2010-07/msg01266.html
|
||||
|
||||
*** Building the MS-Windows port with native compilation fails
|
||||
|
||||
This is known to happen when using MinGW64 GCC 13.1, and seems to
|
||||
affect byte-compilation: the built Emacs crashes while byte-compiling
|
||||
some Lisp files. (This doesn't happen when building a release
|
||||
tarball, because all the Lisp files are already byte-compiled there,
|
||||
but then Emacs could crash later when you use it to byte-compile your
|
||||
or third-party Lisp packages.)
|
||||
|
||||
The reason seems to be specific to MS-Windows or the MinGW64 port of
|
||||
GCC 13.1, and is somehow related to optimizations in this GCC version.
|
||||
There are several known workarounds:
|
||||
|
||||
. Use non-default optimization flags. For example, configuring the
|
||||
build like this will avoid the problem:
|
||||
|
||||
CFLAGS='-O1 -gdwarf-4 -g3' ./configure ...
|
||||
|
||||
(replace the ellipsis "..." with the rest of 'configure' options
|
||||
and arguments).
|
||||
|
||||
. Prevent GCC from performing a specific optimization:
|
||||
|
||||
CFLAGS='-O2 -gdwarf-4 -g3 -fno-optimize-sibling-calls' ./configure ...
|
||||
|
||||
This is actually a variant of the previous workaround, except that
|
||||
it allows you to have almost the full set of optimizations used by
|
||||
-O2.
|
||||
|
||||
. Downgrade to GCC 12.x.
|
||||
|
||||
. Build Emacs without native compilation.
|
||||
|
||||
*** Building the native MS-Windows port fails due to unresolved externals
|
||||
|
||||
The linker error messages look like this:
|
||||
|
|
|
@ -437,6 +437,42 @@ ifeq ($(HAVE_NATIVE_COMP),yes)
|
|||
$(emacs) -l comp -f comp-compile-all-trampolines
|
||||
endif
|
||||
|
||||
.PHONY: compile-eln-targets compile-eln-aot
|
||||
|
||||
# ELNDONE is defined by ../src/Makefile, as the list of preloaded
|
||||
# *.eln files, which are therefore already compiled by the time
|
||||
# compile-eln-aot is called.
|
||||
ifeq ($(NATIVE_COMPILATION_AOT),yes)
|
||||
%.eln: %.el
|
||||
$(AM_V_ELN)$(emacs) $(BYTE_COMPILE_FLAGS) \
|
||||
-l comp -f byte-compile-refresh-preloaded \
|
||||
--eval '(batch-native-compile t)' $<
|
||||
|
||||
compile-eln-targets: $(filter-out $(ELNDONE),$(TARGETS))
|
||||
else
|
||||
compile-eln-targets:
|
||||
endif
|
||||
|
||||
# This is called from ../src/Makefile when building a release tarball
|
||||
# configured --with-native-compilation=aot.
|
||||
compile-eln-aot:
|
||||
@(cd $(lisp) && \
|
||||
els=`echo "${SUBDIRS_REL} " | sed -e 's|/\./|/|g' -e 's|/\. | |g' -e 's| |/*.el |g'`; \
|
||||
for el in $$els; do \
|
||||
test -f $$el || continue; \
|
||||
test -f $${el}c || continue; \
|
||||
GREP_OPTIONS= grep '^;.*[^a-zA-Z]no-byte-compile: *t' $$el > /dev/null && \
|
||||
continue; \
|
||||
GREP_OPTIONS= grep '^;.*[^a-zA-Z]no-native-compile: *t' $$el > /dev/null && \
|
||||
continue; \
|
||||
echo "$${el}n"; \
|
||||
done | xargs $(XARGS_LIMIT) echo) | \
|
||||
while read chunk; do \
|
||||
$(MAKE) compile-eln-targets \
|
||||
TARGETS="$$chunk" ELNDONE="$(ELNDONE)"; \
|
||||
done
|
||||
|
||||
|
||||
.PHONY: backup-compiled-files compile-after-backup
|
||||
|
||||
# Backup compiled Lisp files in elc.tar.gz. If that file already
|
||||
|
|
|
@ -167,8 +167,8 @@ Earlier variables shadow later ones with the same name.")
|
|||
((or `(lambda . ,_) `(closure . ,_))
|
||||
;; While byte-compile-unfold-bcf can inline dynbind byte-code into
|
||||
;; letbind byte-code (or any other combination for that matter), we
|
||||
;; can only inline dynbind source into dynbind source or letbind
|
||||
;; source into letbind source.
|
||||
;; can only inline dynbind source into dynbind source or lexbind
|
||||
;; source into lexbind source.
|
||||
;; When the function comes from another file, we byte-compile
|
||||
;; the inlined function first, and then inline its byte-code.
|
||||
;; This also has the advantage that the final code does not
|
||||
|
@ -176,7 +176,10 @@ Earlier variables shadow later ones with the same name.")
|
|||
;; the build more reproducible.
|
||||
(if (eq fn localfn)
|
||||
;; From the same file => same mode.
|
||||
(macroexp--unfold-lambda `(,fn ,@(cdr form)))
|
||||
(let* ((newform `(,fn ,@(cdr form)))
|
||||
(unfolded (macroexp--unfold-lambda newform)))
|
||||
;; Use the newform only if it could be optimized.
|
||||
(if (eq unfolded newform) form unfolded))
|
||||
;; Since we are called from inside the optimizer, we need to make
|
||||
;; sure not to propagate lexvar values.
|
||||
(let ((byte-optimize--lexvars nil)
|
||||
|
@ -452,13 +455,6 @@ for speeding up processing.")
|
|||
`(progn ,@(byte-optimize-body env t))
|
||||
`(,fn ,vars ,(mapcar #'byte-optimize-form env) . ,rest)))
|
||||
|
||||
(`((lambda . ,_) . ,_)
|
||||
(let ((newform (macroexp--unfold-lambda form)))
|
||||
(if (eq newform form)
|
||||
;; Some error occurred, avoid infinite recursion.
|
||||
form
|
||||
(byte-optimize-form newform for-effect))))
|
||||
|
||||
(`(setq ,var ,expr)
|
||||
(let ((lexvar (assq var byte-optimize--lexvars))
|
||||
(value (byte-optimize-form expr nil)))
|
||||
|
@ -1412,15 +1408,15 @@ See Info node `(elisp) Integer Basics'."
|
|||
|
||||
|
||||
(defun byte-optimize-funcall (form)
|
||||
;; (funcall #'(lambda ...) ...) -> ((lambda ...) ...)
|
||||
;; (funcall #'(lambda ...) ...) -> (let ...)
|
||||
;; (funcall #'SYM ...) -> (SYM ...)
|
||||
;; (funcall 'SYM ...) -> (SYM ...)
|
||||
(let* ((fn (nth 1 form))
|
||||
(head (car-safe fn)))
|
||||
(if (or (eq head 'function)
|
||||
(and (eq head 'quote) (symbolp (nth 1 fn))))
|
||||
(cons (nth 1 fn) (cdr (cdr form)))
|
||||
form)))
|
||||
(pcase form
|
||||
(`(,_ #'(lambda . ,_) . ,_)
|
||||
(macroexp--unfold-lambda form))
|
||||
(`(,_ ,(or `#',f `',(and f (pred symbolp))) . ,actuals)
|
||||
`(,f ,@actuals))
|
||||
(_ form)))
|
||||
|
||||
(defun byte-optimize-apply (form)
|
||||
(let ((len (length form)))
|
||||
|
|
|
@ -3556,12 +3556,6 @@ lambda-expression."
|
|||
((and (byte-code-function-p (car form))
|
||||
(memq byte-optimize '(t lap)))
|
||||
(byte-compile-unfold-bcf form))
|
||||
((and (eq (car-safe (car form)) 'lambda)
|
||||
;; if the form comes out the same way it went in, that's
|
||||
;; because it was malformed, and we couldn't unfold it.
|
||||
(not (eq form (setq form (macroexp--unfold-lambda form)))))
|
||||
(byte-compile-form form byte-compile--for-effect)
|
||||
(setq byte-compile--for-effect nil))
|
||||
((byte-compile-normal-call form)))
|
||||
(if byte-compile--for-effect
|
||||
(byte-compile-discard))
|
||||
|
|
|
@ -245,17 +245,18 @@ The name is made by appending a number to PREFIX, default \"T\"."
|
|||
|
||||
(defun cl--slet (bindings body)
|
||||
"Like `cl--slet*' but for \"parallel let\"."
|
||||
(cond
|
||||
((seq-some (lambda (binding) (macroexp--dynamic-variable-p (car binding)))
|
||||
bindings)
|
||||
;; FIXME: We use `identity' to obfuscate the code enough to
|
||||
;; circumvent the known bug in `macroexp--unfold-lambda' :-(
|
||||
`(funcall (identity (lambda (,@(mapcar #'car bindings))
|
||||
,@(macroexp-unprogn body)))
|
||||
,@(mapcar #'cadr bindings)))
|
||||
((null (cdr bindings))
|
||||
(macroexp-let* bindings body))
|
||||
(t `(let ,bindings ,@(macroexp-unprogn body)))))
|
||||
(let ((dyn nil)) ;Is there a var declared as dynbound among the bindings?
|
||||
;; `seq-some' lead to bootstrap problems.
|
||||
(dolist (binding bindings)
|
||||
(if (macroexp--dynamic-variable-p (car binding)) (setq dyn t)))
|
||||
(cond
|
||||
(dyn
|
||||
`(funcall (lambda (,@(mapcar #'car bindings))
|
||||
,@(macroexp-unprogn body))
|
||||
,@(mapcar #'cadr bindings)))
|
||||
((null (cdr bindings))
|
||||
(macroexp-let* bindings body))
|
||||
(t `(let ,bindings ,@(macroexp-unprogn body))))))
|
||||
|
||||
(defun cl--slet* (bindings body)
|
||||
"Like `macroexp-let*' but uses static scoping for all the BINDINGS."
|
||||
|
|
|
@ -63,16 +63,19 @@ redefine OBJECT if it is a symbol."
|
|||
(list (intern (completing-read (format-prompt "Disassemble function" fn)
|
||||
obarray 'fboundp t nil nil def))
|
||||
nil 0 t)))
|
||||
(if (and (consp object) (not (functionp object)))
|
||||
(setq object `(lambda () ,object)))
|
||||
(or indent (setq indent 0)) ;Default indent to zero
|
||||
(save-excursion
|
||||
(if (or interactive-p (null buffer))
|
||||
(with-output-to-temp-buffer "*Disassemble*"
|
||||
(set-buffer "*Disassemble*")
|
||||
(disassemble-internal object indent (not interactive-p)))
|
||||
(set-buffer buffer)
|
||||
(disassemble-internal object indent nil)))
|
||||
(let ((lb lexical-binding))
|
||||
(if (and (consp object) (not (functionp object)))
|
||||
(setq object `(lambda () ,object)))
|
||||
(or indent (setq indent 0)) ;Default indent to zero
|
||||
(save-excursion
|
||||
(if (or interactive-p (null buffer))
|
||||
(with-output-to-temp-buffer "*Disassemble*"
|
||||
(set-buffer "*Disassemble*")
|
||||
(let ((lexical-binding lb))
|
||||
(disassemble-internal object indent (not interactive-p))))
|
||||
(set-buffer buffer)
|
||||
(let ((lexical-binding lb))
|
||||
(disassemble-internal object indent nil)))))
|
||||
nil)
|
||||
|
||||
(declare-function native-comp-unit-file "data.c")
|
||||
|
|
|
@ -453,14 +453,17 @@ TURN-ON is a function that will be called with no args in every buffer
|
|||
and that should try to turn MODE on if applicable for that buffer.
|
||||
|
||||
Each of KEY VALUE is a pair of CL-style keyword arguments.
|
||||
The :predicate argument specifies in which major modes should the
|
||||
The :predicate key specifies in which major modes should the
|
||||
globalized minor mode be switched on. The value should be t (meaning
|
||||
switch on the minor mode in all major modes), nil (meaning don't
|
||||
switch on in any major mode), a list of modes (meaning switch on only
|
||||
in those modes and their descendants), or a list (not MODES...),
|
||||
meaning switch on in any major mode except MODES. The value can also
|
||||
mix all of these forms, see the info node `Defining Minor Modes' for
|
||||
details.
|
||||
details. The :predicate key causes the macro to create a user option
|
||||
named the same as MODE, but ending with \"-modes\" instead of \"-mode\".
|
||||
That user option can then be used to customize in which modes this
|
||||
globalized minor mode will be switched on.
|
||||
As the minor mode defined by this function is always global, any
|
||||
:global keyword is ignored.
|
||||
Other keywords have the same meaning as in `define-minor-mode',
|
||||
|
|
|
@ -407,7 +407,7 @@ The search is done in the source for library LIBRARY."
|
|||
(setq library (substring library 0 (match-beginning 1))))
|
||||
;; Strip extension from .emacs.el to make sure symbol is searched in
|
||||
;; .emacs too.
|
||||
(when (string-match "\\.emacs\\(.el\\)" library)
|
||||
(when (string-match "\\.emacs\\(.el\\)\\'" library)
|
||||
(setq library (substring library 0 (match-beginning 1))))
|
||||
(let* ((filename (find-library-name library))
|
||||
(regexp-symbol (cdr (assq type find-function-regexp-alist))))
|
||||
|
|
|
@ -244,68 +244,64 @@ It should normally be a symbol with position and it defaults to FORM."
|
|||
new-form)))
|
||||
|
||||
(defun macroexp--unfold-lambda (form &optional name)
|
||||
;; In lexical-binding mode, let and functions don't bind vars in the same way
|
||||
;; (let obey special-variable-p, but functions don't). But luckily, this
|
||||
;; doesn't matter here, because function's behavior is underspecified so it
|
||||
;; can safely be turned into a `let', even though the reverse is not true.
|
||||
(or name (setq name "anonymous lambda"))
|
||||
(let* ((lambda (car form))
|
||||
(values (cdr form))
|
||||
(arglist (nth 1 lambda))
|
||||
(body (cdr (cdr lambda)))
|
||||
optionalp restp
|
||||
bindings)
|
||||
(if (and (stringp (car body)) (cdr body))
|
||||
(setq body (cdr body)))
|
||||
(if (and (consp (car body)) (eq 'interactive (car (car body))))
|
||||
(setq body (cdr body)))
|
||||
;; FIXME: The checks below do not belong in an optimization phase.
|
||||
(while arglist
|
||||
(cond ((eq (car arglist) '&optional)
|
||||
;; ok, I'll let this slide because funcall_lambda() does...
|
||||
;; (if optionalp (error "Multiple &optional keywords in %s" name))
|
||||
(if restp (error "&optional found after &rest in %s" name))
|
||||
(if (null (cdr arglist))
|
||||
(error "Nothing after &optional in %s" name))
|
||||
(setq optionalp t))
|
||||
((eq (car arglist) '&rest)
|
||||
;; ...but it is by no stretch of the imagination a reasonable
|
||||
;; thing that funcall_lambda() allows (&rest x y) and
|
||||
;; (&rest x &optional y) in arglists.
|
||||
(if (null (cdr arglist))
|
||||
(error "Nothing after &rest in %s" name))
|
||||
(if (cdr (cdr arglist))
|
||||
(error "Multiple vars after &rest in %s" name))
|
||||
(setq restp t))
|
||||
(restp
|
||||
(setq bindings (cons (list (car arglist)
|
||||
(and values (cons 'list values)))
|
||||
bindings)
|
||||
values nil))
|
||||
((and (not optionalp) (null values))
|
||||
(setq arglist nil values 'too-few))
|
||||
(t
|
||||
(setq bindings (cons (list (car arglist) (car values))
|
||||
bindings)
|
||||
values (cdr values))))
|
||||
(setq arglist (cdr arglist)))
|
||||
(if values
|
||||
(macroexp-warn-and-return
|
||||
(format-message
|
||||
(if (eq values 'too-few)
|
||||
"attempt to open-code `%s' with too few arguments"
|
||||
"attempt to open-code `%s' with too many arguments")
|
||||
name)
|
||||
form nil nil arglist)
|
||||
|
||||
;; The following leads to infinite recursion when loading a
|
||||
;; file containing `(defsubst f () (f))', and then trying to
|
||||
;; byte-compile that file.
|
||||
;;(setq body (mapcar 'byte-optimize-form body)))
|
||||
|
||||
(if bindings
|
||||
`(let ,(nreverse bindings) . ,body)
|
||||
(macroexp-progn body)))))
|
||||
(pcase form
|
||||
((or `(funcall (function ,lambda) . ,actuals) `(,lambda . ,actuals))
|
||||
(let* ((formals (nth 1 lambda))
|
||||
(body (cdr (macroexp-parse-body (cddr lambda))))
|
||||
optionalp restp
|
||||
(dynboundarg nil)
|
||||
bindings)
|
||||
;; FIXME: The checks below do not belong in an optimization phase.
|
||||
(while formals
|
||||
(if (macroexp--dynamic-variable-p (car formals))
|
||||
(setq dynboundarg t))
|
||||
(cond ((eq (car formals) '&optional)
|
||||
;; ok, I'll let this slide because funcall_lambda() does...
|
||||
;; (if optionalp (error "Multiple &optional keywords in %s" name))
|
||||
(if restp (error "&optional found after &rest in %s" name))
|
||||
(if (null (cdr formals))
|
||||
(error "Nothing after &optional in %s" name))
|
||||
(setq optionalp t))
|
||||
((eq (car formals) '&rest)
|
||||
;; ...but it is by no stretch of the imagination a reasonable
|
||||
;; thing that funcall_lambda() allows (&rest x y) and
|
||||
;; (&rest x &optional y) in formalss.
|
||||
(if (null (cdr formals))
|
||||
(error "Nothing after &rest in %s" name))
|
||||
(if (cdr (cdr formals))
|
||||
(error "Multiple vars after &rest in %s" name))
|
||||
(setq restp t))
|
||||
(restp
|
||||
(setq bindings (cons (list (car formals)
|
||||
(and actuals (cons 'list actuals)))
|
||||
bindings)
|
||||
actuals nil))
|
||||
((and (not optionalp) (null actuals))
|
||||
(setq formals nil actuals 'too-few))
|
||||
(t
|
||||
(setq bindings (cons (list (car formals) (car actuals))
|
||||
bindings)
|
||||
actuals (cdr actuals))))
|
||||
(setq formals (cdr formals)))
|
||||
(cond
|
||||
(actuals
|
||||
(macroexp-warn-and-return
|
||||
(format-message
|
||||
(if (eq actuals 'too-few)
|
||||
"attempt to open-code `%s' with too few arguments"
|
||||
"attempt to open-code `%s' with too many arguments")
|
||||
name)
|
||||
form nil nil formals))
|
||||
;; In lexical-binding mode, let and functions don't bind vars in
|
||||
;; the same way (let obey special-variable-p, but functions
|
||||
;; don't). So if one of the vars is declared as dynamically scoped, we
|
||||
;; can't just convert the call to `let'.
|
||||
;; FIXME: We should α-rename the affected args and then use `let'.
|
||||
(dynboundarg form)
|
||||
(bindings `(let ,(nreverse bindings) . ,body))
|
||||
(t (macroexp-progn body)))))
|
||||
(_ (error "Not an unfoldable form: %S" form))))
|
||||
|
||||
(defun macroexp--dynamic-variable-p (var)
|
||||
"Whether the variable VAR is dynamically scoped.
|
||||
|
@ -437,27 +433,22 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
(setq args (cddr args)))
|
||||
(cons 'progn (nreverse assignments))))))
|
||||
(`(,(and fun `(lambda . ,_)) . ,args)
|
||||
;; Embedded lambda in function position.
|
||||
;; If the byte-optimizer is loaded, try to unfold this,
|
||||
;; i.e. rewrite it to (let (<args>) <body>). We'd do it in the optimizer
|
||||
;; anyway, but doing it here (i.e. earlier) can sometimes avoid the
|
||||
;; creation of a closure, thus resulting in much better code.
|
||||
(let ((newform (macroexp--unfold-lambda form)))
|
||||
(if (eq newform form)
|
||||
;; Unfolding failed for some reason, avoid infinite recursion.
|
||||
(macroexp--cons (macroexp--all-forms fun 2)
|
||||
(macroexp--all-forms args)
|
||||
form)
|
||||
(macroexp--expand-all newform))))
|
||||
(macroexp--cons (macroexp--all-forms fun 2)
|
||||
(macroexp--all-forms args)
|
||||
form))
|
||||
(`(funcall ,exp . ,args)
|
||||
(let ((eexp (macroexp--expand-all exp))
|
||||
(eargs (macroexp--all-forms args)))
|
||||
;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
|
||||
;; has a compiler-macro, or to unfold it.
|
||||
(pcase eexp
|
||||
;; Rewrite (funcall #'foo bar) to (foo bar), in case `foo'
|
||||
;; has a compiler-macro, or to unfold it.
|
||||
((and `#',f
|
||||
(guard (not (or (special-form-p f) (macrop f))))) ;; bug#46636
|
||||
(guard (and (symbolp f)
|
||||
;; bug#46636
|
||||
(not (or (special-form-p f) (macrop f))))))
|
||||
(macroexp--expand-all `(,f . ,eargs)))
|
||||
(`#'(lambda . ,_)
|
||||
(macroexp--unfold-lambda `(,fn ,eexp . ,eargs)))
|
||||
(_ `(,fn ,eexp . ,eargs)))))
|
||||
(`(funcall . ,_) form) ;bug#53227
|
||||
(`(,func . ,_)
|
||||
|
|
|
@ -187,8 +187,10 @@ A FUNC form can have any number of `:no-eval' (or `:no-value'),
|
|||
:eval (format "This number is %d" 4))
|
||||
"Manipulating Strings"
|
||||
(substring
|
||||
:eval (substring "foobar" 0 3)
|
||||
:eval (substring "foobar" 3))
|
||||
:eval (substring "abcde" 1 3)
|
||||
:eval (substring "abcde" 2)
|
||||
:eval (substring "abcde" 1 -1)
|
||||
:eval (substring "abcde" -4 4))
|
||||
(string-limit
|
||||
:eval (string-limit "foobar" 3)
|
||||
:eval (string-limit "foobar" 3 t)
|
||||
|
|
|
@ -715,11 +715,21 @@ for use at QPOS."
|
|||
"Text properties added to the text shown by `minibuffer-message'.")
|
||||
|
||||
(defun minibuffer-message (message &rest args)
|
||||
"Temporarily display MESSAGE at the end of the minibuffer.
|
||||
The text is displayed for `minibuffer-message-timeout' seconds,
|
||||
or until the next input event arrives, whichever comes first.
|
||||
Enclose MESSAGE in [...] if this is not yet the case.
|
||||
If ARGS are provided, then pass MESSAGE through `format-message'."
|
||||
"Temporarily display MESSAGE at the end of minibuffer text.
|
||||
This function is designed to be called from the minibuffer, i.e.,
|
||||
when Emacs prompts the user for some input, and the user types
|
||||
into the minibuffer. If called when the current buffer is not
|
||||
the minibuffer, this function just calls `message', and thus
|
||||
displays MESSAGE in the echo-area.
|
||||
When called from the minibuffer, this function displays MESSAGE
|
||||
at the end of minibuffer text for `minibuffer-message-timeout'
|
||||
seconds, or until the next input event arrives, whichever comes first.
|
||||
It encloses MESSAGE in [...] if it is not yet enclosed.
|
||||
The intent is to show the message without hiding what the user typed.
|
||||
If ARGS are provided, then the function first passes MESSAGE
|
||||
through `format-message'.
|
||||
If some of the minibuffer text has the `minibuffer-message' text
|
||||
property, MESSAGE is shown at that position instead of EOB."
|
||||
(if (not (minibufferp (current-buffer) t))
|
||||
(progn
|
||||
(if args
|
||||
|
@ -796,7 +806,7 @@ The minibuffer message functions include `minibuffer-message' and
|
|||
(next-single-property-change pt 'minibuffer-message nil (point-max)))))
|
||||
|
||||
(defun set-minibuffer-message (message)
|
||||
"Temporarily display MESSAGE at the end of the minibuffer.
|
||||
"Temporarily display MESSAGE at the end of the active minibuffer window.
|
||||
If some part of the minibuffer text has the `minibuffer-message' property,
|
||||
the message will be displayed before the first such character, instead of
|
||||
at the end of the minibuffer.
|
||||
|
@ -954,7 +964,7 @@ is at its default value `grow-only'."
|
|||
multi-message-separator)))
|
||||
|
||||
(defun clear-minibuffer-message ()
|
||||
"Clear minibuffer message.
|
||||
"Clear message temporarily shown in the minibuffer.
|
||||
Intended to be called via `clear-message-function'."
|
||||
(when (not noninteractive)
|
||||
(when (timerp minibuffer-message-timer)
|
||||
|
|
|
@ -1086,6 +1086,7 @@ the like."
|
|||
"&" #'eww-browse-with-external-browser
|
||||
"d" #'eww-download
|
||||
"w" #'eww-copy-page-url
|
||||
"A" #'eww-copy-alternate-url
|
||||
"C" #'url-cookie-list
|
||||
"v" #'eww-view-source
|
||||
"R" #'eww-readable
|
||||
|
@ -2576,4 +2577,83 @@ Otherwise, the restored buffer will contain a prompt to do so by using
|
|||
|
||||
(provide 'eww)
|
||||
|
||||
;;; Alternate links (RSS and Atom feeds, etc.)
|
||||
|
||||
(defun eww--alternate-urls (dom &optional base)
|
||||
"Return an alist of alternate links in DOM.
|
||||
|
||||
Each element is a list of the form (URL TYPE TITLE) where URL is
|
||||
the href attribute of the link expanded relative to BASE, TYPE is
|
||||
its type attribute, and TITLE is its title attribute. If any of
|
||||
these attributes is absent, the corresponding element is nil."
|
||||
(let ((alternates
|
||||
(seq-filter
|
||||
(lambda (attrs) (string= (alist-get 'rel attrs)
|
||||
"alternate"))
|
||||
(mapcar #'dom-attributes (dom-by-tag dom 'link)))))
|
||||
(mapcar (lambda (alternate)
|
||||
(list (url-expand-file-name (alist-get 'href alternate)
|
||||
base)
|
||||
(alist-get 'type alternate)
|
||||
(alist-get 'title alternate)))
|
||||
alternates)))
|
||||
|
||||
(defun eww-read-alternate-url ()
|
||||
"Get the URL of an alternate link of this page.
|
||||
|
||||
If there is just one alternate link, return its URL. If there
|
||||
are multiple alternate links, prompt for one in the minibuffer
|
||||
with completion. If there are none, return nil."
|
||||
(when-let ((alternates (eww--alternate-urls
|
||||
(plist-get eww-data :dom)
|
||||
(plist-get eww-data :url))))
|
||||
(let ((url-max-width
|
||||
(seq-max (mapcar #'string-pixel-width
|
||||
(mapcar #'car alternates))))
|
||||
(title-max-width
|
||||
(seq-max (mapcar #'string-pixel-width
|
||||
(mapcar #'caddr alternates))))
|
||||
(sep-width (string-pixel-width " ")))
|
||||
(if (cdr alternates)
|
||||
(let ((completion-extra-properties
|
||||
(list :annotation-function
|
||||
(lambda (feed)
|
||||
(let* ((attrs (alist-get feed
|
||||
alternates
|
||||
nil
|
||||
nil
|
||||
#'string=))
|
||||
(type (car attrs))
|
||||
(title (cadr attrs)))
|
||||
(concat
|
||||
(propertize " " 'display
|
||||
`(space :align-to
|
||||
(,(+ sep-width
|
||||
url-max-width))))
|
||||
title
|
||||
(when type
|
||||
(concat
|
||||
(propertize " " 'display
|
||||
`(space :align-to
|
||||
(,(+ (* 2 sep-width)
|
||||
url-max-width
|
||||
title-max-width))))
|
||||
"[" type "]"))))))))
|
||||
(completing-read "Alternate URL: " alternates nil t))
|
||||
(caar alternates)))))
|
||||
|
||||
(defun eww-copy-alternate-url ()
|
||||
"Copy the alternate URL of the current page into the kill ring.
|
||||
If there are multiple alternate links on the current page, prompt
|
||||
for one in the minibuffer, with completion.
|
||||
Alternate links are references that an HTML page may include to
|
||||
point to its alternative representations, such as a translated
|
||||
version or an RSS feed."
|
||||
(interactive nil eww-mode)
|
||||
(if-let ((url (eww-read-alternate-url)))
|
||||
(progn
|
||||
(kill-new url)
|
||||
(message "Copied %s to kill ring" url))
|
||||
(user-error "No alternate links found on this page!")))
|
||||
|
||||
;;; eww.el ends here
|
||||
|
|
|
@ -2659,7 +2659,7 @@ need for `c-font-lock-extra-types'.")
|
|||
;; prevent a repeat invocation. See elisp/lispref page "Search-based
|
||||
;; fontification".
|
||||
(let (pos)
|
||||
(while
|
||||
(while
|
||||
(and (< (point) limit)
|
||||
(c-syntactic-re-search-forward c-using-key limit 'end))
|
||||
(while ; Do one declarator of a comma separated list, each time around.
|
||||
|
|
|
@ -230,7 +230,7 @@ chosen (interactively or automatically)."
|
|||
. ,(eglot-alternatives '("digestif" "texlab")))
|
||||
(erlang-mode . ("erlang_ls" "--transport" "stdio"))
|
||||
((yaml-ts-mode yaml-mode) . ("yaml-language-server" "--stdio"))
|
||||
(nix-mode . ,(eglot-alternatives '("nil" "rnix-lsp")))
|
||||
(nix-mode . ,(eglot-alternatives '("nil" "rnix-lsp" "nixd")))
|
||||
(nickel-mode . ("nls"))
|
||||
(gdscript-mode . ("localhost" 6008))
|
||||
((fortran-mode f90-mode) . ("fortls"))
|
||||
|
@ -3769,7 +3769,7 @@ If NOERROR, return predicate, else erroring function."
|
|||
(if peg-after-p
|
||||
(make-overlay (point) (1+ (point)) nil t)
|
||||
(make-overlay (1- (point)) (point) nil nil nil)))
|
||||
(do-it (label lpad rpad i)
|
||||
(do-it (label lpad rpad i n)
|
||||
(let* ((firstp (zerop i))
|
||||
(tweak-cursor-p (and firstp peg-after-p))
|
||||
(ov (make-ov))
|
||||
|
@ -3782,18 +3782,18 @@ If NOERROR, return predicate, else erroring function."
|
|||
(1 'eglot-type-hint-face)
|
||||
(2 'eglot-parameter-hint-face)
|
||||
(_ 'eglot-inlay-hint-face))))
|
||||
(overlay-put ov 'priority i)
|
||||
(overlay-put ov 'priority (if peg-after-p i (- n i)))
|
||||
(overlay-put ov 'eglot--inlay-hint t)
|
||||
(overlay-put ov 'evaporate t)
|
||||
(overlay-put ov 'eglot--overlay t))))
|
||||
(if (stringp label) (do-it label left-pad right-pad 0)
|
||||
(if (stringp label) (do-it label left-pad right-pad 0 1)
|
||||
(cl-loop
|
||||
for i from 0 for ldetail across label
|
||||
do (eglot--dbind ((InlayHintLabelPart) value) ldetail
|
||||
(do-it value
|
||||
(and (zerop i) left-pad)
|
||||
(and (= i (1- (length label))) right-pad)
|
||||
i)))))))))
|
||||
i (length label))))))))))
|
||||
(jsonrpc-async-request
|
||||
(eglot--current-server-or-lose)
|
||||
:textDocument/inlayHint
|
||||
|
|
|
@ -453,7 +453,9 @@ valid signal handlers.")
|
|||
(const :tag "Unlimited" nil))
|
||||
:version "22.1")
|
||||
|
||||
(defcustom gdb-non-stop-setting (not (eq system-type 'windows-nt))
|
||||
;; This is disabled by default because we don't really support
|
||||
;; asynchronous execution of the debuggee; see bug#63084. FIXME.
|
||||
(defcustom gdb-non-stop-setting nil
|
||||
"If non-nil, GDB sessions are expected to support the non-stop mode.
|
||||
When in the non-stop mode, stopped threads can be examined while
|
||||
other threads continue to execute.
|
||||
|
@ -468,7 +470,7 @@ don't support the non-stop mode.
|
|||
GDB session needs to be restarted for this setting to take effect."
|
||||
:type 'boolean
|
||||
:group 'gdb-non-stop
|
||||
:version "26.1")
|
||||
:version "29.1")
|
||||
|
||||
(defcustom gdb-debuginfod-enable-setting
|
||||
;; debuginfod servers are only for ELF executables, and elfutils, of
|
||||
|
|
|
@ -80,6 +80,7 @@
|
|||
((parent-is "const_declaration") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "default_case") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "expression_case") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "selector_expression") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "expression_switch_statement") parent-bol 0)
|
||||
((parent-is "field_declaration_list") parent-bol go-ts-mode-indent-offset)
|
||||
((parent-is "import_spec_list") parent-bol go-ts-mode-indent-offset)
|
||||
|
|
|
@ -1406,6 +1406,10 @@ keyword
|
|||
- Point is inside a paren from a block start followed by some
|
||||
items on the same line.
|
||||
- START is the first non space char position *after* the open paren.
|
||||
:inside-paren-continuation-line
|
||||
- Point is on a continuation line inside a paren.
|
||||
- START is the position where the previous line (excluding lines
|
||||
for inner parens) starts.
|
||||
|
||||
:after-backslash
|
||||
- Fallback case when point is after backslash.
|
||||
|
@ -1460,7 +1464,21 @@ keyword
|
|||
(= (line-number-at-pos)
|
||||
(progn
|
||||
(python-util-forward-comment)
|
||||
(line-number-at-pos))))))))
|
||||
(line-number-at-pos)))))))
|
||||
(continuation-start
|
||||
(when start
|
||||
(save-excursion
|
||||
(forward-line -1)
|
||||
(back-to-indentation)
|
||||
;; Skip inner parens.
|
||||
(cl-loop with prev-start = (python-syntax-context 'paren)
|
||||
while (and prev-start (>= prev-start start))
|
||||
if (= prev-start start)
|
||||
return (point)
|
||||
else do (goto-char prev-start)
|
||||
(back-to-indentation)
|
||||
(setq prev-start
|
||||
(python-syntax-context 'paren)))))))
|
||||
(when start
|
||||
(cond
|
||||
;; Current line only holds the closing paren.
|
||||
|
@ -1476,6 +1494,9 @@ keyword
|
|||
(back-to-indentation)
|
||||
(python-syntax-closing-paren-p))
|
||||
(cons :inside-paren-at-closing-nested-paren start))
|
||||
;; This line is a continuation of the previous line.
|
||||
(continuation-start
|
||||
(cons :inside-paren-continuation-line continuation-start))
|
||||
;; This line starts from an opening block in its own line.
|
||||
((save-excursion
|
||||
(goto-char start)
|
||||
|
@ -1591,7 +1612,8 @@ possibilities can be narrowed to specific indentation points."
|
|||
(`(,(or :after-line
|
||||
:after-comment
|
||||
:inside-string
|
||||
:after-backslash) . ,start)
|
||||
:after-backslash
|
||||
:inside-paren-continuation-line) . ,start)
|
||||
;; Copy previous indentation.
|
||||
(goto-char start)
|
||||
(current-indentation))
|
||||
|
|
|
@ -1121,10 +1121,15 @@ possible values of STATE are explained in `vc-state', and MODEL in
|
|||
the returned list.
|
||||
|
||||
BEWARE: this function may change the current buffer."
|
||||
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
|
||||
(vc-deduce-fileset-1 not-state-changing
|
||||
allow-unregistered
|
||||
state-model-only-files)))
|
||||
(let (new-buf res)
|
||||
(with-current-buffer (or (buffer-base-buffer) (current-buffer))
|
||||
(setq res
|
||||
(vc-deduce-fileset-1 not-state-changing
|
||||
allow-unregistered
|
||||
state-model-only-files))
|
||||
(setq new-buf (current-buffer)))
|
||||
(set-buffer new-buf)
|
||||
res))
|
||||
|
||||
(defun vc-deduce-fileset-1 (not-state-changing
|
||||
allow-unregistered
|
||||
|
|
138
lisp/wid-edit.el
138
lisp/wid-edit.el
|
@ -284,71 +284,79 @@ The user is asked to choose between each NAME from ITEMS.
|
|||
If ITEMS has simple item definitions, then this function returns the VALUE of
|
||||
the chosen element. If ITEMS is a keymap, then the return value is the symbol
|
||||
in the key vector, as in the argument of `define-key'."
|
||||
(cond ((and (< (length items) widget-menu-max-size)
|
||||
event (display-popup-menus-p))
|
||||
;; Mouse click.
|
||||
(if (keymapp items)
|
||||
;; Modify the keymap prompt, and then restore the old one, if any.
|
||||
(let ((prompt (keymap-prompt items)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setq items (delete prompt items))
|
||||
(push title (cdr items))
|
||||
;; Return just the first element of the list of events.
|
||||
(car (x-popup-menu event items)))
|
||||
(setq items (delete title items))
|
||||
(when prompt
|
||||
(push prompt (cdr items)))))
|
||||
(x-popup-menu event (list title (cons "" items)))))
|
||||
((or widget-menu-minibuffer-flag
|
||||
(> (length items) widget-menu-max-shortcuts))
|
||||
(when (keymapp items)
|
||||
(setq items (widget--simplify-menu items)))
|
||||
;; Read the choice of name from the minibuffer.
|
||||
(setq items (cl-remove-if 'stringp items))
|
||||
(let ((val (completing-read (concat title ": ") items nil t)))
|
||||
(if (stringp val)
|
||||
(let ((try (try-completion val items)))
|
||||
(when (stringp try)
|
||||
(setq val try))
|
||||
(cdr (assoc val items))))))
|
||||
(t
|
||||
(when (keymapp items)
|
||||
(setq items (widget--simplify-menu items)))
|
||||
;; Construct a menu of the choices
|
||||
;; and then use it for prompting for a single character.
|
||||
(let* ((next-digit ?0)
|
||||
alist choice some-choice-enabled value)
|
||||
(with-current-buffer (get-buffer-create " widget-choose")
|
||||
(erase-buffer)
|
||||
(insert "Available choices:\n\n")
|
||||
(while items
|
||||
(setq choice (pop items))
|
||||
(when (consp choice)
|
||||
(let* ((name (substitute-command-keys (car choice)))
|
||||
(function (cdr choice)))
|
||||
(insert (format "%c = %s\n" next-digit name))
|
||||
(push (cons next-digit function) alist)
|
||||
(setq some-choice-enabled t)))
|
||||
;; Allocate digits to disabled alternatives
|
||||
;; so that the digit of a given alternative never varies.
|
||||
(setq next-digit (1+ next-digit)))
|
||||
(insert "\nC-g = Quit")
|
||||
(goto-char (point-min))
|
||||
(forward-line))
|
||||
(or some-choice-enabled
|
||||
(error "None of the choices is currently meaningful"))
|
||||
(save-window-excursion
|
||||
;; Select window to be able to scroll it from minibuffer
|
||||
(with-selected-window
|
||||
(display-buffer (get-buffer " widget-choose")
|
||||
'(display-buffer-in-direction
|
||||
(direction . bottom)
|
||||
(window-height . fit-window-to-buffer)))
|
||||
(setq value (read-char-choice
|
||||
(format "%s: " title)
|
||||
(mapcar #'car alist)))))
|
||||
(cdr (assoc value alist))))))
|
||||
;; Apply quote substitution to customize choice menu item text,
|
||||
;; whether it occurs in a widget buffer or in a popup menu.
|
||||
(let ((items (mapc (lambda (x)
|
||||
(when (consp x)
|
||||
(dotimes (i (1- (length x)))
|
||||
(when (char-or-string-p (nth i x))
|
||||
(setcar (nthcdr i x)
|
||||
(substitute-command-keys
|
||||
(car (nthcdr i x))))))))
|
||||
items)))
|
||||
(cond ((and (< (length items) widget-menu-max-size)
|
||||
event (display-popup-menus-p))
|
||||
;; Mouse click.
|
||||
(if (keymapp items)
|
||||
;; Modify the keymap prompt, and then restore the old one, if any.
|
||||
(let ((prompt (keymap-prompt items)))
|
||||
(unwind-protect
|
||||
(progn
|
||||
(setq items (delete prompt items))
|
||||
(push title (cdr items))
|
||||
;; Return just the first element of the list of events.
|
||||
(car (x-popup-menu event items)))
|
||||
(setq items (delete title items))
|
||||
(when prompt
|
||||
(push prompt (cdr items)))))
|
||||
(x-popup-menu event (list title (cons "" items)))))
|
||||
((or widget-menu-minibuffer-flag
|
||||
(> (length items) widget-menu-max-shortcuts))
|
||||
(when (keymapp items)
|
||||
(setq items (widget--simplify-menu items)))
|
||||
;; Read the choice of name from the minibuffer.
|
||||
(setq items (cl-remove-if 'stringp items))
|
||||
(let ((val (completing-read (concat title ": ") items nil t)))
|
||||
(if (stringp val)
|
||||
(let ((try (try-completion val items)))
|
||||
(when (stringp try)
|
||||
(setq val try))
|
||||
(cdr (assoc val items))))))
|
||||
(t
|
||||
(when (keymapp items)
|
||||
(setq items (widget--simplify-menu items)))
|
||||
;; Construct a menu of the choices
|
||||
;; and then use it for prompting for a single character.
|
||||
(let ((next-digit ?0)
|
||||
alist choice some-choice-enabled value)
|
||||
(with-current-buffer (get-buffer-create " widget-choose")
|
||||
(erase-buffer)
|
||||
(insert "Available choices:\n\n")
|
||||
(while items
|
||||
(setq choice (pop items))
|
||||
(when (consp choice)
|
||||
(insert (format "%c = %s\n" next-digit (car choice)))
|
||||
(push (cons next-digit (cdr choice)) alist)
|
||||
(setq some-choice-enabled t))
|
||||
;; Allocate digits to disabled alternatives
|
||||
;; so that the digit of a given alternative never varies.
|
||||
(setq next-digit (1+ next-digit)))
|
||||
(insert "\nC-g = Quit")
|
||||
(goto-char (point-min))
|
||||
(forward-line))
|
||||
(or some-choice-enabled
|
||||
(error "None of the choices is currently meaningful"))
|
||||
(save-window-excursion
|
||||
;; Select window to be able to scroll it from minibuffer
|
||||
(with-selected-window
|
||||
(display-buffer (get-buffer " widget-choose")
|
||||
'(display-buffer-in-direction
|
||||
(direction . bottom)
|
||||
(window-height . fit-window-to-buffer)))
|
||||
(setq value (read-char-choice
|
||||
(format "%s: " title)
|
||||
(mapcar #'car alist)))))
|
||||
(cdr (assoc value alist)))))))
|
||||
|
||||
;;; Widget text specifications.
|
||||
;;
|
||||
|
|
|
@ -933,6 +933,11 @@ elnlisp := $(addprefix ${lispsource}/,${elnlisp}) $(lisp:.elc=.eln)
|
|||
## native-lisp where the *.eln files will be produced, and the exact
|
||||
## names of those *.eln files, cannot be known in advance; we must ask
|
||||
## Emacs to produce them.
|
||||
## If AOT native compilation is requested, we additionally
|
||||
## native-compile all the *.el files in ../lisp that need to be
|
||||
## compiled and haven't yet been compiled. ELDONE holds the list
|
||||
## of *.el files that were already native-compiled.
|
||||
NATIVE_COMPILATION_AOT = @NATIVE_COMPILATION_AOT@
|
||||
../native-lisp: | $(pdmp)
|
||||
@if test ! -d $@; then \
|
||||
mkdir $@ && $(MAKE) $(AM_V_NO_PD) $(elnlisp); \
|
||||
|
@ -943,6 +948,9 @@ elnlisp := $(addprefix ${lispsource}/,${elnlisp}) $(lisp:.elc=.eln)
|
|||
--bin-dest $(BIN_DESTDIR) --eln-dest $(ELN_DESTDIR) \
|
||||
&& cp -f emacs$(EXEEXT) bootstrap-emacs$(EXEEXT) \
|
||||
&& cp -f $(pdmp) $(bootstrap_pdmp); \
|
||||
if test $(NATIVE_COMPILATION_AOT) = yes; then \
|
||||
$(MAKE) $(AM_V_NO_PD) -C ../lisp compile-eln-aot EMACS="../src/emacs$(EXEEXT)" ELNDONE="$(addprefix %,$(notdir $(elnlisp))))"; \
|
||||
fi; \
|
||||
fi
|
||||
endif
|
||||
|
||||
|
|
|
@ -4602,6 +4602,8 @@ by calling `format-decode', which see. */)
|
|||
|
||||
if (unprocessed > 0)
|
||||
{
|
||||
BUF_TEMP_SET_PT (XBUFFER (conversion_buffer),
|
||||
BUF_Z (XBUFFER (conversion_buffer)));
|
||||
coding.mode |= CODING_MODE_LAST_BLOCK;
|
||||
decode_coding_c_string (&coding, (unsigned char *) read_buf,
|
||||
unprocessed, conversion_buffer);
|
||||
|
|
50
src/frame.c
50
src/frame.c
|
@ -1464,6 +1464,10 @@ affects all frames on the same terminal device. */)
|
|||
If FRAME is a switch-frame event `(switch-frame FRAME1)', use
|
||||
FRAME1 as frame.
|
||||
|
||||
If TRACK is non-zero and the frame that currently has the focus
|
||||
redirects its focus to the selected frame, redirect that focused
|
||||
frame's focus to FRAME instead.
|
||||
|
||||
FOR_DELETION non-zero means that the selected frame is being
|
||||
deleted, which includes the possibility that the frame's terminal
|
||||
is dead.
|
||||
|
@ -1471,7 +1475,7 @@ affects all frames on the same terminal device. */)
|
|||
The value of NORECORD is passed as argument to Fselect_window. */
|
||||
|
||||
Lisp_Object
|
||||
do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord)
|
||||
do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord)
|
||||
{
|
||||
struct frame *sf = SELECTED_FRAME (), *f;
|
||||
|
||||
|
@ -1493,6 +1497,44 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord)
|
|||
else if (f == sf)
|
||||
return frame;
|
||||
|
||||
/* If the frame with GUI focus has had it's Emacs focus redirected
|
||||
toward the currently selected frame, we should change the
|
||||
redirection to point to the newly selected frame. This means
|
||||
that if the focus is redirected from a minibufferless frame to a
|
||||
surrogate minibuffer frame, we can use `other-window' to switch
|
||||
between all the frames using that minibuffer frame, and the focus
|
||||
redirection will follow us around. This code is necessary when
|
||||
we have a minibufferless frame using the MB in another (normal)
|
||||
frame (bug#64152) (ACM, 2023-06-20). */
|
||||
#ifdef HAVE_WINDOW_SYSTEM
|
||||
if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
|
||||
{
|
||||
Lisp_Object gfocus; /* The frame which still has focus on the
|
||||
current terminal, according to the GUI
|
||||
system. */
|
||||
Lisp_Object focus; /* The frame to which Emacs has redirected
|
||||
the focus from `gfocus'. This might be a
|
||||
frame with a minibuffer when `gfocus'
|
||||
doesn't have a MB. */
|
||||
|
||||
gfocus = FRAME_TERMINAL (f)->get_focus_frame (f);
|
||||
if (FRAMEP (gfocus))
|
||||
{
|
||||
focus = FRAME_FOCUS_FRAME (XFRAME (gfocus));
|
||||
if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
|
||||
/* Redirect frame focus also when FRAME has its minibuffer
|
||||
window on the selected frame (see Bug#24500).
|
||||
|
||||
Don't do that: It causes redirection problem with a
|
||||
separate minibuffer frame (Bug#24803) and problems
|
||||
when updating the cursor on such frames.
|
||||
|| (NILP (focus)
|
||||
&& EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window))) */
|
||||
Fredirect_frame_focus (gfocus, frame);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_X_WINDOWS */
|
||||
|
||||
if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
|
||||
resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
|
||||
|
||||
|
@ -1594,7 +1636,7 @@ This function returns FRAME, or nil if FRAME has been deleted. */)
|
|||
/* Do not select a tooltip frame (Bug#47207). */
|
||||
error ("Cannot select a tooltip frame");
|
||||
else
|
||||
return do_switch_frame (frame, 0, norecord);
|
||||
return do_switch_frame (frame, 1, 0, norecord);
|
||||
}
|
||||
|
||||
DEFUN ("handle-switch-frame", Fhandle_switch_frame,
|
||||
|
@ -1610,7 +1652,7 @@ necessarily represent user-visible input focus. */)
|
|||
kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
|
||||
run_hook (Qmouse_leave_buffer_hook);
|
||||
|
||||
return do_switch_frame (event, 0, Qnil);
|
||||
return do_switch_frame (event, 0, 0, Qnil);
|
||||
}
|
||||
|
||||
DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0,
|
||||
|
@ -2177,7 +2219,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
|
|||
Fraise_frame (frame1);
|
||||
#endif
|
||||
|
||||
do_switch_frame (frame1, 1, Qnil);
|
||||
do_switch_frame (frame1, 0, 1, Qnil);
|
||||
sf = SELECTED_FRAME ();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -11882,7 +11882,7 @@ quit_throw_to_read_char (bool from_signal)
|
|||
if (FRAMEP (internal_last_event_frame)
|
||||
&& !EQ (internal_last_event_frame, selected_frame))
|
||||
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
|
||||
0, Qnil);
|
||||
0, 0, Qnil);
|
||||
|
||||
sys_longjmp (getcjmp, 1);
|
||||
}
|
||||
|
|
|
@ -4888,7 +4888,7 @@ extern void syms_of_indent (void);
|
|||
/* Defined in frame.c. */
|
||||
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
|
||||
extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
|
||||
extern Lisp_Object do_switch_frame (Lisp_Object, int, Lisp_Object);
|
||||
extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
|
||||
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
|
||||
extern void frames_discard_buffer (Lisp_Object);
|
||||
extern void init_frame_once (void);
|
||||
|
|
|
@ -1125,8 +1125,8 @@ read_minibuf_unwind (void)
|
|||
found:
|
||||
if (!EQ (exp_MB_frame, saved_selected_frame)
|
||||
&& !NILP (exp_MB_frame))
|
||||
do_switch_frame (exp_MB_frame, 0, Qt); /* This also sets
|
||||
minibuf_window */
|
||||
do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
|
||||
minibuf_window */
|
||||
|
||||
/* To keep things predictable, in case it matters, let's be in the
|
||||
minibuffer when we reset the relevant variables. Don't depend on
|
||||
|
@ -1238,7 +1238,7 @@ read_minibuf_unwind (void)
|
|||
/* Restore the selected frame. */
|
||||
if (!EQ (exp_MB_frame, saved_selected_frame)
|
||||
&& !NILP (exp_MB_frame))
|
||||
do_switch_frame (saved_selected_frame, 0, Qt);
|
||||
do_switch_frame (saved_selected_frame, 0, 0, Qt);
|
||||
}
|
||||
|
||||
/* Replace the expired minibuffer in frame exp_MB_frame with the next less
|
||||
|
|
|
@ -7416,7 +7416,7 @@ the return value is nil. Otherwise the value is t. */)
|
|||
do_switch_frame (NILP (dont_set_frame)
|
||||
? data->selected_frame
|
||||
: old_frame
|
||||
, 0, Qnil);
|
||||
, 0, 0, Qnil);
|
||||
}
|
||||
|
||||
FRAME_WINDOW_CHANGE (f) = true;
|
||||
|
|
|
@ -26181,7 +26181,7 @@ x_try_restore_frame (void)
|
|||
|
||||
FOR_EACH_FRAME (tail, frame)
|
||||
{
|
||||
if (!NILP (do_switch_frame (frame, 1, Qnil)))
|
||||
if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -683,7 +683,7 @@ def long_function_name(
|
|||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(python-tests-look-at "var_four):")
|
||||
(should (eq (car (python-indent-context))
|
||||
:inside-paren-newline-start-from-block))
|
||||
:inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(python-tests-look-at "print (var_one)")
|
||||
(should (eq (car (python-indent-context))
|
||||
|
@ -707,8 +707,8 @@ foo = long_function_name(
|
|||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 4))
|
||||
(python-tests-look-at "var_three, var_four)")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 4))))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 2))))
|
||||
|
||||
(ert-deftest python-indent-hanging-close-paren ()
|
||||
"Like first pep8 case, but with hanging close paren." ;; See Bug#20742.
|
||||
|
@ -864,7 +864,7 @@ data = {
|
|||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 4))
|
||||
(python-tests-look-at "{")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 4))
|
||||
(python-tests-look-at "'objlist': [")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
|
@ -876,20 +876,20 @@ data = {
|
|||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 16))
|
||||
(python-tests-look-at "'name': 'first',")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 16))
|
||||
(python-tests-look-at "},")
|
||||
(should (eq (car (python-indent-context))
|
||||
:inside-paren-at-closing-nested-paren))
|
||||
(should (= (python-indent-calculate-indentation) 12))
|
||||
(python-tests-look-at "{")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 12))
|
||||
(python-tests-look-at "'pk': 2,")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 16))
|
||||
(python-tests-look-at "'name': 'second',")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 16))
|
||||
(python-tests-look-at "}")
|
||||
(should (eq (car (python-indent-context))
|
||||
|
@ -933,7 +933,7 @@ data = {'key': {
|
|||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 9))
|
||||
(python-tests-look-at "{'pk': 2,")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(python-tests-look-at "'name': 'second'}")
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
|
@ -966,10 +966,10 @@ data = ('these',
|
|||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 8))))
|
||||
|
||||
(ert-deftest python-indent-inside-paren-4 ()
|
||||
|
@ -1023,7 +1023,7 @@ CHOICES = (('some', 'choice'),
|
|||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 11))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 11))))
|
||||
|
||||
(ert-deftest python-indent-inside-paren-7 ()
|
||||
|
@ -1034,6 +1034,71 @@ CHOICES = (('some', 'choice'),
|
|||
;; This signals an error if the test fails
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))))
|
||||
|
||||
(ert-deftest python-indent-inside-paren-8 ()
|
||||
"Test for Bug#63959."
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
for a in [ # comment
|
||||
'some', # Manually indented.
|
||||
'thing']: # Respect indentation of the previous line.
|
||||
"
|
||||
(python-tests-look-at "for a in [ # comment")
|
||||
(should (eq (car (python-indent-context)) :no-indent))
|
||||
(should (= (python-indent-calculate-indentation) 0))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context))
|
||||
:inside-paren-newline-start-from-block))
|
||||
(should (= (python-indent-calculate-indentation) 8))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 10))))
|
||||
|
||||
(ert-deftest python-indent-inside-paren-9 ()
|
||||
"Test `:inside-paren-continuation-line'."
|
||||
(python-tests-with-temp-buffer
|
||||
"
|
||||
a = (((
|
||||
1, 2),
|
||||
3), # Do not respect the indentation of the previous line
|
||||
4) # Do not respect the indentation of the previous line
|
||||
b = ((
|
||||
1, 2), # Manually indented
|
||||
3, # Do not respect the indentation of the previous line
|
||||
4, # Respect the indentation of the previous line
|
||||
5, # Manually indented
|
||||
6) # Respect the indentation of the previous line
|
||||
"
|
||||
(python-tests-look-at "a = (((")
|
||||
(should (eq (car (python-indent-context)) :no-indent))
|
||||
(should (= (python-indent-calculate-indentation) 0))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 4))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 6))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 5))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :after-line))
|
||||
(should (= (python-indent-calculate-indentation) 0))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 4))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren))
|
||||
(should (= (python-indent-calculate-indentation) 5))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 5))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 5))
|
||||
(forward-line 1)
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 8))))
|
||||
|
||||
(ert-deftest python-indent-inside-paren-block-1 ()
|
||||
"`python-indent-block-paren-deeper' set to nil (default).
|
||||
See Bug#62696."
|
||||
|
@ -1271,7 +1336,7 @@ objects = Thing.objects.all() \\
|
|||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (= (python-indent-calculate-indentation) 27))
|
||||
(python-tests-look-at "status='bought'")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-newline-start))
|
||||
(should (eq (car (python-indent-context)) :inside-paren-continuation-line))
|
||||
(should (= (python-indent-calculate-indentation) 27))
|
||||
(python-tests-look-at ") \\")
|
||||
(should (eq (car (python-indent-context)) :inside-paren-at-closing-paren))
|
||||
|
|
Loading…
Add table
Reference in a new issue