Merge remote-tracking branch 'origin/master' into feature/android

This commit is contained in:
Po Lu 2023-02-28 18:20:25 +08:00
commit 03c0cb8671
47 changed files with 659 additions and 273 deletions

View file

@ -1556,18 +1556,26 @@ command prompts for a @dfn{library name} rather than a file name; it
searches through each directory in the Emacs Lisp load path, trying to
find a file matching that library name. If the library name is
@samp{@var{foo}}, it tries looking for files named
@file{@var{foo}.elc}, @file{@var{foo}.el}, and @file{@var{foo}}. The
default behavior is to load the first file found. This command
prefers @file{.elc} files over @file{.el} files because compiled files
load and run faster. If it finds that @file{@var{lib}.el} is newer
than @file{@var{lib}.elc}, it issues a warning, in case someone made
changes to the @file{.el} file and forgot to recompile it, but loads
the @file{.elc} file anyway. (Due to this behavior, you can save
unfinished edits to Emacs Lisp source files, and not recompile until
your changes are ready for use.) If you set the option
@code{load-prefer-newer} to a non-@code{nil} value, however, then
rather than the procedure described above, Emacs loads whichever
version of the file is newest.
@file{@var{foo}.elc}, @file{@var{foo}.el}, and @file{@var{foo}}. (If
Emacs was built with native compilation enabled, @code{load-library}
looks for a @samp{.eln} file that corresponds to @file{@var{foo}.el}
and loads it instead of @file{@var{foo}.elc}.) The default behavior
is to load the first file found. This command prefers @file{.eln}
files over @file{.elc} files, and prefers @file{.elc} files over
@file{.el} files, because compiled files load and run faster. If it
finds that @file{@var{lib}.el} is newer than @file{@var{lib}.elc}, it
issues a warning, in case someone made changes to the @file{.el} file
and forgot to recompile it, but loads the @file{.elc} file anyway.
(Due to this behavior, you can save unfinished edits to Emacs Lisp
source files, and not recompile until your changes are ready for use.)
If you set the option @code{load-prefer-newer} to a non-@code{nil}
value, however, then rather than the procedure described above, Emacs
loads whichever version of the file is newest. If Emacs was built
with native compilation, and it cannot find the @samp{.eln} file
corresponding to @file{@var{lib}.el}, it will load a
@file{@var{lib}.elc} and start native compilation of
@file{@var{lib}.el} in the background, then load the @samp{.eln} file
when it finishes compilation.
Emacs Lisp programs usually load Emacs Lisp files using the
@code{load} function. This is similar to @code{load-library}, but is
@ -1604,6 +1612,11 @@ It is customary to put locally installed libraries in the
@code{load-path}, or in some subdirectory of @file{site-lisp}. This
way, you don't need to modify the default value of @code{load-path}.
@vindex native-comp-eln-load-path
Similarly to @code{load-path}, the list of directories where Emacs
looks for @file{*.eln} files with natively-compiled Lisp code is
specified by the variable @code{native-comp-eln-load-path}.
@cindex autoload
Some commands are @dfn{autoloaded}; when you run them, Emacs
automatically loads the associated library first. For instance, the

View file

@ -2745,10 +2745,12 @@ desktop reloading, since it bypasses the init file, where
@findex desktop-revert
You can have separate saved desktop configurations in different
directories; starting Emacs from a directory where you have a saved
desktop configuration will restore that configuration. You can save
the current desktop and reload the one saved in another directory by
typing @kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert}
reverts to the previously reloaded desktop.
desktop configuration will restore that configuration, provided that
you customize @code{desktop-path} to prepend @file{.} (the current
directory) to the other directories there. You can save the current
desktop and reload the one saved in another directory by typing
@kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert} reverts
to the previously reloaded desktop.
@vindex desktop-load-locked-desktop
The file in which Emacs saves the desktop is locked while the

View file

@ -75,17 +75,20 @@ file exists, and Emacs was compiled with native-compilation support
(@pxref{Native Compilation}), @code{load} attempts to find a
corresponding @samp{.eln} file, and if found, loads it instead of
@file{@var{filename}.elc}. Otherwise, it loads
@file{@var{filename}.elc}. If there is no file by that name, then
@code{load} looks for a file named @file{@var{filename}.el}. If that
file exists, it is loaded. If Emacs was compiled with support for
dynamic modules (@pxref{Dynamic Modules}), @code{load} next looks for
a file named @file{@var{filename}.@var{ext}}, where @var{ext} is a
system-dependent file-name extension of shared libraries. Finally, if
neither of those names is found, @code{load} looks for a file named
@var{filename} with nothing appended, and loads it if it exists. (The
@code{load} function is not clever about looking at @var{filename}.
In the perverse case of a file named @file{foo.el.el}, evaluation of
@code{(load "foo.el")} will indeed find it.)
@file{@var{filename}.elc} (and starts a background native compilation
to produce the missing @samp{.eln} file, followed by loading that
file). If there is no @file{@var{filename}.elc}, then @code{load}
looks for a file named @file{@var{filename}.el}. If that file exists,
it is loaded. If Emacs was compiled with support for dynamic modules
(@pxref{Dynamic Modules}), @code{load} next looks for a file named
@file{@var{filename}.@var{ext}}, where @var{ext} is a system-dependent
file-name extension of shared libraries (@samp{.so} on GNU and Unix
systems). Finally, if neither of those names is found, @code{load}
looks for a file named @var{filename} with nothing appended, and loads
it if it exists. (The @code{load} function is not clever about
looking at @var{filename}. In the perverse case of a file named
@file{foo.el.el}, evaluation of @code{(load "foo.el")} will indeed
find it.)
If Auto Compression mode is enabled, as it is by default, then if
@code{load} can not find a file, it searches for a compressed version

View file

@ -3688,8 +3688,8 @@ default, from @code{font-lock-function-name-face}.
@vindex font-lock-variable-name-face
for the name of a variable being defined or declared.
@item font-lock-variable-ref-face
@vindex font-lock-variable-ref-face
@item font-lock-variable-use-face
@vindex font-lock-variable-use-face
for the name of a variable being referenced. This face inherits, by
default, from @code{font-lock-variable-name-face}.
@ -3772,8 +3772,8 @@ for properties of an object, such as the declaration of fields in a
struct. This face inherits, by default, from
@code{font-lock-variable-name-face}.
@item font-lock-property-ref-face
@vindex font-lock-property-ref-face
@item font-lock-property-use-face
@vindex font-lock-property-use-face
for properties of an object, such as use of fields in a struct. This
face inherits, by default, from @code{font-lock-property-name-face}.
@ -5093,7 +5093,15 @@ This anchor is a function that is called with 3 arguments: @var{node},
@item parent-bol
This anchor is a function that is called with 3 arguments: @var{node},
@var{parent}, and @var{bol}, and returns the first non-space character
on the line of @var{parent}.
on the line which @var{parent}'s start is on.
@item parent-bol
This anchor is a function that is called with 3 arguments: @var{node},
@var{parent}, and @var{bol}. It finds the first ancestor node
(parent, grandparent, etc) of @var{node} that starts on its own line,
and return the start of that node. ``Starting on its own line'' means
there is only whitespace character before the node on the line which
the node's start is on.
@item prev-sibling
This anchor is a function that is called with 3 arguments: @var{node},

View file

@ -14509,13 +14509,23 @@ Here's an example method that's more complex:
@end example
@table @code
@vindex nnimap-address
@item nnimap-address
The address of the server, like @samp{imap.gmail.com}.
@vindex nnimap-user
@item nnimap-user
Username to use for authentication to the @acronym{IMAP} server. This
corresponds to the value of the @samp{login} token in your
@file{~/.authinfo} file. Set this variable if you want to access
multiple accounts from the same @acronym{IMAP} server.
@vindex nnimap-server-port
@item nnimap-server-port
If the server uses a non-standard port, that can be specified here. A
typical port would be @code{"imap"} or @code{"imaps"}.
@vindex nnimap-stream
@item nnimap-stream
How @code{nnimap} should connect to the server. Possible values are:
@ -14546,6 +14556,7 @@ Non-encrypted and unsafe straight socket connection.
@end table
@vindex nnimap-authenticator
@item nnimap-authenticator
Some @acronym{IMAP} servers allow anonymous logins. In that case,
this should be set to @code{anonymous}. If this variable isn't set,
@ -14555,6 +14566,7 @@ specific login method to be used, you can set this variable to either
@code{plain}, @code{cram-md5} or @code{xoauth2}. (The latter method
requires using the @file{oauth2.el} library.)
@vindex nnimap-expunge
@item nnimap-expunge
When to expunge deleted messages. If @code{never}, deleted articles
are marked with the IMAP @code{\\Delete} flag but not automatically
@ -14570,27 +14582,32 @@ EXPUNGE nil is equivalent to @code{never}, while t will immediately
expunge ALL articles that are currently flagged as deleted
(i.e., potentially not only the article that was just deleted).
@vindex nnimap-streaming
@item nnimap-streaming
Virtually all @acronym{IMAP} server support fast streaming of data.
If you have problems connecting to the server, try setting this to
@code{nil}.
@vindex nnimap-fetch-partial-articles
@item nnimap-fetch-partial-articles
If non-@code{nil}, fetch partial articles from the server. If set to
a string, then it's interpreted as a regexp, and parts that have
matching types will be fetched. For instance, @samp{"text/"} will
fetch all textual parts, while leaving the rest on the server.
@vindex nnimap-record-commands
@item nnimap-record-commands
If non-@code{nil}, record all @acronym{IMAP} commands in the
@samp{"*imap log*"} buffer.
@vindex nnimap-use-namespaces
@item nnimap-use-namespaces
If non-@code{nil}, omit the IMAP namespace prefix in nnimap group
names. If your IMAP mailboxes are called something like @samp{INBOX}
and @samp{INBOX.Lists.emacs}, but you'd like the nnimap group names to
be @samp{INBOX} and @samp{Lists.emacs}, you should enable this option.
@vindex nnimap-keepalive-intervals
@item nnimap-keepalive-intervals
By default, nnimap will send occasional @samp{NOOP} (keepalive)
commands to the server, to keep the connection alive. This option

View file

@ -107,6 +107,15 @@ If you want to get back the old behavior, set the user option to the value
(setopt gdb-locals-table-row-config
`((type . 0) (name . 0) (value . ,gdb-locals-value-limit)))
** Compile
*** New user option 'grep-use-headings'.
When non-nil, the output of Grep is split into sections, one for each
file, instead of having file names prefixed to each line. It is
equivalent to the --heading option of some tools such as 'git grep'
and 'rg'. The headings are displayed using the new 'grep-heading'
face.
** VC
---
@ -352,6 +361,21 @@ compared reliably at all.
This warning can be suppressed using 'with-suppressed-warnings' with
the warning name 'suspicious'.
---
*** Warn about 'condition-case' without handlers.
The compiler now warns when the 'condition-case' form is used without
any actual handlers, as in
(condition-case nil (read buffer))
because it has no effect other than the execution of the body form.
In particular, no errors are caught or suppressed. If the intention
was to catch all errors, add an explicit handler for 'error', or use
'ignore-error' or 'ignore-errors'.
This warning can be suppressed using 'with-suppressed-warnings' with
the warning name 'suspicious'.
+++
** New function 'file-user-uid'.
This function is like 'user-uid', but is aware of file name handlers,

View file

@ -832,8 +832,8 @@ These faces are primarily meant for use with tree-sitter. They are:
'font-lock-escape-face', 'font-lock-function-call-face',
'font-lock-misc-punctuation-face', 'font-lock-number-face',
'font-lock-operator-face', 'font-lock-property-name-face',
'font-lock-property-ref-face', 'font-lock-punctuation-face',
'font-lock-regexp-face', and 'font-lock-variable-ref-face'.
'font-lock-property-use-face', 'font-lock-punctuation-face',
'font-lock-regexp-face', and 'font-lock-variable-use-face'.
+++
** New face 'variable-pitch-text'.

View file

@ -1732,6 +1732,8 @@ process_file_name (char *file, language *lang)
char *cmd = xmalloc (buf_len);
snprintf (cmd, buf_len, "%s %s > %s",
compr->command, new_real_name, new_tmp_name);
free (new_real_name);
free (new_tmp_name);
#endif
inf = (system (cmd) == -1
? NULL

View file

@ -2482,7 +2482,8 @@ the United States."
(interactive)
(cond ((eq last-command 'calcDigit-start)
(erase-buffer))
(t (backward-delete-char 1)))
(t (with-suppressed-warnings ((interactive-only backward-delete-char))
(backward-delete-char 1))))
(if (= (calc-minibuffer-size) 0)
(progn
(setq last-command-event 13)

View file

@ -73,11 +73,11 @@ Do not call this mode function yourself. It is meant for internal use."
font-lock-keyword-face font-lock-negation-char-face
font-lock-number-face font-lock-misc-punctuation-face
font-lock-operator-face font-lock-preprocessor-face
font-lock-property-name-face font-lock-property-ref-face
font-lock-property-name-face font-lock-property-use-face
font-lock-punctuation-face
font-lock-regexp-grouping-backslash font-lock-regexp-grouping-construct
font-lock-string-face font-lock-type-face font-lock-variable-name-face
font-lock-variable-ref-face
font-lock-variable-use-face
font-lock-warning-face button link link-visited fringe
header-line tooltip mode-line mode-line-buffer-id
mode-line-emphasis mode-line-highlight mode-line-inactive

View file

@ -1664,8 +1664,8 @@ See Info node `(elisp) Integer Basics'."
file-directory-p file-exists-p file-locked-p file-name-absolute-p
file-name-concat
file-newer-than-file-p file-readable-p file-symlink-p file-writable-p
float float-time floor format format-time-string frame-first-window
frame-root-window frame-selected-window
float float-time floor format format-message format-time-string
frame-first-window frame-root-window frame-selected-window
frame-visible-p fround ftruncate
get gethash get-buffer get-buffer-window get-file-buffer
hash-table-count
@ -1685,7 +1685,7 @@ See Info node `(elisp) Integer Basics'."
regexp-quote region-beginning region-end reverse round
sin sqrt string string-equal string-lessp
string-search string-to-char
string-to-number string-to-syntax substring
string-to-number string-to-syntax substring substring-no-properties
sxhash-equal sxhash-eq sxhash-eql
symbol-function symbol-name symbol-plist symbol-value
string-make-unibyte

View file

@ -339,14 +339,19 @@ Assumes the caller has bound `macroexpand-all-environment'."
(`(cond . ,clauses)
(macroexp--cons fn (macroexp--all-clauses clauses) form))
(`(condition-case . ,(or `(,err ,body . ,handlers) pcase--dontcare))
(macroexp--cons
fn
(macroexp--cons err
(macroexp--cons (macroexp--expand-all body)
(macroexp--all-clauses handlers 1)
(cddr form))
(cdr form))
form))
(let ((exp-body (macroexp--expand-all body)))
(if handlers
(macroexp--cons fn
(macroexp--cons
err (macroexp--cons
exp-body
(macroexp--all-clauses handlers 1)
(cddr form))
(cdr form))
form)
(macroexp-warn-and-return
(format-message "`condition-case' without handlers")
exp-body (list 'suspicious 'condition-case) t form))))
(`(,(or 'defvar 'defconst) ,(and name (pred symbolp)) . ,_)
(push name macroexp--dynvars)
(macroexp--all-forms form 2))

View file

@ -2046,7 +2046,7 @@ as the constructs of Haddock, Javadoc and similar systems."
"Font Lock mode face used to highlight variable names."
:group 'font-lock-faces)
(defface font-lock-variable-ref-face
(defface font-lock-variable-use-face
'((t :inherit font-lock-variable-name-face))
"Font Lock mode face used to highlight variable references."
:group 'font-lock-faces
@ -2134,7 +2134,7 @@ For example, the declaration of fields in a struct."
:group 'font-lock-faces
:version "29.1")
(defface font-lock-property-ref-face
(defface font-lock-property-use-face
'((t :inherit font-lock-property-name-face))
"Font Lock mode face used to highlight property references.
For example, property lookup of fields in a struct."

View file

@ -215,15 +215,29 @@ the default otherwise."
;; calculated, This causes the first cached completion to
;; be taken (i.e. the one that the user sees highlighted)
completion-all-sorted-completions)
(minibuffer-force-complete-and-exit)
(if (window-minibuffer-p)
(minibuffer-force-complete-and-exit)
(minibuffer-force-complete (icomplete--field-beg)
(icomplete--field-end)
'dont-cycle)
(completion-in-region-mode -1))
;; Otherwise take the faster route...
(minibuffer-complete-and-exit)))
(if (window-minibuffer-p)
(minibuffer-complete-and-exit)
(completion-complete-and-exit
(icomplete--field-beg)
(icomplete--field-end)
(lambda () (completion-in-region-mode -1))))))
(defun icomplete-force-complete ()
"Complete the icomplete minibuffer."
(interactive)
;; We're not at all interested in cycling here (bug#34077).
(minibuffer-force-complete nil nil 'dont-cycle))
(if (window-minibuffer-p)
(minibuffer-force-complete nil nil 'dont-cycle)
(minibuffer-force-complete (icomplete--field-beg)
(icomplete--field-end)
'dont-cycle)))
;; Apropos `icomplete-scroll', we implement "scrolling icomplete"
;; within classic icomplete, which is "rotating", by contrast.
@ -429,9 +443,12 @@ more like `ido-mode' than regular `icomplete-mode'."
:global t
(remove-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)
(remove-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup)
(remove-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup)
(when fido-mode
(icomplete-mode -1)
(setq icomplete-mode t)
(when icomplete-in-buffer
(add-hook 'completion-in-region-mode-hook #'icomplete--in-region-setup))
(add-hook 'minibuffer-setup-hook #'icomplete-minibuffer-setup)
(add-hook 'minibuffer-setup-hook #'icomplete--fido-mode-setup)))

View file

@ -4778,7 +4778,13 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
(defun tramp-handle-unlock-file (file)
"Like `unlock-file' for Tramp files."
(when-let ((lockname (tramp-compat-make-lock-file-name file)))
;; When there is no connection, we don't do it. Otherwise,
;; functions like `kill-buffer' would try to reestablish the
;; connection. See Bug#61663.
(when-let ((v (tramp-dissect-file-name file))
(p (tramp-get-process v))
((process-live-p p))
(lockname (tramp-compat-make-lock-file-name file)))
(condition-case err
(delete-file lockname)
;; `userlock--handle-unlock-error' exists since Emacs 28.1.

View file

@ -77,6 +77,7 @@
(declare-function treesit-node-child "treesit.c")
(declare-function treesit-node-child-by-field-name "treesit.c")
(declare-function treesit-node-type "treesit.c")
(declare-function treesit-node-prev-sibling "treesit.c")
;;; Custom variables
@ -279,6 +280,12 @@ doesn't have a child."
;; prev-sibling doesn't have a child.
(treesit-node-start prev-sibling)))
(defun c-ts-mode--standalone-grandparent (_node parent bol &rest args)
"Like the standalone-parent anchor but pass it the grandparent.
PARENT, BOL, ARGS are the same as other anchor functions."
(apply (alist-get 'standalone-parent treesit-simple-indent-presets)
parent (treesit-node-parent parent) bol args))
(defun c-ts-mode--indent-styles (mode)
"Indent rules supported by `c-ts-mode'.
MODE is either `c' or `cpp'."
@ -300,9 +307,9 @@ MODE is either `c' or `cpp'."
((parent-is "comment") prev-adaptive-prefix 0)
;; Labels.
((node-is "labeled_statement") parent-bol 0)
((node-is "labeled_statement") standalone-parent 0)
((parent-is "labeled_statement")
point-min c-ts-common-statement-offset)
c-ts-mode--standalone-grandparent c-ts-mode-indent-offset)
((node-is "preproc") point-min 0)
((node-is "#endif") point-min 0)
@ -330,7 +337,7 @@ MODE is either `c' or `cpp'."
;; Closing bracket. This should be before initializer_list
;; (and probably others) rule because that rule (and other
;; similar rules) will match the closing bracket. (Bug#61398)
((node-is "}") point-min c-ts-common-statement-offset)
((node-is "}") standalone-parent 0)
,@(when (eq mode 'cpp)
'(((node-is "access_specifier") parent-bol 0)
;; Indent the body of namespace definitions.
@ -341,25 +348,25 @@ MODE is either `c' or `cpp'."
((match nil "initializer_list" nil 1 1) parent-bol c-ts-mode-indent-offset)
((match nil "initializer_list" nil 2) c-ts-mode--anchor-prev-sibling 0)
;; Statement in enum.
((match nil "enumerator_list" nil 1 1) point-min c-ts-common-statement-offset)
((match nil "enumerator_list" nil 1 1) standalone-parent c-ts-mode-indent-offset)
((match nil "enumerator_list" nil 2) c-ts-mode--anchor-prev-sibling 0)
;; Statement in struct and union.
((match nil "field_declaration_list" nil 1 1) point-min c-ts-common-statement-offset)
((match nil "field_declaration_list" nil 1 1) standalone-parent c-ts-mode-indent-offset)
((match nil "field_declaration_list" nil 2) c-ts-mode--anchor-prev-sibling 0)
;; Statement in {} blocks.
((match nil "compound_statement" nil 1 1) point-min c-ts-common-statement-offset)
((match nil "compound_statement" nil 1 1) standalone-parent c-ts-mode-indent-offset)
((match nil "compound_statement" nil 2) c-ts-mode--anchor-prev-sibling 0)
;; Opening bracket.
((node-is "compound_statement") point-min c-ts-common-statement-offset)
((node-is "compound_statement") standalone-parent c-ts-mode-indent-offset)
;; Bug#61291.
((match "expression_statement" nil "body") point-min c-ts-common-statement-offset)
((match "expression_statement" nil "body") standalone-parent c-ts-mode-indent-offset)
;; These rules are for cases where the body is bracketless.
;; Tested by the "Bracketless Simple Statement" test.
((parent-is "if_statement") point-min c-ts-common-statement-offset)
((parent-is "for_statement") point-min c-ts-common-statement-offset)
((parent-is "while_statement") point-min c-ts-common-statement-offset)
((parent-is "do_statement") point-min c-ts-common-statement-offset)
((parent-is "if_statement") standalone-parent c-ts-mode-indent-offset)
((parent-is "for_statement") standalone-parent c-ts-mode-indent-offset)
((parent-is "while_statement") standalone-parent c-ts-mode-indent-offset)
((parent-is "do_statement") standalone-parent c-ts-mode-indent-offset)
,@(when (eq mode 'cpp)
`(((node-is "field_initializer_list") parent-bol ,(* c-ts-mode-indent-offset 2)))))))
@ -388,16 +395,13 @@ MODE is either `c' or `cpp'."
((parent-is "do_statement") parent-bol 0)
,@common))))
(defun c-ts-mode--top-level-label-matcher (node &rest _)
(defun c-ts-mode--top-level-label-matcher (node parent &rest _)
"A matcher that matches a top-level label.
NODE should be a labeled_statement."
(let ((func (treesit-parent-until
node (lambda (n)
(equal (treesit-node-type n)
"compound_statement")))))
(and (equal (treesit-node-type node)
"labeled_statement")
(not (treesit-node-top-level func "compound_statement")))))
NODE should be a labeled_statement. PARENT is its parent."
(and (equal (treesit-node-type node)
"labeled_statement")
(equal "function_definition"
(treesit-node-type (treesit-node-parent parent)))))
;;; Font-lock
@ -543,7 +547,7 @@ MODE is either `c' or `cpp'."
'((assignment_expression
left: (identifier) @font-lock-variable-name-face)
(assignment_expression
left: (field_expression field: (_) @font-lock-property-ref-face))
left: (field_expression field: (_) @font-lock-property-use-face))
(assignment_expression
left: (pointer_expression
(identifier) @font-lock-variable-name-face))
@ -579,7 +583,7 @@ MODE is either `c' or `cpp'."
:language mode
:feature 'property
'((field_identifier) @font-lock-property-ref-face)
'((field_identifier) @font-lock-property-use-face)
:language mode
:feature 'bracket
@ -656,7 +660,7 @@ OVERRIDE, START, END, and ARGS, see `treesit-font-lock-rules'."
"call_expression"))
(treesit-fontify-with-override
(treesit-node-start node) (treesit-node-end node)
'font-lock-variable-ref-face override start end)))
'font-lock-variable-use-face override start end)))
(defun c-ts-mode--fontify-defun (node override start end &rest _)
"Correctly fontify the DEFUN macro.
@ -867,6 +871,8 @@ the semicolon. This function skips the semicolon."
(when (eq c-ts-mode-indent-style 'linux)
(setq-local indent-tabs-mode t))
(setq-local c-ts-common-indent-offset 'c-ts-mode-indent-offset)
;; This setup is not needed anymore, but we might find uses for it
;; later, so I'm keeping it.
(setq-local c-ts-common-indent-type-regexp-alist
`((block . ,(rx (or "compound_statement"
"field_declaration_list"

View file

@ -154,7 +154,7 @@
:language 'cmake
:feature 'variable
:override t
'((variable) @font-lock-variable-ref-face)
'((variable) @font-lock-variable-use-face)
:language 'cmake
:feature 'error

View file

@ -1706,7 +1706,7 @@ to `compilation-error-regexp-alist' if RULES is nil."
(set-marker (make-marker)
(save-excursion
(goto-char (point-min))
(text-property-search-forward 'compilation-header-end)
(text-property-search-forward 'compilation-annotation)
;; If we have no end marker, this will be
;; `point-min' still.
(point)))))
@ -1854,6 +1854,14 @@ If nil, don't hide anything."
;; buffers when it changes from nil to non-nil or vice-versa.
(unless compilation-in-progress (force-mode-line-update t)))
(defun compilation-insert-annotation (&rest args)
"Insert ARGS at point, adding the `compilation-annotation' text property.
This property is used to distinguish output of the compilation
process from additional information inserted by Emacs."
(let ((start (point)))
(apply #'insert args)
(put-text-property start (point) 'compilation-annotation t)))
;;;###autoload
(defun compilation-start (command &optional mode name-function highlight-regexp
continue)
@ -1975,17 +1983,16 @@ Returns the compilation buffer created."
(setq-local compilation-auto-jump-to-next t))
(when (zerop (buffer-size))
;; Output a mode setter, for saving and later reloading this buffer.
(insert "-*- mode: " name-of-mode
"; default-directory: "
(prin1-to-string (abbreviate-file-name default-directory))
" -*-\n"))
(insert (format "%s started at %s\n\n"
mode-name
(substring (current-time-string) 0 19))
command "\n")
;; Mark the end of the header so that we don't interpret
;; anything in it as an error.
(put-text-property (1- (point)) (point) 'compilation-header-end t)
(compilation-insert-annotation
"-*- mode: " name-of-mode
"; default-directory: "
(prin1-to-string (abbreviate-file-name default-directory))
" -*-\n"))
(compilation-insert-annotation
(format "%s started at %s\n\n"
mode-name
(substring (current-time-string) 0 19))
command "\n")
(setq thisdir default-directory))
(set-buffer-modified-p nil))
;; Pop up the compilation buffer.
@ -2467,13 +2474,13 @@ commands of Compilation major mode are available. See
(cur-buffer (current-buffer)))
;; Record where we put the message, so we can ignore it later on.
(goto-char omax)
(insert ?\n mode-name " " (car status))
(compilation-insert-annotation ?\n mode-name " " (car status))
(if (and (numberp compilation-window-height)
(zerop compilation-window-height))
(message "%s" (cdr status)))
(if (bolp)
(forward-char -1))
(insert " at " (substring (current-time-string) 0 19))
(compilation-insert-annotation " at " (substring (current-time-string) 0 19))
(goto-char (point-max))
;; Prevent that message from being recognized as a compilation error.
(add-text-properties omax (point)

View file

@ -708,9 +708,9 @@ compilation and evaluation time conflicts."
(treesit-font-lock-rules
:language 'c-sharp
:feature 'expression
'((conditional_expression (identifier) @font-lock-variable-ref-face)
(postfix_unary_expression (identifier)* @font-lock-variable-ref-face)
(initializer_expression (assignment_expression left: (identifier) @font-lock-variable-ref-face)))
'((conditional_expression (identifier) @font-lock-variable-use-face)
(postfix_unary_expression (identifier)* @font-lock-variable-use-face)
(initializer_expression (assignment_expression left: (identifier) @font-lock-variable-use-face)))
:language 'c-sharp
:feature 'bracket
@ -739,8 +739,8 @@ compilation and evaluation time conflicts."
:language 'c-sharp
:override t
:feature 'property
`((attribute (identifier) @font-lock-property-ref-face (attribute_argument_list))
(attribute (identifier) @font-lock-property-ref-face))
`((attribute (identifier) @font-lock-property-use-face (attribute_argument_list))
(attribute (identifier) @font-lock-property-use-face))
:language 'c-sharp
:override t
@ -878,23 +878,23 @@ compilation and evaluation time conflicts."
:override t
'((if_directive
"if" @font-lock-preprocessor-face
(identifier) @font-lock-variable-ref-face)
(identifier) @font-lock-variable-use-face)
(elif_directive
"elif" @font-lock-preprocessor-face
(identifier) @font-lock-variable-ref-face)
(identifier) @font-lock-variable-use-face)
(else_directive) @font-lock-preprocessor-face
(endif_directive) @font-lock-preprocessor-face
(define_directive
"define" @font-lock-preprocessor-face
(identifier) @font-lock-variable-ref-face)
(identifier) @font-lock-variable-use-face)
(nullable_directive) @font-lock-preprocessor-face
(pragma_directive) @font-lock-preprocessor-face
(region_directive) @font-lock-preprocessor-face
(endregion_directive) @font-lock-preprocessor-face
(region_directive
(preproc_message) @font-lock-variable-ref-face)
(preproc_message) @font-lock-variable-use-face)
(endregion_directive
(preproc_message) @font-lock-variable-ref-face))))
(preproc_message) @font-lock-variable-use-face))))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.cs\\'" . csharp-mode))

View file

@ -486,7 +486,8 @@ This can be useful when using docker to run a language server.")
(WorkspaceEdit () (:changes :documentChanges))
(WorkspaceSymbol (:name :kind) (:containerName :location :data))
(InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft
:paddingRight :data)))
:paddingRight :data))
(InlayHintLabelPart (:value) (:tooltip :location :command)))
"Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces.
INTERFACE-NAME is a symbol designated by the spec as
@ -641,7 +642,7 @@ Honor `eglot-strict-mode'."
Honor `eglot-strict-mode'."
(declare (indent 1) (debug (sexp &rest form)))
(let ((e (cl-gensym "jsonrpc-lambda-elem")))
`(lambda (,e) (eglot--dbind ,cl-lambda-list ,e ,@body))))
`(lambda (,e) (cl-block nil (eglot--dbind ,cl-lambda-list ,e ,@body)))))
(cl-defmacro eglot--dcase (obj &rest clauses)
"Like `pcase', but for the LSP object OBJ.
@ -816,6 +817,7 @@ treated as in `eglot--dbind'."
`(:valueSet
[,@(mapcar
#'car eglot--tag-faces)])))
:general (list :positionEncodings ["utf-32" "utf-8" "utf-16"])
:experimental eglot--{})))
(cl-defgeneric eglot-workspace-folders (server)
@ -1439,71 +1441,111 @@ CONNECT-ARGS are passed as additional arguments to
(let ((warning-minimum-level :error))
(display-warning 'eglot (apply #'format format args) :warning)))
(defun eglot-current-column () (- (point) (line-beginning-position)))
(defalias 'eglot--bol
(if (fboundp 'pos-bol) #'pos-bol
(lambda (&optional n) (let ((inhibit-field-text-motion t))
(line-beginning-position n))))
"Return position of first character in current line.")
(defvar eglot-current-column-function #'eglot-lsp-abiding-column
"Function to calculate the current column.
;;; Encoding fever
;;;
(define-obsolete-function-alias
'eglot-lsp-abiding-column 'eglot-utf-16-linepos "29.1")
(define-obsolete-function-alias
'eglot-current-column 'eglot-utf-32-linepos "29.1")
(define-obsolete-variable-alias
'eglot-current-column-function 'eglot-current-linepos-function "29.1")
This is the inverse operation of
`eglot-move-to-column-function' (which see). It is a function of
no arguments returning a column number. For buffers managed by
fully LSP-compliant servers, this should be set to
`eglot-lsp-abiding-column' (the default), and
`eglot-current-column' for all others.")
(defvar eglot-current-linepos-function #'eglot-utf-16-linepos
"Function calculating position relative to line beginning.
(defun eglot-lsp-abiding-column (&optional lbp)
"Calculate current COLUMN as defined by the LSP spec.
LBP defaults to `line-beginning-position'."
(/ (- (length (encode-coding-region (or lbp (line-beginning-position))
It is a function of no arguments considering the text from line
beginning up to current point. The return value is the number of
UTF code units needed to encode that text from the LSP server's
perspective. This may be a number of octets, 16-bit words or
Unicode code points, depending on whether the LSP server's
`positionEncoding' capability is UTF-8, UTF-16 or UTF-32,
respectively. Position of point should remain unaltered if that
return value is fed through the corresponding inverse function
`eglot-move-to-linepos-function' (which see).")
(defun eglot-utf-8-linepos ()
"Calculate number of UTF-8 bytes from line beginning."
(length (encode-coding-region (eglot--bol) (point) 'utf-8-unix t)))
(defun eglot-utf-16-linepos (&optional lbp)
"Calculate number of UTF-16 code units from position given by LBP.
LBP defaults to `eglot--bol'."
(/ (- (length (encode-coding-region (or lbp (eglot--bol))
;; Fix github#860
(min (point) (point-max)) 'utf-16 t))
2)
2))
(defun eglot-utf-32-linepos ()
"Calculate number of Unicode codepoints from line beginning."
(- (point) (eglot--bol)))
(defun eglot--pos-to-lsp-position (&optional pos)
"Convert point POS to LSP position."
(eglot--widening
;; LSP line is zero-origin; emacs is one-origin.
(list :line (1- (line-number-at-pos pos t))
:character (progn (when pos (goto-char pos))
(funcall eglot-current-column-function)))))
(funcall eglot-current-linepos-function)))))
(defvar eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column
"Function to move to a column reported by the LSP server.
(define-obsolete-function-alias
'eglot-move-to-current-column 'eglot-move-to-utf-32-linepos "29.1")
(define-obsolete-function-alias
'eglot-move-to-lsp-abiding-column 'eglot-move-to-utf-16-linepos "29.1")
(define-obsolete-variable-alias
'eglot-move-to-column-function 'eglot-move-to-linepos-function "29.1")
According to the standard, LSP column/character offsets are based
on a count of UTF-16 code units, not actual visual columns. So
when LSP says position 3 of a line containing just \"aXbc\",
where X is a multi-byte character, it actually means `b', not
`c'. However, many servers don't follow the spec this closely.
(defvar eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos
"Function to move to a position within a line reported by the LSP server.
For buffers managed by fully LSP-compliant servers, this should
be set to `eglot-move-to-lsp-abiding-column' (the default), and
`eglot-move-to-column' for all others.")
Per the LSP spec, character offsets in LSP Position objects count
UTF-16 code units, not actual code points. So when LSP says
position 3 of a line containing just \"aXbc\", where X is a funny
looking character in the UTF-16 \"supplementary plane\", it
actually means `b', not `c'. The default value
`eglot-move-to-utf-16-linepos' accounts for this.
(defun eglot-move-to-column (column)
"Move to COLUMN without closely following the LSP spec."
This variable can also be set to `eglot-move-to-utf-8-linepos' or
`eglot-move-to-utf-32-linepos' for servers not closely following
the spec. Also, since LSP 3.17 server and client may agree on an
encoding and Eglot will set this variable automatically.")
(defun eglot-move-to-utf-8-linepos (n)
"Move to line's Nth byte as computed by LSP's UTF-8 criterion."
(let* ((bol (eglot--bol))
(goal-byte (+ (position-bytes bol) n))
(eol (line-end-position)))
(goto-char bol)
(while (and (< (position-bytes (point)) goal-byte) (< (point) eol))
;; raw bytes take 2 bytes in the buffer
(when (>= (char-after) #x3fff80) (setq goal-byte (1+ goal-byte)))
(forward-char 1))))
(defun eglot-move-to-utf-16-linepos (n)
"Move to line's Nth code unit as computed by LSP's UTF-16 criterion."
(let* ((bol (eglot--bol))
(goal-char (+ bol n))
(eol (line-end-position)))
(goto-char bol)
(while (and (< (point) goal-char) (< (point) eol))
;; code points in the "supplementary place" use two code units
(when (<= #x010000 (char-after) #x10ffff) (setq goal-char (1- goal-char)))
(forward-char 1))))
(defun eglot-move-to-utf-32-linepos (n)
"Move to line's Nth codepoint as computed by LSP's UTF-32 criterion."
;; We cannot use `move-to-column' here, because it moves to *visual*
;; columns, which can be different from LSP columns in case of
;; columns, which can be different from LSP characters in case of
;; `whitespace-mode', `prettify-symbols-mode', etc. (github#296,
;; github#297)
(goto-char (min (+ (line-beginning-position) column)
(line-end-position))))
(defun eglot-move-to-lsp-abiding-column (column)
"Move to COLUMN abiding by the LSP spec."
(save-restriction
(cl-loop
with lbp = (line-beginning-position)
initially
(narrow-to-region lbp (line-end-position))
(move-to-column column)
for diff = (- column
(eglot-lsp-abiding-column lbp))
until (zerop diff)
do (condition-case eob-err
(forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2))
(end-of-buffer (cl-return eob-err))))))
(goto-char (min (+ (eglot--bol) n) (line-end-position))))
(defun eglot--lsp-position-to-point (pos-plist &optional marker)
"Convert LSP position POS-PLIST to Emacs point.
@ -1515,16 +1557,17 @@ If optional MARKER, return a marker instead"
(forward-line (min most-positive-fixnum
(plist-get pos-plist :line)))
(unless (eobp) ;; if line was excessive leave point at eob
(let ((tab-width 1)
(col (plist-get pos-plist :character)))
(let ((col (plist-get pos-plist :character)))
(unless (wholenump col)
(eglot--warn
"Caution: LSP server sent invalid character position %s. Using 0 instead."
col)
(setq col 0))
(funcall eglot-move-to-column-function col)))
(funcall eglot-move-to-linepos-function col)))
(if marker (copy-marker (point-marker)) (point)))))
;;; More helpers
(defconst eglot--uri-path-allowed-chars
(let ((vec (copy-sequence url-path-allowed-chars)))
(aset vec ?: nil) ;; see github#639
@ -1758,6 +1801,14 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
:init-value nil :lighter nil :keymap eglot-mode-map
(cond
(eglot--managed-mode
(pcase (plist-get (eglot--capabilities (eglot-current-server))
:positionEncoding)
("utf-32"
(eglot--setq-saving eglot-current-linepos-function #'eglot-utf-32-linepos)
(eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-32-linepos))
("utf-8"
(eglot--setq-saving eglot-current-linepos-function #'eglot-utf-8-linepos)
(eglot--setq-saving eglot-move-to-linepos-function #'eglot-move-to-utf-8-linepos)))
(add-hook 'after-change-functions 'eglot--after-change nil t)
(add-hook 'before-change-functions 'eglot--before-change nil t)
(add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t)
@ -2144,7 +2195,7 @@ COMMAND is a symbol naming the command."
(eglot--widening
(goto-char (point-min))
(setq beg
(line-beginning-position
(eglot--bol
(1+ (plist-get (plist-get range :start) :line))))
(setq end
(line-end-position
@ -2584,14 +2635,14 @@ Try to visit the target file for a richer summary line."
(collect (lambda ()
(eglot--widening
(pcase-let* ((`(,beg . ,end) (eglot--range-region range))
(bol (progn (goto-char beg) (line-beginning-position)))
(bol (progn (goto-char beg) (eglot--bol)))
(substring (buffer-substring bol (line-end-position)))
(hi-beg (- beg bol))
(hi-end (- (min (line-end-position) end) bol)))
(add-face-text-property hi-beg hi-end 'xref-match
t substring)
(list substring (line-number-at-pos (point) t)
(eglot-current-column) (- end beg))))))
(eglot-utf-32-linepos) (- end beg))))))
(`(,summary ,line ,column ,length)
(cond
(visiting (with-current-buffer visiting (funcall collect)))
@ -2935,7 +2986,7 @@ for which LSP on-type-formatting should be requested."
(looking-back
(regexp-opt
(cl-coerce (cl-getf completion-capability :triggerCharacters) 'list))
(line-beginning-position))))
(eglot--bol))))
:exit-function
(lambda (proxy status)
(when (memq status '(finished exact))
@ -3545,20 +3596,30 @@ If NOERROR, return predicate, else erroring function."
(paint-hint
(eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight)
(goto-char (eglot--lsp-position-to-point position))
(let ((ov (make-overlay (point) (point)))
(left-pad (and paddingLeft (not (memq (char-before) '(32 9)))))
(right-pad (and paddingRight (not (memq (char-after) '(32 9)))))
(text (if (stringp label)
label (plist-get (elt label 0) :value))))
(overlay-put ov 'before-string
(propertize
(concat (and left-pad " ") text (and right-pad " "))
'face (pcase kind
(1 'eglot-type-hint-face)
(2 'eglot-parameter-hint-face)
(_ 'eglot-inlay-hint-face))))
(overlay-put ov 'eglot--inlay-hint t)
(overlay-put ov 'eglot--overlay t)))))
(when (or (> (point) to) (< (point) from)) (cl-return))
(let ((left-pad (and paddingLeft
(not (memq (char-before) '(32 9))) " "))
(right-pad (and paddingRight
(not (memq (char-after) '(32 9))) " ")))
(cl-flet
((do-it (text lpad rpad)
(let ((ov (make-overlay (point) (point))))
(overlay-put ov 'before-string
(propertize
(concat lpad text rpad)
'face (pcase kind
(1 'eglot-type-hint-face)
(2 'eglot-parameter-hint-face)
(_ 'eglot-inlay-hint-face))))
(overlay-put ov 'eglot--inlay-hint t)
(overlay-put ov 'eglot--overlay t))))
(if (stringp label) (do-it label left-pad right-pad)
(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))))))))))
(jsonrpc-async-request
(eglot--current-server-or-lose)
:textDocument/inlayHint

View file

@ -178,12 +178,12 @@
:language 'go
:feature 'property
'((selector_expression field: (field_identifier) @font-lock-property-ref-face)
(keyed_element (_ (identifier) @font-lock-property-ref-face)))
'((selector_expression field: (field_identifier) @font-lock-property-use-face)
(keyed_element (_ (identifier) @font-lock-property-use-face)))
:language 'go
:feature 'variable
'((identifier) @font-lock-variable-ref-face)
'((identifier) @font-lock-variable-use-face)
:language 'go
:feature 'escape-sequence

View file

@ -457,6 +457,33 @@ buffer `default-directory'."
:type '(repeat (choice (const :tag "Default" nil)
(string :tag "Directory"))))
(defcustom grep-use-headings nil
"If non-nil, subdivide grep output into sections, one per file."
:type 'boolean
:version "30.1")
(defface grep-heading `((t :inherit ,grep-hit-face))
"Face of headings when `grep-use-headings' is non-nil."
:version "30.1")
(defvar grep-heading-regexp
(rx bol
(or
(group-n 2
(group-n 1 (+ (not (any 0 ?\n))))
0)
(group-n 2
(group-n 1 (+? nonl))
(any ?: ?- ?=)))
(+ digit)
(any ?: ?- ?=))
"Regexp used to create headings from grep output lines.
It should be anchored at beginning of line. The first capture
group, if present, should match the heading associated to the
line. The buffer range of the second capture, if present, is
made invisible (presumably because displaying it would be
redundant).")
(defvar grep-find-abbreviate-properties
(let ((ellipsis (if (char-displayable-p ?…) "[…]" "[...]"))
(map (make-sparse-keymap)))
@ -612,6 +639,40 @@ This function is called from `compilation-filter-hook'."
(while (re-search-forward "\033\\[[0-9;]*[mK]" end 1)
(replace-match "" t t))))))
(defvar grep--heading-format
(eval-when-compile
(let ((title (propertize "%s"
'font-lock-face 'grep-heading
'outline-level 1)))
(propertize (concat title "\n") 'compilation-annotation t)))
"Format string of grep headings.
This is passed to `format' with one argument, the text of the
first capture group of `grep-heading-regexp'.")
(defvar-local grep--heading-state nil
"Variable to keep track of the `grep--heading-filter' state.")
(defun grep--heading-filter ()
"Filter function to add headings to output of a grep process."
(unless grep--heading-state
(setq grep--heading-state (cons (point-min-marker) nil)))
(save-excursion
(let ((limit (car grep--heading-state)))
;; Move point to the old limit and update limit marker.
(move-marker limit (prog1 (pos-bol) (goto-char limit)))
(while (re-search-forward grep-heading-regexp limit t)
(unless (get-text-property (point) 'compilation-annotation)
(let ((heading (match-string-no-properties 1))
(start (match-beginning 2))
(end (match-end 2)))
(when start
(put-text-property start end 'invisible t))
(when (and heading (not (equal heading (cdr grep--heading-state))))
(save-excursion
(goto-char (pos-bol))
(insert-before-markers (format grep--heading-format heading)))
(setf (cdr grep--heading-state) heading))))))))
(defun grep-probe (command args &optional func result)
(let (process-file-side-effects)
(equal (condition-case nil
@ -906,6 +967,11 @@ The value depends on `grep-command', `grep-template',
(add-function :filter-return (local 'kill-transform-function)
(lambda (string)
(string-replace "\0" ":" string)))
(when grep-use-headings
(add-hook 'compilation-filter-hook #'grep--heading-filter 80 t)
(setq-local outline-search-function #'outline-search-level
outline-level (lambda () (get-text-property
(point) 'outline-level))))
(add-hook 'compilation-filter-hook #'grep-filter nil t))
(defun grep--save-buffers ()

View file

@ -244,7 +244,7 @@
name: (identifier) @font-lock-variable-name-face)
(element_value_pair
key: (identifier) @font-lock-property-ref-face)
key: (identifier) @font-lock-property-use-face)
(formal_parameter
name: (identifier) @font-lock-variable-name-face)
@ -255,14 +255,14 @@
:override t
:feature 'expression
'((method_invocation
object: (identifier) @font-lock-variable-ref-face)
object: (identifier) @font-lock-variable-use-face)
(method_invocation
name: (identifier) @font-lock-function-call-face)
(argument_list (identifier) @font-lock-variable-name-face)
(expression_statement (identifier) @font-lock-variable-ref-face))
(expression_statement (identifier) @font-lock-variable-use-face))
:language 'java
:feature 'bracket

View file

@ -3563,13 +3563,13 @@ This function is intended for use in `after-change-functions'."
:language 'javascript
:feature 'property
'(((property_identifier) @font-lock-property-ref-face
'(((property_identifier) @font-lock-property-use-face
(:pred js--treesit-property-not-function-p
@font-lock-property-ref-face))
@font-lock-property-use-face))
(pair value: (identifier) @font-lock-variable-ref-face)
(pair value: (identifier) @font-lock-variable-use-face)
((shorthand_property_identifier) @font-lock-property-ref-face))
((shorthand_property_identifier) @font-lock-property-use-face))
:language 'javascript
:feature 'assignment
@ -3681,8 +3681,8 @@ For OVERRIDE, START, END, see `treesit-font-lock-rules'."
(treesit-fontify-with-override
(treesit-node-start node) (treesit-node-end node)
(pcase (treesit-node-type node)
("identifier" 'font-lock-variable-ref-face)
("property_identifier" 'font-lock-property-ref-face))
("identifier" 'font-lock-variable-use-face)
("property_identifier" 'font-lock-property-use-face))
override start end)))
(defun js--treesit-defun-name (node)

View file

@ -101,7 +101,7 @@
:language 'json
:feature 'pair
:override t ; Needed for overriding string face on keys.
'((pair key: (_) @font-lock-property-ref-face))
'((pair key: (_) @font-lock-property-use-face))
:language 'json
:feature 'error
:override t

View file

@ -1147,7 +1147,7 @@ fontified."
@font-lock-variable-name-face)
(assignment left: (attribute
attribute: (identifier)
@font-lock-property-ref-face))
@font-lock-property-use-face))
(pattern_list (identifier)
@font-lock-variable-name-face)
(tuple_pattern (identifier)
@ -1184,12 +1184,12 @@ fontified."
:feature 'property
:language 'python
'((attribute
attribute: (identifier) @font-lock-property-ref-face)
attribute: (identifier) @font-lock-property-use-face)
(class_definition
body: (block
(expression_statement
(assignment left:
(identifier) @font-lock-property-ref-face)))))
(identifier) @font-lock-property-use-face)))))
:feature 'operator
:language 'python

View file

@ -909,7 +909,9 @@ This only affects the output of the command `ruby-toggle-block'."
"<<=" ">>=" "&&=" "||=" "and" "or"))
(cond
((not ruby-after-operator-indent)
(ruby-smie--indent-to-stmt ruby-indent-level))
(ruby-smie--indent-to-stmt (if (smie-indent--hanging-p)
ruby-indent-level
0)))
((and (smie-rule-parent-p ";" nil)
(smie-indent--hanging-p))
ruby-indent-level)))

View file

@ -292,11 +292,11 @@ values of OVERRIDE"
:language language
:feature 'global
'((global_variable) @font-lock-variable-ref-face)
'((global_variable) @font-lock-variable-use-face)
:language language
:feature 'instance
'((instance_variable) @font-lock-variable-ref-face)
'((instance_variable) @font-lock-variable-use-face)
:language language
:feature 'method-definition

View file

@ -239,8 +239,8 @@
:language 'rust
:feature 'property
'((field_identifier) @font-lock-property-ref-face
(shorthand_field_initializer (identifier) @font-lock-property-ref-face))
'((field_identifier) @font-lock-property-use-face
(shorthand_field_initializer (identifier) @font-lock-property-use-face))
;; Must be under type, otherwise some imports can be highlighted as constants.
:language 'rust
@ -251,25 +251,25 @@
:language 'rust
:feature 'variable
'((arguments (identifier) @font-lock-variable-ref-face)
(array_expression (identifier) @font-lock-variable-ref-face)
(assignment_expression right: (identifier) @font-lock-variable-ref-face)
(binary_expression left: (identifier) @font-lock-variable-ref-face)
(binary_expression right: (identifier) @font-lock-variable-ref-face)
(block (identifier) @font-lock-variable-ref-face)
(compound_assignment_expr right: (identifier) @font-lock-variable-ref-face)
(field_expression value: (identifier) @font-lock-variable-ref-face)
(field_initializer value: (identifier) @font-lock-variable-ref-face)
(if_expression condition: (identifier) @font-lock-variable-ref-face)
(let_condition value: (identifier) @font-lock-variable-ref-face)
(let_declaration value: (identifier) @font-lock-variable-ref-face)
(match_arm value: (identifier) @font-lock-variable-ref-face)
(match_expression value: (identifier) @font-lock-variable-ref-face)
(reference_expression value: (identifier) @font-lock-variable-ref-face)
(return_expression (identifier) @font-lock-variable-ref-face)
(tuple_expression (identifier) @font-lock-variable-ref-face)
(unary_expression (identifier) @font-lock-variable-ref-face)
(while_expression condition: (identifier) @font-lock-variable-ref-face))
'((arguments (identifier) @font-lock-variable-use-face)
(array_expression (identifier) @font-lock-variable-use-face)
(assignment_expression right: (identifier) @font-lock-variable-use-face)
(binary_expression left: (identifier) @font-lock-variable-use-face)
(binary_expression right: (identifier) @font-lock-variable-use-face)
(block (identifier) @font-lock-variable-use-face)
(compound_assignment_expr right: (identifier) @font-lock-variable-use-face)
(field_expression value: (identifier) @font-lock-variable-use-face)
(field_initializer value: (identifier) @font-lock-variable-use-face)
(if_expression condition: (identifier) @font-lock-variable-use-face)
(let_condition value: (identifier) @font-lock-variable-use-face)
(let_declaration value: (identifier) @font-lock-variable-use-face)
(match_arm value: (identifier) @font-lock-variable-use-face)
(match_expression value: (identifier) @font-lock-variable-use-face)
(reference_expression value: (identifier) @font-lock-variable-use-face)
(return_expression (identifier) @font-lock-variable-use-face)
(tuple_expression (identifier) @font-lock-variable-use-face)
(unary_expression (identifier) @font-lock-variable-use-face)
(while_expression condition: (identifier) @font-lock-variable-use-face))
:language 'rust
:feature 'escape-sequence

View file

@ -249,9 +249,9 @@ Argument LANGUAGE is either `typescript' or `tsx'."
(public_field_definition
name: (property_identifier) @font-lock-property-name-face)
(pair key: (property_identifier) @font-lock-property-ref-face)
(pair key: (property_identifier) @font-lock-property-use-face)
((shorthand_property_identifier) @font-lock-property-ref-face))
((shorthand_property_identifier) @font-lock-property-use-face))
:language language
:feature 'expression
@ -272,7 +272,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
:language language
:feature 'pattern
`((pair_pattern
key: (property_identifier) @font-lock-property-ref-face
key: (property_identifier) @font-lock-property-use-face
value: [(identifier) @font-lock-variable-name-face
(assignment_pattern left: (identifier) @font-lock-variable-name-face)])

View file

@ -768,7 +768,9 @@ one is kept. See `seq-uniq' for non-destructive operation."
(defun delete-consecutive-dups (list &optional circular)
"Destructively remove `equal' consecutive duplicates from LIST.
First and last elements are considered consecutive if CIRCULAR is
non-nil."
non-nil.
Of several consecutive `equal' occurrences, the one earliest in
the list is kept."
(let ((tail list) last)
(while (cdr tail)
(if (equal (car tail) (cadr tail))
@ -804,6 +806,7 @@ TO as (+ FROM (* N INC)) or use a variable whose value was
computed with this exact expression. Alternatively, you can,
of course, also replace TO with a slightly larger value
\(or a slightly more negative value if INC is negative)."
(declare (side-effect-free t))
(if (or (not to) (= from to))
(list from)
(or inc (setq inc 1))
@ -825,6 +828,7 @@ of course, also replace TO with a slightly larger value
If TREE is a cons cell, this recursively copies both its car and its cdr.
Contrast to `copy-sequence', which copies only along the cdrs. With second
argument VECP, this copies vectors as well as conses."
(declare (side-effect-free t))
(if (consp tree)
(let (result)
(while (consp tree)
@ -5266,11 +5270,13 @@ wherever possible, since it is slow."
(defsubst looking-at-p (regexp)
"\
Same as `looking-at' except this function does not change the match data."
(declare (side-effect-free t))
(looking-at regexp t))
(defsubst string-match-p (regexp string &optional start)
"\
Same as `string-match' except this function does not change the match data."
(declare (side-effect-free t))
(string-match regexp string start t))
(defun subregexp-context-p (regexp pos &optional start)
@ -5541,7 +5547,7 @@ Upper-case and lower-case letters are treated as equal.
Unibyte strings are converted to multibyte for comparison.
See also `string-equal'."
(declare (pure t) (side-effect-free t))
(declare (side-effect-free t))
(eq t (compare-strings string1 0 nil string2 0 nil t)))
(defun string-prefix-p (prefix string &optional ignore-case)
@ -5868,6 +5874,7 @@ integer that encodes the corresponding syntax class. See Info
node `(elisp)Syntax Table Internals' for a list of codes.
If SYNTAX is nil, return nil."
(declare (pure t) (side-effect-free t))
(and syntax (logand (car syntax) 65535)))
;; Utility motion commands
@ -6718,6 +6725,7 @@ Note that a version specified by the list (1) is equal to (1 0),
\(1 0 0), (1 0 0 0), etc. That is, the trailing zeros are insignificant.
Also, a version given by the list (1) is higher than (1 -1), which in
turn is higher than (1 -2), which is higher than (1 -3)."
(declare (pure t) (side-effect-free t))
(while (and l1 l2 (= (car l1) (car l2)))
(setq l1 (cdr l1)
l2 (cdr l2)))
@ -6739,6 +6747,7 @@ Note that a version specified by the list (1) is equal to (1 0),
\(1 0 0), (1 0 0 0), etc. That is, the trailing zeros are insignificant.
Also, a version given by the list (1) is higher than (1 -1), which in
turn is higher than (1 -2), which is higher than (1 -3)."
(declare (pure t) (side-effect-free t))
(while (and l1 l2 (= (car l1) (car l2)))
(setq l1 (cdr l1)
l2 (cdr l2)))
@ -6760,6 +6769,7 @@ Note that integer list (1) is equal to (1 0), (1 0 0), (1 0 0 0),
etc. That is, the trailing zeroes are insignificant. Also, integer
list (1) is greater than (1 -1) which is greater than (1 -2)
which is greater than (1 -3)."
(declare (pure t) (side-effect-free t))
(while (and l1 l2 (= (car l1) (car l2)))
(setq l1 (cdr l1)
l2 (cdr l2)))
@ -6777,6 +6787,7 @@ which is greater than (1 -3)."
"Return the first non-zero element of LST, which is a list of integers.
If all LST elements are zeros or LST is nil, return zero."
(declare (pure t) (side-effect-free t))
(while (and lst (zerop (car lst)))
(setq lst (cdr lst)))
(if lst
@ -6943,6 +6954,7 @@ REGEXP defaults to \"[ \\t\\n\\r]+\"."
"Trim STRING of trailing string matching REGEXP.
REGEXP defaults to \"[ \\t\\n\\r]+\"."
(declare (side-effect-free t))
(let ((i (string-match-p (concat "\\(?:" (or regexp "[ \t\n\r]+") "\\)\\'")
string)))
(if i (substring string 0 i) string)))
@ -7014,6 +7026,7 @@ sentence (see Info node `(elisp) Documentation Tips')."
"Return OBJECT as a list.
If OBJECT is already a list, return OBJECT itself. If it's
not a list, return a one-element list containing OBJECT."
(declare (side-effect-free error-free))
(if (listp object)
object
(list object)))
@ -7089,6 +7102,7 @@ is inserted before adjusting the number of empty lines."
If OMIT-NULLS, empty lines will be removed from the results.
If KEEP-NEWLINES, don't strip trailing newlines from the result
lines."
(declare (side-effect-free t))
(if (equal string "")
(if omit-nulls
nil

View file

@ -1399,8 +1399,8 @@ for determining whether point is within a selector."
:feature 'query
:language 'css
'((keyword_query) @font-lock-property-ref-face
(feature_name) @font-lock-property-ref-face)
'((keyword_query) @font-lock-property-use-face
(feature_name) @font-lock-property-use-face)
:feature 'bracket
:language 'css

View file

@ -92,8 +92,8 @@
:language 'toml
:feature 'pair
:override t ; Needed for overriding string face on keys.
'((bare_key) @font-lock-property-ref-face
(quoted_key) @font-lock-property-ref-face
'((bare_key) @font-lock-property-use-face
(quoted_key) @font-lock-property-use-face
(table ("[" @font-lock-bracket-face
(_) @font-lock-type-face
"]" @font-lock-bracket-face))

View file

@ -94,22 +94,22 @@
:feature 'property
:override t
'((block_mapping_pair
key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face)))
key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face)))
(block_mapping_pair
key: (flow_node
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face))
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face))
(flow_mapping
(_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face))))
(_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face))))
(flow_mapping
(_ key:
(flow_node
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face)))
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face)))
(flow_sequence
(_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-ref-face))))
(_ key: (flow_node (plain_scalar (string_scalar) @font-lock-property-use-face))))
(flow_sequence
(_ key:
(flow_node
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-ref-face))))
[(double_quote_scalar) (single_quote_scalar)] @font-lock-property-use-face))))
:language 'yaml
:feature 'error

View file

@ -1227,6 +1227,16 @@ See `treesit-simple-indent-presets'.")
(goto-char (treesit-node-start parent))
(back-to-indentation)
(point))))
(cons 'standalone-parent
(lambda (_n parent &rest _)
(save-excursion
(catch 'term
(while parent
(goto-char (treesit-node-start parent))
(when (looking-back (rx bol (* whitespace))
(line-beginning-position))
(throw 'term (point)))
(setq parent (treesit-node-parent parent)))))))
(cons 'prev-sibling (lambda (node &rest _)
(treesit-node-start
(treesit-node-prev-sibling node))))
@ -1323,6 +1333,11 @@ parent-bol
Returns the beginning of non-space characters on the line where
PARENT is on.
standalone-parent
Finds the first ancestor node (parent, grandparent, etc) that
starts on its own line, and return the start of that node.
prev-sibling
Returns the start of NODE's previous sibling.
@ -1854,10 +1869,23 @@ This is a tree-sitter equivalent of `beginning-of-defun'.
Behavior of this function depends on `treesit-defun-type-regexp'
and `treesit-defun-skipper'."
(interactive "^p")
(when (treesit-beginning-of-thing treesit-defun-type-regexp arg)
(when treesit-defun-skipper
(funcall treesit-defun-skipper))
t))
(let ((orig-point (point))
(success nil))
(catch 'done
(dotimes (_ 2)
(when (treesit-beginning-of-thing treesit-defun-type-regexp arg)
(when treesit-defun-skipper
(funcall treesit-defun-skipper)
(setq success t)))
;; If we end up at the same point, it means we went to the
;; next beg-of-defun, but defun skipper moved point back to
;; where we started, in this case we just move one step
;; further.
(if (or (eq arg 0) (not (eq orig-point (point))))
(throw 'done success)
(setq arg (if (> arg 0) (1+ arg) (1- arg))))))))
(defun treesit-end-of-defun (&optional arg _)
"Move forward to next end of defun.
@ -1869,9 +1897,21 @@ This is a tree-sitter equivalent of `end-of-defun'. Behavior of
this function depends on `treesit-defun-type-regexp' and
`treesit-defun-skipper'."
(interactive "^p\nd")
(when (treesit-end-of-thing treesit-defun-type-regexp arg)
(when treesit-defun-skipper
(funcall treesit-defun-skipper))))
(let ((orig-point (point)))
(catch 'done
(dotimes (_ 2) ; Not making progress is better than infloop.
(when (treesit-end-of-thing treesit-defun-type-regexp arg)
(when treesit-defun-skipper
(funcall treesit-defun-skipper)))
;; If we end up at the same point, it means we went to the
;; prev end-of-defun, but defun skipper moved point back to
;; where we started, in this case we just move one step
;; further.
(if (or (eq arg 0) (not (eq orig-point (point))))
(throw 'done nil)
(setq arg (if (> arg 0) (1+ arg) (1- arg))))))))
(defvar-local treesit-text-type-regexp "\\`comment\\'"
"A regexp that matches the node type of textual nodes.
@ -2027,9 +2067,9 @@ REGEXP and PRED are the same as in `treesit-thing-at-point'."
;;
;; prev-end (tricky):
;; 1. prev-sibling exists
;; -> If you think about it, we are already at prev-sibling's end!
;; So we need to go one step further, either to
;; prev-prev-sibling's end, or parent's prev-sibling's end, etc.
;; -> If we are already at prev-sibling's end, we need to go one
;; step further, either to prev-prev-sibling's end, or parent's
;; prev-sibling's end, etc.
;; 2. prev-sibling is nil but parent exists
;; -> Obviously we don't want to go to parent's end, instead, we
;; want to go to parent's prev-sibling's end. Again, we recurse
@ -2079,18 +2119,24 @@ function is called recursively."
;; ...forward.
(if (and (eq side 'beg)
;; Should we skip the defun (recurse)?
(cond (next (not recursing)) ; [1] (see below)
(parent t) ; [2]
(t nil)))
;; Special case: go to next beg-of-defun. Set POS
;; to the end of next-sib/parent defun, and run one
;; more step. If there is a next-sib defun, we only
;; need to recurse once, so we don't need to recurse
;; if we are already recursing [1]. If there is no
(cond (next (and (not recursing) ; [1] (see below)
(eq pos (funcall advance next))))
(parent t))) ; [2]
;; Special case: go to next beg-of-defun, but point
;; is already on beg-of-defun. Set POS to the end
;; of next-sib/parent defun, and run one more step.
;; If there is a next-sib defun, we only need to
;; recurse once, so we don't need to recurse if we
;; are already recursing [1]. If there is no
;; next-sib but a parent, keep stepping out
;; (recursing) until we got out of the parents until
;; (1) there is a next sibling defun, or (2) no more
;; parents [2].
;;
;; If point on beg-of-defun but we are already
;; recurring, that doesn't count as special case,
;; because we have already made progress (by moving
;; the end of next before recurring.)
(setq pos (or (treesit--navigate-thing
(treesit-node-end (or next parent))
1 'beg regexp pred t)
@ -2099,9 +2145,9 @@ function is called recursively."
(setq pos (funcall advance (or next parent))))
;; ...backward.
(if (and (eq side 'end)
(cond (prev (not recursing))
(parent t)
(t nil)))
(cond (prev (and (not recursing)
(eq pos (funcall advance prev))))
(parent t)))
;; Special case: go to prev end-of-defun.
(setq pos (or (treesit--navigate-thing
(treesit-node-start (or prev parent))

View file

@ -428,6 +428,8 @@ s/= @GL_GENERATE_STDINT_H_CONDITION@/= 1/
s/= @GL_GENERATE_LIMITS_H_CONDITION@/= 1/
s/= @GL_GENERATE_ERRNO_H_CONDITION@/= /
s/= @GL_GENERATE_LIMITS_H_CONDITION@/= /
s/= @GL_GENERATE_GETOPT_CDEFS_H_CONDITION@/= 1/
s/= @GL_GENERATE_GETOPT_H_CONDITION@/= 1/
s/= @GL_GENERATE_GMP_H_CONDITION@/= 1/
s/= @GL_GENERATE_GMP_GMP_H_CONDITION@/= /
s/= @GL_GENERATE_MINI_GMP_H_CONDITION@/= 1/

View file

@ -170,3 +170,6 @@ gl_cv_func_free_preserves_errno=yes
# Don't build the Gnulib nanosleep module: it requires W2K or later,
# and MinGW does have nanosleep.
gl_cv_func_nanosleep=yes
# Suppress configure-time diagnostic from unnecessary libxattr check,
# as xattr will not be supported here.
enable_xattr=no

View file

@ -2401,7 +2401,7 @@ whether or not it is currently displayed in some window. */)
last line that it occupies. */
if (it_start < ZV)
{
if ((it.bidi_it.scan_dir > 0)
if ((it.bidi_it.scan_dir >= 0 || it.vpos == vpos_init)
? IT_CHARPOS (it) < it_start
: IT_CHARPOS (it) > it_start)
{

View file

@ -2484,7 +2484,7 @@ treesit_predicate_match (Lisp_Object args, struct capture_range captures)
{
if (XFIXNUM (Flength (args)) != 2)
xsignal2 (Qtreesit_query_error,
build_string ("Predicate `equal' requires two "
build_string ("Predicate `match' requires two "
"arguments but only given"),
Flength (args));

View file

@ -1446,6 +1446,12 @@ literals (Bug#20852)."
'((suspicious set-buffer))
"Warning: Use .with-current-buffer. rather than")
(test-suppression
'(defun zot (x)
(condition-case nil (list x)))
'((suspicious condition-case))
"Warning: `condition-case' without handlers")
(test-suppression
'(defun zot ()
(let ((_ 1))

View file

@ -119,9 +119,10 @@ provide HTML fragments. Some tests override those variables."
(ert-deftest sgml-html-meta-no-post-less-than-10lines ()
"No '</head>', detect charset in the first 10 lines."
(let ((sgml-html-meta-post ""))
(should (eq 'utf-8 (sgml-html-meta-run
(concat "\n\n\n\n\n\n\n\n\n"
"<meta charset='utf-8'>"))))))
(should (eq 'utf-8 (coding-system-base
(sgml-html-meta-run
(concat "\n\n\n\n\n\n\n\n\n"
"<meta charset='utf-8'>")))))))
(ert-deftest sgml-html-meta-no-post-10lines ()
"No '</head>', do not detect charset after the first 10 lines."

View file

@ -6535,11 +6535,33 @@ INPUT, if non-nil, is a string sent to the process."
(save-buffer)
(should-not (buffer-modified-p)))
(should-not (with-no-warnings (file-locked-p tmp-name1)))
;; `kill-buffer' removes the lock.
(with-no-warnings (lock-file tmp-name1))
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
(with-temp-buffer
(set-visited-file-name tmp-name1)
(insert "foo")
(should (buffer-modified-p))
(cl-letf (((symbol-function #'read-from-minibuffer)
(lambda (&rest _args) "yes")))
(kill-buffer)))
(should-not (with-no-warnings (file-locked-p tmp-name1)))
;; `kill-buffer' should not remove the lock when the
;; connection is broken. See Bug#61663.
(with-no-warnings (lock-file tmp-name1))
(should (eq (with-no-warnings (file-locked-p tmp-name1)) t))
(with-temp-buffer
(set-visited-file-name tmp-name1)
(insert "foo")
(should (buffer-modified-p))
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(cl-letf (((symbol-function #'read-from-minibuffer)
(lambda (&rest _args) "yes")))
(kill-buffer)))
;; A new connection changes process id, and also the
;; lockname contents.
;; lockname contents. But the lock file still exists.
(tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password)
(should (stringp (with-no-warnings (file-locked-p tmp-name1))))

View file

@ -856,8 +856,8 @@ pylsp prefers autopep over yafp, despite its README stating the contrary."
'((c-mode . ("clangd")))))
(with-current-buffer
(eglot--find-file-noselect "project/foo.c")
(setq-local eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column)
(setq-local eglot-current-column-function #'eglot-lsp-abiding-column)
(setq-local eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos)
(setq-local eglot-current-linepos-function #'eglot-utf-16-linepos)
(eglot--sniffing (:client-notifications c-notifs)
(eglot--tests-connect)
(end-of-line)
@ -866,12 +866,12 @@ pylsp prefers autopep over yafp, despite its README stating the contrary."
(eglot--wait-for (c-notifs 2) (&key params &allow-other-keys)
(should (equal 71 (cadddr (cadadr (aref (cadddr params) 0))))))
(beginning-of-line)
(should (eq eglot-move-to-column-function #'eglot-move-to-lsp-abiding-column))
(funcall eglot-move-to-column-function 71)
(should (eq eglot-move-to-linepos-function #'eglot-move-to-utf-16-linepos))
(funcall eglot-move-to-linepos-function 71)
(should (looking-at "p")))))))
(ert-deftest eglot-test-lsp-abiding-column ()
"Test basic `eglot-lsp-abiding-column' and `eglot-move-to-lsp-abiding-column'."
"Test basic LSP character counting logic."
(skip-unless (executable-find "clangd"))
(eglot-tests--lsp-abiding-column-1))

View file

@ -66,4 +66,18 @@
(cl-letf (((symbol-function 'w32-shell-dos-semantics) #'ignore))
(grep-tests--check-rgrep-abbreviation))))
(ert-deftest grep-tests--grep-heading-regexp-without-null ()
(dolist (sep '(?: ?- ?=))
(let ((string (format "filename%c123%ctext" sep sep)))
(should (string-match grep-heading-regexp string))
(should (equal (match-string 1 string) "filename"))
(should (equal (match-string 2 string) (format "filename%c" sep))))))
(ert-deftest grep-tests--grep-heading-regexp-with-null ()
(dolist (sep '(?: ?- ?=))
(let ((string (format "funny:0:filename%c123%ctext" 0 sep)))
(should (string-match grep-heading-regexp string))
(should (equal (match-string 1 string) "funny:0:filename"))
(should (equal (match-string 2 string) "funny:0:filename\0")))))
;;; grep-tests.el ends here

View file

@ -10,6 +10,10 @@
foo = obj.bar { |m| tee(m) } +
obj.qux { |m| hum(m) }
some_variable = abc + some_method(
some_argument
)
foo.
bar
.baz

View file

@ -1171,5 +1171,39 @@ final or penultimate step during initialization."))
(should-not (list-of-strings-p '("a" nil "b")))
(should-not (list-of-strings-p '("a" "b" . "c"))))
(ert-deftest subr--delete-dups ()
(should (equal (delete-dups nil) nil))
(let* ((a (list "a" "b" "c"))
(a-dedup (delete-dups a)))
(should (equal a-dedup '("a" "b" "c")))
(should (eq a a-dedup)))
(let* ((a (list "a" "a" "b" "b" "a" "c" "b" "c" "a"))
(a-b (cddr a)) ; link of first "b"
(a-dedup (delete-dups a)))
(should (equal a-dedup '("a" "b" "c")))
(should (eq a a-dedup))
(should (eq (cdr a-dedup) a-b))))
(ert-deftest subr--delete-consecutive-dups ()
(should (equal (delete-consecutive-dups nil) nil))
(let* ((a (list "a" "b" "c"))
(a-dedup (delete-consecutive-dups a)))
(should (equal a-dedup '("a" "b" "c")))
(should (eq a a-dedup)))
(let* ((a (list "a" "a" "b" "a" "a" "b" "b" "b" "c" "c" "a" "a"))
(a-b (nthcdr 3 a)) ; link of third "a"
(a-dedup (delete-consecutive-dups a)))
(should (equal a-dedup '("a" "b" "a" "b" "c" "a")))
(should (eq a a-dedup))
(should (equal (nthcdr 2 a-dedup) a-b)))
(let* ((a (list "a" "b" "a"))
(a-dedup (delete-consecutive-dups a t)))
(should (equal a-dedup '("a" "b")))
(should (eq a a-dedup)))
(let* ((a (list "a" "a" "b" "a" "a" "b" "b" "b" "c" "c" "a" "a"))
(a-dedup (delete-consecutive-dups a t)))
(should (equal a-dedup '("a" "b" "a" "b" "c")))
(should (eq a a-dedup))))
(provide 'subr-tests)
;;; subr-tests.el ends here

View file

@ -977,22 +977,22 @@ and \"]\"."
(defvar treesit--ert-defun-navigation-nested-master
;; START PREV-BEG NEXT-END PREV-END NEXT-BEG
'((0 103 105 102 106) ; Between Beg of parent & 1st sibling.
'((0 103 105 102 104) ; Between Beg of parent & 1st sibling.
(1 103 105 102 106) ; Beg of 1st sibling.
(2 104 105 102 106) ; Inside 1st sibling.
(3 104 107 102 109) ; End of 1st sibling.
(4 104 107 102 109) ; Between 1st sibling & 2nd sibling.
(5 104 107 102 109) ; Beg of 2nd sibling.
(3 104 107 102 106) ; End of 1st sibling.
(4 104 107 105 106) ; Between 1st sibling & 2nd sibling.
(5 104 107 105 109) ; Beg of 2nd sibling.
(6 106 107 105 109) ; Inside 2nd sibling.
(7 106 108 105 109) ; End of 2nd sibling.
(8 106 108 105 109) ; Between 2nd sibling & end of parent.
(9 103 110 102 nil) ; End of parent.
(8 106 108 107 109) ; Between 2nd sibling & end of parent.
(9 103 110 102 109) ; End of parent.
(100 nil 102 nil 103) ; Before 1st parent.
(100 nil 102 nil 101) ; Before 1st parent.
(101 nil 102 nil 103) ; Beg of 1st parent.
(102 101 108 nil 109) ; Between 1st & 2nd parent.
(103 101 108 nil 109) ; Beg of 2nd parent.
(110 109 nil 108 nil) ; After 3rd parent.
(102 101 108 102 103) ; Between 1st & 2nd parent.
(103 101 108 102 109) ; Beg of 2nd parent.
(110 109 nil 110 nil) ; After 3rd parent.
)
"Master of nested navigation test.
@ -1000,7 +1000,7 @@ This basically says, e.g., \"start with point on marker 0, go to
the prev-beg, now point should be at marker 103\", etc.")
(defvar treesit--ert-defun-navigation-top-level-master
;; START PREV-BEG NEXT-END NEXT-BEG PREV-END
;; START PREV-BEG NEXT-END PREV-END NEXT-BEG
'((0 103 108 102 109) ; Between Beg of parent & 1st sibling.
(1 103 108 102 109) ; Beg of 1st sibling.
(2 103 108 102 109) ; Inside 1st sibling.
@ -1010,14 +1010,14 @@ the prev-beg, now point should be at marker 103\", etc.")
(6 103 108 102 109) ; Inside 2nd sibling.
(7 103 108 102 109) ; End of 2nd sibling.
(8 103 108 102 109) ; Between 2nd sibling & end of parent.
(9 103 110 102 nil) ; End of parent.
(9 103 110 102 109) ; End of parent.
;; Top-level defuns should be identical to the nested test.
(100 nil 102 nil 103) ; Before 1st parent.
(100 nil 102 nil 101) ; Before 1st parent.
(101 nil 102 nil 103) ; Beg of 1st parent.
(102 101 108 nil 109) ; Between 1st & 2nd parent.
(103 101 108 nil 109) ; Beg of 2nd parent.
(110 109 nil 108 nil) ; After 3rd parent.
(102 101 108 102 103) ; Between 1st & 2nd parent.
(103 101 108 102 109) ; Beg of 2nd parent.
(110 109 nil 110 nil) ; After 3rd parent.
)
"Master of top-level navigation test.")