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

This commit is contained in:
Po Lu 2023-01-19 22:20:23 +08:00
commit f99f759931
42 changed files with 902 additions and 300 deletions

View file

@ -1331,11 +1331,18 @@ point is on a directory entry, mark all files in that directory tree
listed files and directories.
@findex vc-dir-mark-by-regexp
@item %
@item % m
@itemx * %
You can use this command to mark files by regexp
(@code{vc-dir-mark-by-regexp}). If given a prefix, unmark files
instead.
@findex vc-dir-mark-registered-files
@item * r
You can use this command to mark files that are in one of registered
states, including edited, added or removed.
(@code{vc-dir-mark-registered-files}).
@item G
Add the file under point to the list of files that the VC should
ignore (@code{vc-dir-ignore}). For instance, if the VC is Git, it

View file

@ -430,10 +430,15 @@ For example, one element normally found in the list has the form
mode for files whose names end in @file{.c}. (Note that @samp{\\} is
needed in Lisp syntax to include a @samp{\} in the string, which must
be used to suppress the special meaning of @samp{.} in regexps.) If
the element has the form @code{(@var{regexp} @var{mode-function}
@var{flag})} and @var{flag} is non-@code{nil}, then after calling
@var{mode-function}, Emacs discards the suffix that matched
@var{regexp} and searches the list again for another match.
the element has the form @w{@code{(@var{regexp} @var{mode-function}
@var{flag})}} and @var{flag} is non-@code{nil}, then after calling
@var{mode-function} (if it is non-@code{nil}), Emacs discards the
suffix that matched @var{regexp} and searches the list again for
another match. This ``recursive extension stripping'' is used for
files which have multiple extensions, and the ``outer'' extension
hides the ``inner'' one that actually specifies the right mode. For
example, backup files and GPG-encrypted files with @file{.gpg}
extension use this feature.
@vindex auto-mode-case-fold
On GNU/Linux and other systems with case-sensitive file names, Emacs

View file

@ -312,7 +312,7 @@ to @code{regexp-history}.
@cindex @code{case-fold}, text property
@findex read-regexp-case-fold-search
The user can use the @kbd{M-c} command to indicate whether case
The user can use the @kbd{M-s c} command to indicate whether case
folding should be on or off. If the user has used this command, the
returned string will have the text property @code{case-fold} set to
either @code{fold} or @code{inhibit-fold}. It is up to the caller of

View file

@ -911,8 +911,8 @@ This function returns a new string containing one character,
@end defun
@defun string-to-char string
This function returns the first character in @var{string}. This
mostly identical to @code{(aref string 0)}, except that it returns 0
This function returns the first character in @var{string}. This is
mostly identical to @w{@code{(aref string 0)}}, except that it returns 0
if the string is empty. (The value is also 0 when the first character
of @var{string} is the null character, @acronym{ASCII} code 0.) This
function may be eliminated in the future if it does not seem useful

View file

@ -64,10 +64,11 @@ modify this GNU manual.''
Eshell is a shell-like command interpreter implemented in Emacs Lisp.
It invokes no external processes except for those requested by the
user. It is intended to be an alternative to the IELM (@pxref{Lisp Interaction, Emacs Lisp Interaction, , emacs, The Emacs Editor})
REPL for Emacs @emph{and} with an interface similar to command shells
such as @command{bash}, @command{zsh}, @command{rc}, or
@command{4dos}.
user. It is intended to be an alternative to the IELM (@pxref{Lisp
Interaction, Emacs Lisp Interaction, , emacs, The Emacs Editor})
REPL@footnote{Short for ``Read-Eval-Print Loop''.} for Emacs
@emph{and} with an interface similar to command shells such as
@command{bash}, @command{zsh}, @command{rc}, or @command{4dos}.
@c This manual is updated to release 2.4 of Eshell.
@insertcopying
@ -193,6 +194,13 @@ In a command shell, everything is done by invoking commands. This
chapter covers command invocations in Eshell, including the command
history and invoking commands in a script file.
Unlike regular system shells, Eshell never invokes kernel functions
directly, such as @code{exec(3)}. Instead, it uses the Lisp functions
available in the Emacs Lisp library. It does this by transforming the
input line into a callable Lisp form.@footnote{To see the Lisp form
that will be invoked, type this as the Eshell prompt:
@kbd{eshell-parse-command 'echo hello'}}
@menu
* Invocation::
* Arguments::
@ -207,23 +215,16 @@ history and invoking commands in a script file.
@node Invocation
@section Invocation
Unlike regular system shells, Eshell never invokes kernel functions
directly, such as @code{exec(3)}. Instead, it uses the Lisp functions
available in the Emacs Lisp library. It does this by transforming the
input line into a callable Lisp form.@footnote{To see the Lisp form that will be invoked, type: @samp{eshell-parse-command "echo hello"}}
Eshell is both a command shell and an Emacs Lisp @acronym{REPL}. As a
result, you can invoke commands in two different ways: in @dfn{command
form} or in @dfn{lisp form}.
The command can be either an Elisp function or an external command.
Eshell looks first for an alias (@pxref{Aliases}) with the same name as the
command, then a built-in (@pxref{Built-ins}) or a function with the
same name; if there is no match, it then tries to execute it as an
external command.
The semicolon (@code{;}) can be used to separate multiple command
invocations on a single line. You can also separate commands with
@code{&&} or @code{||}. When using @code{&&}, Eshell will execute the
second command only if the first succeeds (i.e.@: has an exit
status of 0); with @code{||}, Eshell will execute the second command
only if the first fails.
You can use the semicolon (@code{;}) to separate multiple command
invocations on a single line, executing each in turn. You can also
separate commands with @code{&&} or @code{||}. When using @code{&&},
Eshell will execute the second command only if the first succeeds
(i.e.@: has an exit status of 0); with @code{||}, Eshell will execute
the second command only if the first fails.
A command invocation followed by an ampersand (@code{&}) will be run
in the background. Eshell has no job control, so you can not suspend
@ -232,12 +233,80 @@ the foreground. That said, background processes invoked from Eshell
can be controlled the same way as any other background process in
Emacs.
@subsection Command form
Command form looks much the same as in other shells. A command
consists of arguments separated by spaces; the first argument is the
command to run, with any subsequent arguments being passed to that
command.
@example
~ $ echo hello
hello
@end example
@cindex order of looking for commands
@cindex command lookup order
The command can be either an Elisp function or an external command.
Eshell looks for the command in the following order:
@enumerate
@item
As a command alias (@pxref{Aliases})
@item
As a built-in command (@pxref{Built-ins})
@item
As an external program
@item
As an ordinary Lisp function
@end enumerate
@vindex eshell-prefer-lisp-functions
If you would prefer to use ordinary Lisp functions over external
programs, set the option @code{eshell-prefer-lisp-functions} to
@code{t}. This will swap the lookup order of the last two items.
You can also group command forms together into a subcommand with curly
braces (@code{@{@}}). This lets you use the output of a subcommand as
an argument to another command, or within control flow statements
(@pxref{Control Flow}).
@example
~ $ echo @{echo hello; echo there@}
hellothere
@end example
@subsection Lisp form
Lisp form looks like ordinary Emacs Lisp code, because that's what it
is. As a result, you can use any syntax normally available to an
Emacs Lisp program (@pxref{Top, , , elisp, The Emacs Lisp Reference
Manual}).
@example
~ $ (format "hello, %s" user-login-name)
hello, user
@end example
In addition, you can @emph{combine} command forms and Lisp forms
together into single statements, letting you use whatever form is the
most convenient for expressing your intentions.
@example
~ $ ls *.patch > (format-time-string "%F.log")
@end example
This command writes a list of all files matching the glob pattern
@code{*.patch} (@pxref{Globbing}) to a file named
@code{@var{current-date}.log} (@pxref{Redirection}).
@node Arguments
@section Arguments
Ordinarily, command arguments are parsed by Eshell as either strings
Ordinarily, Eshell parses arguments in command form as either strings
or numbers, depending on what the parser thinks they look like. To
specify an argument of some other data type, you can use an
@ref{Dollars Expansion, Elisp expression}:
specify an argument of some other data type, you can use a Lisp form
(@pxref{Invocation}):
@example
~ $ echo (list 1 2 3)
@ -354,10 +423,6 @@ eshell/sudo is a compiled Lisp function in `em-tramp.el'.
sudo is an alias, defined as "*sudo $@@*"
@end example
@vindex eshell-prefer-lisp-functions
If you would prefer to use the built-in commands instead of the external
commands, set @code{eshell-prefer-lisp-functions} to @code{t}.
Some of the built-in commands have different behavior from their
external counterparts, and some have no external counterpart. Most of
these will print a usage message when given the @code{--help} option.
@ -923,15 +988,14 @@ For example, you could handle a subset of the options for the
@node Variables
@section Variables
@vindex eshell-prefer-lisp-variables
Since Eshell is a combination of an Emacs @acronym{REPL}@footnote{
Short for ``Read-Eval-Print Loop''.
} and a command shell, it can refer to variables from two different
sources: ordinary Emacs Lisp variables, as well as environment
variables. By default, when using a variable in Eshell, it will first
look in the list of built-in variables, then in the list of
environment variables, and finally in the list of Lisp variables. If
you would prefer to use Lisp variables over environment variables, you
can set @code{eshell-prefer-lisp-variables} to @code{t}.
Since Eshell is a combination of an Emacs @acronym{REPL} and a command
shell, it can refer to variables from two different sources: ordinary
Emacs Lisp variables, as well as environment variables. By default,
when using a variable in Eshell, it will first look in the list of
built-in variables, then in the list of environment variables, and
finally in the list of Lisp variables. If you would prefer to use
Lisp variables over environment variables, you can set
@code{eshell-prefer-lisp-variables} to @code{t}.
You can set variables in a few different ways. To set a Lisp
variable, you can use the command @samp{setq @var{name} @var{value}},

View file

@ -2079,7 +2079,7 @@ The VC Directory buffer now uses the prefix 'b' for these branch-related
commands.
+++
*** New command '%' ('vc-dir-mark-by-regexp').
*** New command 'vc-dir-mark-by-regexp' bound to '% m' and '* %'.
This command marks files based on a regexp. If given a prefix
argument, unmark instead.
@ -3235,6 +3235,11 @@ programs in the C language.
An optional major mode based on the tree-sitter library for editing
programs in the C++ language.
+++
*** New command 'c-or-c++-ts-mode'.
A command that automatically guesses the language of a header file,
and enables either 'c-ts-mode' or 'c++-ts-mode' accordingly.
+++
*** New major mode 'java-ts-mode'.
An optional major mode based on the tree-sitter library for editing
@ -3802,7 +3807,7 @@ These function now take an optional comparison PREDICATE argument.
** 'read-multiple-choice' can now use long-form answers.
+++
** 'M-c' in 'read-regexp' now toggles case folding.
** 'M-s c' in 'read-regexp' now toggles case folding.
+++
** 'completing-read' now allows a function as its REQUIRE-MATCH argument.

View file

@ -1772,10 +1772,16 @@ It is too wide if it has any lines longer than the largest of
kind name col))
;; There's a "naked" ' character before a symbol/list, so it
;; should probably be quoted with \=.
(when (string-match-p "\\( [\"#]\\|[ \t]\\|^\\)'[a-z(]" docs)
(when (string-match-p (rx (| (in " \t") bol)
(? (in "\"#"))
"'"
(in "A-Za-z" "("))
docs)
(byte-compile-warn-x
name "%s%sdocstring has wrong usage of unescaped single quotes (use \\= or different quoting)"
kind name))
name
(concat "%s%sdocstring has wrong usage of unescaped single quotes"
" (use \\=%c or different quoting such as %c...%c)")
kind name ?' ?` ?'))
;; There's a "Unicode quote" in the string -- it should probably
;; be an ASCII one instead.
(when (byte-compile-warning-enabled-p 'docstrings-non-ascii-quotes)

View file

@ -2811,7 +2811,7 @@ values. Note that this macro is *not* available in Common Lisp.
As a special case, if `(PLACE)' is used instead of `(PLACE VALUE)',
the PLACE is not modified before executing BODY.
See info node `(cl) Function Bindings' for details.
See info node `(cl) Modify Macros' for details.
\(fn ((PLACE VALUE) ...) BODY...)"
(declare (indent 1) (debug ((&rest [&or (symbolp form)

View file

@ -458,12 +458,13 @@ Assumes the caller has bound `macroexpand-all-environment'."
(let ((arg (nth funarg form)))
(when (and (eq 'quote (car-safe arg))
(eq 'lambda (car-safe (cadr arg))))
(setcar (nthcdr funarg form)
(macroexp-warn-and-return
(format "%S quoted with ' rather than with #'"
(let ((f (cadr arg)))
(if (symbolp f) f `(lambda ,(nth 1 f) ...))))
arg nil nil (cadr arg))))))
(setcar
(nthcdr funarg form)
(macroexp-warn-and-return
(format
"(lambda %s ...) quoted with ' rather than with #'"
(or (nth 1 (cadr arg)) "()"))
arg nil nil (cadr arg))))))
;; Macro expand compiler macros. This cannot be delayed to
;; byte-optimize-form because the output of the compiler-macro can
;; use macros.

View file

@ -204,8 +204,12 @@ SUPPRESS-LIST is the list of kinds of warnings to suppress."
some-match))
(define-icon warnings-suppress button
'((emoji "")
(symbol "")
`((emoji "")
;; Many MS-Windows console fonts don't have good glyphs for U+25A0.
(symbol ,(if (and (eq system-type 'windows-nt)
(null window-system))
" » "
""))
(text " stop "))
"Suppress warnings."
:version "29.1"

View file

@ -202,12 +202,13 @@ if ARG is omitted or nil.
(,disable)))
,(erc--assemble-toggle local-p name enable mode t enable-body)
,(erc--assemble-toggle local-p name disable mode nil disable-body)
,(when (and alias (not (eq name alias)))
`(defalias
',(intern
(format "erc-%s-mode"
(downcase (symbol-name alias))))
#',mode))
,@(and-let* ((alias)
((not (eq name alias)))
(aname (intern (format "erc-%s-mode"
(downcase (symbol-name alias))))))
`((defalias ',aname #',mode)
(put ',aname 'erc-module ',(erc--normalize-module-symbol name))))
(put ',mode 'erc-module ',(erc--normalize-module-symbol name))
;; For find-function and find-variable.
(put ',mode 'definition-name ',name)
(put ',enable 'definition-name ',name)

View file

@ -260,8 +260,8 @@ If START or END is negative, it counts from the end."
(dolist (e rv out)
(when-let* ((s (plist-get e :secret))
(v (auth-source--obfuscate s)))
(setf (plist-get e :secret)
(apply-partially #'auth-source--deobfuscate v)))
(setq e (plist-put e :secret (apply-partially
#'auth-source--deobfuscate v))))
(push e out)))
rv)))

View file

@ -1305,6 +1305,14 @@ See also `erc-show-my-nick'."
(defvar-local erc-dbuf nil)
;; See comments in `erc-scenarios-base-local-modules' explaining why
;; this is insufficient as a public interface.
(defvar erc--target-priors nil
"Analogous to `erc--server-reconnecting' but for target buffers.
Bound to local variables from an existing (logical) session's
buffer during local-module setup and `erc-mode-hook' activation.")
(defun erc--target-from-string (string)
"Construct an `erc--target' variant from STRING."
(funcall (if (erc-channel-p string)
@ -1950,7 +1958,8 @@ nil."
(let ((out (list (reverse new-modes))))
(pcase-dolist (`(,k . ,v) old-vars)
(when (and (string-prefix-p "erc-" (symbol-name k))
(string-suffix-p "-mode" (symbol-name k)))
(string-suffix-p "-mode" (symbol-name k))
(get k 'erc-module))
(if v
(cl-pushnew k (car out))
(setf (car out) (delq k (car out)))
@ -1985,7 +1994,9 @@ Returns the buffer for the given server or channel."
(let* ((target (and channel (erc--target-from-string channel)))
(buffer (erc-get-buffer-create server port nil target id))
(old-buffer (current-buffer))
(old-vars (and target (buffer-local-variables)))
(erc--target-priors (and target ; buf from prior session
(buffer-local-value 'erc--target buffer)
(buffer-local-variables buffer)))
(old-recon-count erc-server-reconnect-count)
(old-point nil)
(delayed-modules nil)
@ -1998,7 +2009,8 @@ Returns the buffer for the given server or channel."
(setq old-point (point))
(setq delayed-modules
(erc--merge-local-modes (erc--update-modules)
(or erc--server-reconnecting old-vars)))
(or erc--server-reconnecting
erc--target-priors)))
(delay-mode-hooks (erc-mode))
@ -2071,9 +2083,7 @@ Returns the buffer for the given server or channel."
(erc-determine-parameters server port nick full-name user passwd)
(save-excursion (run-mode-hooks))
(dolist (mod (car delayed-modules)) (funcall mod +1))
(dolist (var (cdr delayed-modules)) (set var nil))
;; FIXME consolidate this prompt-setup logic with the pass above.
;; set up prompt
(unless continued-session
@ -2086,6 +2096,10 @@ Returns the buffer for the given server or channel."
(erc-display-prompt)
(goto-char (point-max)))
(save-excursion (run-mode-hooks)
(dolist (mod (car delayed-modules)) (funcall mod +1))
(dolist (var (cdr delayed-modules)) (set var nil)))
;; Saving log file on exit
(run-hook-with-args 'erc-connect-pre-hook buffer)

View file

@ -132,7 +132,8 @@ or `eshell-printn' for display."
;; bug#27361.
(when (equal output-newline '(nil))
(display-warning
:warning "To terminate with a newline, you should use -N instead."))
'(eshell echo)
"To terminate with a newline, you should use -N instead."))
(eshell-echo args output-newline))))
(defun eshell/printnl (&rest args)

View file

@ -628,9 +628,10 @@ If QUOTED is non-nil, this was invoked inside double-quotes."
(if (or (eq max-arity 'many) (>= max-arity 2))
(funcall target indices quoted)
(display-warning
:warning (concat "Function for `eshell-variable-aliases-list' "
"entry should accept two arguments: INDICES "
"and QUOTED.'"))
'(eshell variable-alias)
(concat "Function for `eshell-variable-aliases-list' "
"entry should accept two arguments: INDICES "
"and QUOTED.'"))
(funcall target indices)))))
((symbolp target)
(eshell-apply-indices (symbol-value target) indices quoted))

View file

@ -5059,7 +5059,8 @@ This is a separate procedure so your site-init or startup file can
redefine it.
If the optional argument KEEP-BACKUP-VERSION is non-nil,
we do not remove backup version numbers, only true file version numbers.
See also `file-name-version-regexp'."
See `file-name-version-regexp' for what constitutes backup versions
and version strings."
(let ((handler (find-file-name-handler name 'file-name-sans-versions)))
(if handler
(funcall handler 'file-name-sans-versions name keep-backup-version)
@ -5111,9 +5112,12 @@ the group would be preserved too."
(file-attribute-group-id attributes)))))))))))
(defun file-name-sans-extension (filename)
"Return FILENAME sans final \"extension\".
"Return FILENAME sans final \"extension\" and any backup version strings.
The extension, in a file name, is the part that begins with the last `.',
except that a leading `.' of the file name, if there is one, doesn't count."
except that a leading `.' of the file name, if there is one, doesn't count.
Any extensions that indicate backup versions and version strings are
removed by calling `file-name-sans-versions', which see, before looking
for the \"real\" file extension."
(save-match-data
(let ((file (file-name-sans-versions (file-name-nondirectory filename)))
directory)
@ -5127,12 +5131,14 @@ except that a leading `.' of the file name, if there is one, doesn't count."
filename))))
(defun file-name-extension (filename &optional period)
"Return FILENAME's final \"extension\".
"Return FILENAME's final \"extension\" sans any backup version strings.
The extension, in a file name, is the part that begins with the last `.',
excluding version numbers and backup suffixes, except that a leading `.'
of the file name, if there is one, doesn't count.
except that a leading `.' of the file name, if there is one, doesn't count.
This function calls `file-name-sans-versions', which see, to remove from
the extension it returns any parts that indicate backup versions and
version strings.
Return nil for extensionless file names such as `foo'.
Return the empty string for file names such as `foo.'.
Return the empty string for file names such as `foo.' that end in a period.
By default, the returned value excludes the period that starts the
extension, but if the optional argument PERIOD is non-nil, the period

View file

@ -4379,6 +4379,10 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
;; or return nil meaning don't make a backup.
(if ange-ftp-make-backup-files
(ange-ftp-real-find-backup-file-name fn)))
(defun ange-ftp-file-user-uid ()
;; Return "don't know" value.
-1)
;;; Define the handler for special file names
;;; that causes ange-ftp to be invoked.
@ -4519,6 +4523,9 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
(put 'file-notify-add-watch 'ange-ftp 'ignore)
(put 'file-notify-rm-watch 'ange-ftp 'ignore)
(put 'file-notify-valid-p 'ange-ftp 'ignore)
;; Return the "don't know' value for remote user uid.
(put 'file-user-uid 'ange-ftp 'ange-ftp-file-user-uid)
;;; Define ways of getting at unmodified Emacs primitives,
;;; turning off our handler.

View file

@ -670,6 +670,13 @@ offered."
(setq local (expand-file-name local (file-name-directory localname))))
(concat (file-truename archive) local))))
(defun tramp-archive-handle-file-user-uid ()
"Like `user-uid' for file archives."
(with-parsed-tramp-archive-file-name default-directory nil
(let ((default-directory (file-name-directory archive)))
;; `file-user-uid' exists since Emacs 30.1.
(tramp-compat-funcall 'file-user-uid))))
(defun tramp-archive-handle-insert-directory
(filename switches &optional wildcard full-directory-p)
"Like `insert-directory' for file archives."
@ -702,12 +709,6 @@ offered."
(let ((default-directory (file-name-directory archive)))
(temporary-file-directory))))
(defun tramp-archive-handle-file-user-uid ()
"Like `user-uid' for file archives."
(with-parsed-tramp-archive-file-name default-directory nil
(let ((default-directory (file-name-directory archive)))
(file-user-uid))))
(defun tramp-archive-handle-not-implemented (operation &rest args)
"Generic handler for operations not implemented for file archives."
(let ((v (ignore-errors

View file

@ -204,7 +204,7 @@ If NAME doesn't belong to an encrypted remote directory, return nil."
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-crypt-handle-file-system-info)
;; `file-truename' performed by default handler.
(file-user-uid . tramp-handle-file-user-uid)
;; `file-user-uid' performed by default-handler.
(file-writable-p . tramp-crypt-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.

View file

@ -976,6 +976,50 @@ This mode is independent from the classic cc-mode.el based
(treesit-major-mode-setup)))
;; We could alternatively use parsers, but if this works well, I don't
;; see the need to change. This is copied verbatim from cc-guess.el.
(defconst c-ts-mode--c-or-c++-regexp
(eval-when-compile
(let ((id "[a-zA-Z_][a-zA-Z0-9_]*") (ws "[ \t]+") (ws-maybe "[ \t]*")
(headers '("string" "string_view" "iostream" "map" "unordered_map"
"set" "unordered_set" "vector" "tuple")))
(concat "^" ws-maybe "\\(?:"
"using" ws "\\(?:namespace" ws
"\\|" id "::"
"\\|" id ws-maybe "=\\)"
"\\|" "\\(?:inline" ws "\\)?namespace"
"\\(:?" ws "\\(?:" id "::\\)*" id "\\)?" ws-maybe "{"
"\\|" "class" ws id
"\\(?:" ws "final" "\\)?" ws-maybe "[:{;\n]"
"\\|" "struct" ws id "\\(?:" ws "final" ws-maybe "[:{\n]"
"\\|" ws-maybe ":\\)"
"\\|" "template" ws-maybe "<.*?>"
"\\|" "#include" ws-maybe "<" (regexp-opt headers) ">"
"\\)")))
"A regexp applied to C header files to check if they are really C++.")
;;;###autoload
(defun c-or-c++-ts-mode ()
"Analyze buffer and enable either C or C++ mode.
Some people and projects use .h extension for C++ header files
which is also the one used for C header files. This makes
matching on file name insufficient for detecting major mode that
should be used.
This function attempts to use file contents to determine whether
the code is C or C++ and based on that chooses whether to enable
`c-ts-mode' or `c++-ts-mode'."
(interactive)
(if (save-excursion
(save-restriction
(save-match-data ; Why `save-match-data'?
(widen)
(goto-char (point-min))
(re-search-forward c-ts-mode--c-or-c++-regexp nil t))))
(c++-ts-mode)
(c-ts-mode)))
(provide 'c-ts-mode)
;;; c-ts-mode.el ends here

View file

@ -1361,6 +1361,28 @@ nil; point is then left undefined."
(search-forward-regexp "\\(\n\\|.\\)") ; to set the match-data.
(point))))
(defmacro c-search-forward-non-nil-char-property (property &optional limit)
"Search forward for a text-property PROPERTY value non-nil.
LIMIT bounds the search.
Leave point just after the character. The match data remain
unchanged. Return the value of PROPERTY. If a non-nil value
isn't found, return nil; point is then left undefined."
(declare (debug t))
`(let* ((-limit- (or ,limit (point-max)))
(value (c-get-char-property (point) ,property)))
(cond
((>= (point) -limit-)
nil)
(value
(forward-char)
value)
(t (let ((place (c-next-single-property-change
(point) ,property nil -limit-)))
(when place
(goto-char (1+ place))
(c-get-char-property place ,property)))))))
(defmacro c-search-backward-char-property (property value &optional limit)
"Search backward for a text-property PROPERTY having value VALUE.
LIMIT bounds the search. The comparison is done with `equal'.

View file

@ -142,6 +142,10 @@
;; Put on the brace which introduces a brace list and on the commas
;; which separate the elements within it.
;;
;; 'c-typedef This property is applied to the first character of a
;; "typedef" keyword. It's value is a list of the identifiers that
;; the "typedef" declares as types.
;;
;; 'c-<>-c-types-set
;; This property is set on an opening angle bracket, and indicates that
;; any "," separators within the template/generic expression have been
@ -10024,10 +10028,10 @@ This function might do hidden buffer changes."
;; an identifier instead.
(declare (debug nil))
`(progn
(setq identifier-start type-start)
,(unless short
;; These identifiers are bound only in the inner let.
'(setq identifier-type at-type
identifier-start type-start
got-parens nil
got-identifier t
got-suffix t
@ -10102,10 +10106,11 @@ This function might do hidden buffer changes."
;; The second element of the return value is non-nil when something
;; indicating the identifier is a type occurs in the declaration.
;; Specifically it is nil, or a three element list (A B C) where C is t
;; when context is '<> and the "identifier" is a found type, B is t when a
;; `c-typedef-kwds' ("typedef") is present, and A is t when some other
;; `c-typedef-decl-kwds' (e.g. class, struct, enum) specifier is present.
;; I.e., (some of) the declared identifier(s) are types.
;; when context is '<> and the "identifier" is a found type, B is the
;; position of the `c-typedef-kwds' keyword ("typedef") when such is
;; present, and A is t when some other `c-typedef-decl-kwds' (e.g. class,
;; struct, enum) specifier is present. I.e., (some of) the declared
;; identifier(s) are types.
;;
;; The third element of the return value is non-nil when the declaration
;; parsed might be an expression. The fourth element is the position of
@ -10173,6 +10178,9 @@ This function might do hidden buffer changes."
;; `c-decl-hangon-kwds' and their associated clauses that
;; occurs after the type.
id-start
;; The earlier value of `type-start' if we've shifted the type
;; backwards.
identifier-start
;; These store `at-type', `type-start' and `id-start' of the
;; identifier before the one in those variables. The previous
;; identifier might turn out to be the real type in a
@ -10183,7 +10191,8 @@ This function might do hidden buffer changes."
;; Set if we've found a specifier (apart from "typedef") that makes
;; the defined identifier(s) types.
at-type-decl
;; Set if we've a "typedef" keyword.
;; If we've a "typedef" keyword (?or similar), the buffer position of
;; its first character.
at-typedef
;; Set if `context' is '<> and the identifier is definitely a type, or
;; has already been recorded as a found type.
@ -10266,7 +10275,7 @@ This function might do hidden buffer changes."
(looking-at "@[A-Za-z0-9]+")))
(save-match-data
(if (looking-at c-typedef-key)
(setq at-typedef t)))
(setq at-typedef (point))))
(setq kwd-sym (c-keyword-sym (match-string 1)))
(save-excursion
(c-forward-keyword-clause 1)
@ -10486,9 +10495,9 @@ This function might do hidden buffer changes."
;; True if we've parsed the type decl to a token that is
;; known to end declarations in this context.
at-decl-end
;; The earlier values of `at-type' and `type-start' if we've
;; shifted the type backwards.
identifier-type identifier-start
;; The earlier value of `at-type' if we've shifted the type
;; backwards.
identifier-type
;; If `c-parse-and-markup-<>-arglists' is set we need to
;; turn it off during the name skipping below to avoid
;; getting `c-type' properties that might be bogus. That
@ -10530,6 +10539,10 @@ This function might do hidden buffer changes."
(progn (setq got-identifier nil) t)
;; It turned out to be the real identifier,
;; so stop.
(save-excursion
(c-backward-syntactic-ws)
(c-simple-skip-symbol-backward)
(setq identifier-start (point)))
nil))
t))
@ -10555,6 +10568,10 @@ This function might do hidden buffer changes."
(and (looking-at c-identifier-start)
(setq pos (point))
(setq got-identifier (c-forward-name))
(save-excursion
(c-backward-syntactic-ws)
(c-simple-skip-symbol-backward)
(setq identifier-start (point)))
(setq name-start pos))
(when (looking-at "[0-9]")
(setq got-number t)) ; We probably have an arithmetic expression.
@ -10573,7 +10590,8 @@ This function might do hidden buffer changes."
(setq at-type nil
name-start type-start
id-start type-start
got-identifier t)))
got-identifier t)
(setq identifier-start type-start)))
;; Skip over type decl suffix operators and trailing noise macros.
(while

View file

@ -85,6 +85,8 @@
(cc-bytecomp-defvar parse-sexp-lookup-properties) ; Emacs only.
(declare-function cl-set-difference "cl-seq" (cl-list1 cl-list2 &rest cl-keys))
;; Need to declare these local symbols during compilation since
;; they're referenced from lambdas in `byte-compile' calls that are
;; executed at compile time. They don't need to have the proper
@ -1109,10 +1111,12 @@ casts and declarations are fontified. Used on level 2 and higher."
;; additionally, mark the commas with c-type property 'c-decl-id-start or
;; 'c-decl-type-start (according to TYPES). Stop at LIMIT.
;;
;; If TYPES is t, fontify all identifiers as types, if it is nil fontify as
;; either variables or functions, otherwise TYPES is a face to use. If
;; NOT-TOP is non-nil, we are not at the top-level ("top-level" includes
;; being directly inside a class or namespace, etc.).
;; If TYPES is t, fontify all identifiers as types; if it is a number, a
;; buffer position, additionally set the `c-deftype' text property on the
;; keyword at that position; if it is nil fontify as either variables or
;; functions, otherwise TYPES is a face to use. If NOT-TOP is non-nil, we
;; are not at the top-level ("top-level" includes being directly inside a
;; class or namespace, etc.).
;;
;; TEMPLATE-CLASS is non-nil when the declaration is in template delimiters
;; and was introduced by, e.g. "typename" or "class", such that if there is
@ -1129,17 +1133,28 @@ casts and declarations are fontified. Used on level 2 and higher."
;;(message "c-font-lock-declarators from %s to %s" (point) limit)
(c-fontify-types-and-refs
()
;; If we're altering the declarators in a typedef, we need to scan ALL of
;; them because of the way we check for changes.
(let ((c-do-decl-limit (if (numberp types) (point-max) limit))
decl-ids)
(c-do-declarators
limit list not-top
(cond ((eq types t) 'c-decl-type-start)
c-do-decl-limit
list not-top
(cond ((or (numberp types)
(eq types t))
'c-decl-type-start)
((null types) 'c-decl-id-start))
(lambda (id-start id-end end-pos _not-top is-function init-char)
(if (eq types t)
(if (or (numberp types)
(eq types t))
(when id-start
;; Register and fontify the identifier as a type.
(let ((c-promote-possible-types t))
(goto-char id-start)
(c-forward-type)))
(c-forward-type))
(when (numberp types)
(push (buffer-substring-no-properties id-start id-end)
decl-ids)))
(when id-start
(goto-char id-start)
(when c-opt-identifier-prefix-key
@ -1147,7 +1162,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(eq (match-end 1) id-end))
(while (and (< (point) id-end)
(re-search-forward c-opt-identifier-prefix-key id-end t))
(c-forward-syntactic-ws limit))))
(c-forward-syntactic-ws c-do-decl-limit))))
;; Only apply the face when the text doesn't have one yet.
;; Exception: The "" in C++'s operator"" will already wrongly have
;; string face.
@ -1164,7 +1179,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(equal (buffer-substring-no-properties id-start id-end)
"\"\""))
(goto-char id-end)
(c-forward-syntactic-ws limit)
(c-forward-syntactic-ws c-do-decl-limit)
(when (c-on-identifier)
(c-put-font-lock-face
(point)
@ -1174,10 +1189,21 @@ casts and declarations are fontified. Used on level 2 and higher."
(eq init-char ?=) ; C++ "<class X = Y>"?
(progn
(goto-char end-pos)
(c-forward-token-2 1 nil limit) ; Over "="
(c-forward-token-2 1 nil c-do-decl-limit) ; Over "="
(let ((c-promote-possible-types t))
(c-forward-type t)))))
accept-anon) ; Last argument to c-do-declarators.
;; If we've changed types declared by a "typedef", update the `c-typedef'
;; text property.
(when (numberp types)
(let* ((old-decl-ids (c-get-char-property types 'c-typedef))
(old-types (c--set-difference old-decl-ids decl-ids :test #'equal))
(new-types (c--set-difference decl-ids old-decl-ids :test #'equal)))
(dolist (type old-types)
(c-unfind-type type))
;; The new types have already been added to `c-found-types', as needed.
(when (or old-types new-types)
(c-put-char-property types 'c-typedef decl-ids)))))
nil))
(defun c-get-fontification-context (match-pos not-front-decl &optional toplev)
@ -1433,7 +1459,10 @@ casts and declarations are fontified. Used on level 2 and higher."
(c-font-lock-declarators
(min limit (point-max))
decl-list
(not (null (cadr decl-or-cast)))
(cond ((null (cadr decl-or-cast))
nil)
((cadr (cadr decl-or-cast)))
(t t))
(not toplev)
template-class
(memq context '(decl <>))))
@ -1749,12 +1778,21 @@ casts and declarations are fontified. Used on level 2 and higher."
; speeds up lisp.h tremendously.
(save-excursion
(when (not (c-back-over-member-initializers decl-search-lim))
(setq paren-state (c-parse-state))
(unless (or (eobp)
(looking-at "\\s(\\|\\s)"))
(forward-char))
(c-syntactic-skip-backward "^;{}" decl-search-lim t)
(when (eq (char-before) ?})
(c-go-list-backward) ; brace block of struct, etc.?
;; Do we have the brace block of a struct, etc.?
(when (cond
((and (consp (car paren-state))
(eq (char-before) ?}))
(goto-char (caar paren-state))
t)
((and (numberp (car paren-state))
(eq (char-after (car paren-state)) ?{))
(goto-char (car paren-state))
t))
(c-syntactic-skip-backward "^;{}" decl-search-lim t))
(when (or (bobp)
(memq (char-before) '(?\; ?{ ?})))

View file

@ -2077,6 +2077,37 @@ with // and /*, not more generic line and block comments."
(not (eobp))))
(forward-char))))))
(defun c-before-change-de-typedef (beg end)
;; For each "typedef" starting in (BEG END), remove the defined types from
;; c-found-types
(let (prop)
(save-excursion
(goto-char beg)
(while (and (< (point) end)
(setq prop (c-search-forward-non-nil-char-property
'c-typedef)))
(dolist (type prop)
(c-unfind-type type))))))
(defun c-after-change-de-typedef (beg end _old-len)
;; For each former "typedef" in (BEG END), remove the defined types from
;; those which are no longer typedefs.
(let (prop)
(save-excursion
(goto-char beg)
(c-backward-token-2
1 nil (- (point) 20))
(while (and (< (point) end)
(setq prop (c-search-forward-non-nil-char-property
'c-typedef end)))
(backward-char)
(when (or (not (looking-at c-typedef-key))
(<= (match-end 1) beg))
(dolist (type prop)
(c-unfind-type type))
(c-clear-char-property (point) 'c-typedef))
(forward-char)))))
(defun c-update-new-id (end)
;; Note the bounds of any identifier that END is in or just after, in
;; `c-new-id-start' and `c-new-id-end'. Otherwise set these variables to
@ -2086,7 +2117,9 @@ with // and /*, not more generic line and block comments."
(let ((id-beg (c-on-identifier)))
(setq c-new-id-start id-beg
c-new-id-end (and id-beg
(progn (c-end-of-current-token) (point)))
(progn (goto-char id-beg)
(c-forward-token-2)
(point)))
c-new-id-is-type nil))))
(defun c-post-command ()
@ -2215,6 +2248,10 @@ with // and /*, not more generic line and block comments."
term-pos)
(buffer-substring-no-properties beg end)))))))
;; If we're about to delete "typedef"s, clear the identifiers from
;; `c-found-types'.
(c-before-change-de-typedef beg end)
(if c-get-state-before-change-functions
(mapc (lambda (fn)
(funcall fn beg end))
@ -2306,6 +2343,7 @@ with // and /*, not more generic line and block comments."
(c-update-new-id end)
(c-trim-found-types beg end old-len) ; maybe we don't
; need all of these.
(c-after-change-de-typedef beg end old-len)
(c-invalidate-sws-region-after beg end old-len)
;; (c-invalidate-state-cache beg) ; moved to
;; `c-before-change'.

View file

@ -152,7 +152,6 @@
"then"
"ensure"
"body_statement"
"parenthesized_statements"
"interpolation")
string-end)
"Regular expression of the nodes that can contain statements.")
@ -221,9 +220,9 @@ values of OVERRIDE"
:language language
:feature 'constant
'((true) @font-lock-doc-markup-face
(false) @font-lock-doc-markup-face
(nil) @font-lock-doc-markup-face)
'((true) @font-lock-constant-face
(false) @font-lock-constant-face
(nil) @font-lock-constant-face)
;; Before 'operator so (unary) works.
:language language
@ -512,10 +511,6 @@ array or hash."
(first-child (ruby-ts--first-non-comment-child parent)))
(= (ruby-ts--lineno open-brace) (ruby-ts--lineno first-child))))
(defun ruby-ts--assignment-ancestor (node &rest _)
"Return the assignment ancestor of NODE if any."
(treesit-parent-until node (ruby-ts--type-pred "\\`assignment\\'")))
(defun ruby-ts--statement-ancestor (node &rest _)
"Return the statement ancestor of NODE if any.
A statement is defined as a child of a statement container where
@ -531,26 +526,6 @@ a statement container is a node that matches
parent (treesit-node-parent parent)))
statement))
(defun ruby-ts--is-in-condition (node &rest _)
"Return the condition node if NODE is within a condition."
(while (and node
(not (equal "condition" (treesit-node-field-name node)))
(not (string-match-p ruby-ts--statement-container-regexp
(treesit-node-type node))))
(setq node (treesit-node-parent node)))
(and (equal "condition" (treesit-node-field-name node)) node))
(defun ruby-ts--endless-method (node &rest _)
"Return the expression node if NODE is in an endless method.
i.e. expr of def foo(args) = expr is returned."
(let* ((method node))
(while (and method
(not (string-match-p ruby-ts--method-regex (treesit-node-type method))))
(setq method (treesit-node-parent method)))
(when method
(if (equal "=" (treesit-node-type (treesit-node-child method 3 nil)))
(treesit-node-child method 4 nil)))))
;;
;; end of functions that can be used for queries
;;
@ -587,11 +562,11 @@ i.e. expr of def foo(args) = expr is returned."
;;
;; I'm using very restrictive patterns hoping to reduce rules
;; triggering unintentionally.
((match "else" "if")
((match "else" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "elsif" "if")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((match "end" "if")
((match "end" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--parent-node) 0)
((n-p-gp nil "then\\|else\\|elsif" "if\\|unless")
(ruby-ts--align-keywords ruby-ts--grand-parent-node) ruby-indent-level)
@ -664,6 +639,13 @@ i.e. expr of def foo(args) = expr is returned."
;; else the second query aligns
;; `ruby-indent-level' spaces in from the parent.
((and ruby-ts--align-chain-p (match "\\." "call")) ruby-ts--align-chain 0)
;; Obery ruby-method-call-indent, whether the dot is on
;; this line or the previous line.
((and (not ruby-ts--method-call-indent-p)
(or
(match "\\." "call")
(query "(call \".\" (identifier) @indent)")))
parent 0)
((match "\\." "call") parent ruby-indent-level)
;; ruby-indent-after-block-in-continued-expression
@ -697,23 +679,27 @@ i.e. expr of def foo(args) = expr is returned."
;; 2) With paren, 1st arg on next line
((and (query "(argument_list \"(\" _ @indent)")
(node-is ")"))
(ruby-ts--bol ruby-ts--grand-parent-node) 0)
ruby-ts--parent-call-or-bol 0)
((query "(argument_list \"(\" _ @indent)")
(ruby-ts--bol ruby-ts--grand-parent-node) ruby-indent-level)
ruby-ts--parent-call-or-bol ruby-indent-level)
;; 3) No paren, ruby-parenless-call-arguments-indent is t
((and ruby-ts--parenless-call-arguments-indent-p (parent-is "argument_list"))
first-sibling 0)
;; 4) No paren, ruby-parenless-call-arguments-indent is nil
((parent-is "argument_list") (ruby-ts--bol ruby-ts--grand-parent-node) ruby-indent-level)
((parent-is "argument_list")
(ruby-ts--bol ruby-ts--statement-ancestor) ruby-indent-level)
;; Old... probably too simple
((parent-is "block_parameters") first-sibling 1)
((and (parent-is "binary")
(or ruby-ts--assignment-ancestor
ruby-ts--is-in-condition
ruby-ts--endless-method))
first-sibling 0)
((and (not ruby-ts--after-op-indent-p)
(parent-is "binary\\|conditional"))
(ruby-ts--bol ruby-ts--statement-ancestor) ruby-indent-level)
((parent-is "binary")
ruby-ts--binary-indent-anchor 0)
((parent-is "conditional") parent ruby-indent-level)
;; ruby-mode does not touch these...
((match "bare_string" "string_array") no-indent 0)
@ -732,37 +718,15 @@ i.e. expr of def foo(args) = expr is returned."
((and ruby-ts--same-line-hash-array-p (parent-is "array"))
(nth-sibling 0 ruby-ts--true) 0)
;; NOTE to folks trying to understand my insanity...
;; I having trouble understanding the "logic" of why things
;; are indented like they are so I am adding special cases
;; hoping at some point I will be struck by lightning.
((and (n-p-gp "}" "hash" "pair")
(not ruby-ts--same-line-hash-array-p))
grand-parent 0)
((and (n-p-gp "pair" "hash" "pair")
(not ruby-ts--same-line-hash-array-p))
grand-parent ruby-indent-level)
((and (n-p-gp "}" "hash" "method")
(not ruby-ts--same-line-hash-array-p))
grand-parent 0)
((and (n-p-gp "pair" "hash" "method")
(not ruby-ts--same-line-hash-array-p))
grand-parent ruby-indent-level)
((match "}" "hash") ruby-ts--parent-call-or-bol 0)
((parent-is "hash") ruby-ts--parent-call-or-bol ruby-indent-level)
((match "]" "array") ruby-ts--parent-call-or-bol 0)
((parent-is "array") ruby-ts--parent-call-or-bol ruby-indent-level)
((n-p-gp "}" "hash" "assignment") (ruby-ts--bol ruby-ts--grand-parent-node) 0)
((n-p-gp nil "hash" "assignment") (ruby-ts--bol ruby-ts--grand-parent-node) ruby-indent-level)
((n-p-gp "]" "array" "assignment") (ruby-ts--bol ruby-ts--grand-parent-node) 0)
((n-p-gp nil "array" "assignment") (ruby-ts--bol ruby-ts--grand-parent-node) ruby-indent-level)
((parent-is "pair") ruby-ts--parent-call-or-bol 0)
((n-p-gp "}" "hash" "argument_list") first-sibling 0)
((n-p-gp nil "hash" "argument_list") first-sibling ruby-indent-level)
((n-p-gp "]" "array" "argument_list") first-sibling 0)
((n-p-gp nil "array" "argument_list") first-sibling ruby-indent-level)
((match "}" "hash") first-sibling 0)
((parent-is "hash") first-sibling ruby-indent-level)
((match "]" "array") first-sibling 0)
((parent-is "array") first-sibling ruby-indent-level)
((match ")" "parenthesized_statements") parent-bol 0)
((parent-is "parenthesized_statements") parent-bol ruby-indent-level)
;; If the previous method isn't finished yet, this will get
;; the next method indented properly.
@ -814,6 +778,66 @@ i.e. expr of def foo(args) = expr is returned."
(back-to-indentation)
(point)))))
(defun ruby-ts--binary-indent-anchor (_node parent _bol &rest _)
(save-excursion
(goto-char (treesit-node-start parent))
(when (string-match-p ruby-ts--statement-container-regexp
(treesit-node-type (treesit-node-parent parent)))
;; Hack alert: it's not the proper place to alter the offset.
;; Redoing the analysis in the OFFSET form seems annoying,
;; though. (**)
(forward-char ruby-indent-level))
(point)))
(defun ruby-ts--parent-call-or-bol (_not parent _bol &rest _)
(let* ((parent-bol (save-excursion
(goto-char (treesit-node-start parent))
(back-to-indentation)
(point)))
(found
(treesit-parent-until
parent
(lambda (node)
(or (< (treesit-node-start node) parent-bol)
(string-match-p "\\`array\\|hash\\'" (treesit-node-type node))
;; Method call on same line.
(equal (treesit-node-type node) "argument_list"))))))
(cond
((null found)
parent-bol)
;; No paren/curly/brace found on the same line.
((< (treesit-node-start found) parent-bol)
parent-bol)
;; Hash or array opener on the same line.
((string-match-p "\\`array\\|hash\\'" (treesit-node-type found))
(save-excursion
(goto-char (treesit-node-start (treesit-node-child found 1)))
(point)))
;; Parenless call found: indent to stmt with offset.
((not ruby-parenless-call-arguments-indent)
(save-excursion
(goto-char (treesit-node-start
(ruby-ts--statement-ancestor found)))
;; (**) Same.
(+ (point) ruby-indent-level)))
;; Call with parens -- ident to first arg.
((equal (treesit-node-type (treesit-node-child found 0))
"(")
(save-excursion
(goto-char (treesit-node-start (treesit-node-child found 1)))
(point)))
;; Indent to the parenless call args beginning.
(t
(save-excursion
(goto-char (treesit-node-start found))
(point))))))
(defun ruby-ts--after-op-indent-p (&rest _)
ruby-after-operator-indent)
(defun ruby-ts--method-call-indent-p (&rest _)
ruby-method-call-indent)
(defun ruby-ts--class-or-module-p (node)
"Predicate if NODE is a class or module."
(string-match-p ruby-ts--class-or-module-regex (treesit-node-type node)))

View file

@ -824,11 +824,11 @@ by this function to the end of values available via
(defvar-keymap read-regexp-map
:parent minibuffer-local-map
"M-c" #'read-regexp-toggle-case-folding)
"M-s c" #'read-regexp-toggle-case-fold)
(defvar read-regexp--case-fold nil)
(defun read-regexp-toggle-case-folding ()
(defun read-regexp-toggle-case-fold ()
(interactive)
(setq read-regexp--case-fold
(if (or (eq read-regexp--case-fold 'fold)
@ -875,7 +875,7 @@ in \":\", followed by optional whitespace), DEFAULT is added to the prompt.
The optional argument HISTORY is a symbol to use for the history list.
If nil, use `regexp-history'.
If the user has used the \\<read-regexp-map>\\[read-regexp-toggle-case-folding] command to specify case
If the user has used the \\<read-regexp-map>\\[read-regexp-toggle-case-fold] command to specify case
sensitivity, the returned string will have a text property named
`case-fold' that has a value of either `fold' or
`inhibit-fold'. (It's up to the caller of `read-regexp' to

View file

@ -905,6 +905,14 @@ This is not a general optimization and should be RARELY needed!
See comments in `treesit-font-lock-fontify-region' for more
detail.")
(defvar-local treesit--font-lock-fast-mode-grace-count 5
"Grace counts before we turn on the fast mode.
When query takes abnormally long time to execute, we turn on the
\"fast mode\", but just to be on the safe side, we only turn on
the fast mode after this number of offenses. See bug#60691,
bug#60223.")
;; Some details worth explaining:
;;
;; 1. When we apply face to a node, we clip the face into the
@ -927,13 +935,13 @@ detail.")
;; parse it into a enormously tall tree (10k levels tall). In that
;; case querying the root node is very slow. So we try to get
;; top-level nodes and query them. This ensures that querying is fast
;; everywhere else, except for the problematic region.
;; everywhere else, except for the problematic region. (Bug#59415).
;;
;; Some other time the source file has a top-level node that contains
;; a huge number of children (say, 10k children), querying that node
;; is also very slow, so instead of getting the top-level node, we
;; recursively go down the tree to find nodes that cover the region
;; but are reasonably small.
;; a huge number of immediate children (say, 10k children), querying
;; that node is also very slow, so instead of getting the top-level
;; node, we recursively go down the tree to find nodes that cover the
;; region but are reasonably small. (Bug#59738).
;;
;; 3. It is possible to capture a node that's completely outside the
;; region between START and END: as long as the whole pattern
@ -941,8 +949,8 @@ detail.")
;; returned. If the node is outside of that region, (max node-start
;; start) and friends return bad values, so we filter them out.
;; However, we don't filter these nodes out if a function will process
;; the node, because could (and often do) fontify the relatives of the
;; captured node, not just the node itself. If we took out those
;; the node, because it could (and often do) fontify the relatives of
;; the captured node, not just the node itself. If we took out those
;; nodes author of those functions would be very confused.
(defun treesit-font-lock-fontify-region (start end &optional loudly)
"Fontify the region between START and END.
@ -979,9 +987,12 @@ If LOUDLY is non-nil, display some debugging information."
(end-time (current-time)))
;; If for any query the query time is strangely long,
;; switch to fast mode (see comments above).
(when (> (time-to-seconds (time-subtract end-time start-time))
0.01)
(setq-local treesit--font-lock-fast-mode t))
(when (and (> (time-to-seconds
(time-subtract end-time start-time))
0.01))
(if (> treesit--font-lock-fast-mode-grace-count 0)
(cl-decf treesit--font-lock-fast-mode-grace-count)
(setq-local treesit--font-lock-fast-mode t)))
;; For each captured node, fontify that node.
(with-silent-modifications
@ -1152,6 +1163,9 @@ See `treesit-simple-indent-presets'.")
(and (>= (point) comment-start-bol)
adaptive-fill-regexp
(looking-at adaptive-fill-regexp)
;; If previous line is an empty line, don't
;; indent.
(not (looking-at (rx (* whitespace) eol)))
(match-end 0))))))
;; TODO: Document.
(cons 'grand-parent

View file

@ -325,7 +325,6 @@ See `run-hooks'."
(define-key map "U" #'vc-dir-unmark-all-files)
(define-key map "\C-?" #'vc-dir-unmark-file-up)
(define-key map "\M-\C-?" #'vc-dir-unmark-all-files)
(define-key map "%" #'vc-dir-mark-by-regexp)
;; Movement.
(define-key map "n" #'vc-dir-next-line)
(define-key map " " #'vc-dir-next-line)
@ -361,8 +360,13 @@ See `run-hooks'."
(define-key branch-map "l" #'vc-print-branch-log)
(define-key branch-map "s" #'vc-switch-branch))
(let ((regexp-map (make-sparse-keymap)))
(define-key map "%" regexp-map)
(define-key regexp-map "m" #'vc-dir-mark-by-regexp))
(let ((mark-map (make-sparse-keymap)))
(define-key map "*" mark-map)
(define-key mark-map "%" #'vc-dir-mark-by-regexp)
(define-key mark-map "r" #'vc-dir-mark-registered-files))
;; Hook up the menu.
@ -791,7 +795,7 @@ MARK-FILES should be a list of absolute filenames."
vc-ewoc))
(defun vc-dir-mark-registered-files ()
"Mark files that are in one of registered state: edited, added or removed."
"Mark files that are in one of registered states: edited, added or removed."
(interactive)
(vc-dir-mark-state-files '(edited added removed)))

View file

@ -5670,7 +5670,8 @@ the original point in both windows."
(defun split-window-below (&optional size window-to-split)
"Split WINDOW-TO-SPLIT into two windows, one above the other.
WINDOW-TO-SPLIT is above. The newly split-off window is
WINDOW-TO-SPLIT defaults to the selected window and and will be above
the other window after splitting. The newly split-off window is
below and displays the same buffer. Return the new window.
If optional argument SIZE is omitted or nil, both windows get the
@ -5691,7 +5692,9 @@ amount of redisplay; this is convenient on slow terminals."
;; `split-window' would not signal an error here.
(error "Size of new window too small"))
(setq new-window (split-window window-to-split size))
(unless split-window-keep-point
(when (and (null split-window-keep-point)
(or (null window-to-split)
(eq window-to-split (selected-window))))
(with-current-buffer (window-buffer window-to-split)
;; Use `save-excursion' around vertical movements below
;; (Bug#10971). Note: When WINDOW-TO-SPLIT's buffer has a
@ -5732,8 +5735,9 @@ handled as in `split-window-below'."
(defun split-window-right (&optional size window-to-split)
"Split WINDOW-TO-SPLIT into two side-by-side windows.
WINDOW-TO-SPLIT is on the left. The newly split-off window is on
the right and displays the same buffer. Return the new window.
WINDOW-TO-SPLIT defaults to the selected window and and will be on the
left after splitting. The newly split-off window is on the right and
displays the same buffer. Return the new window.
If optional argument SIZE is omitted or nil, both windows get the
same width, or close to it. If SIZE is positive, the left-hand

View file

@ -525,14 +525,14 @@ get_truename_buffer (register Lisp_Object filename)
return Qnil;
}
/* Run buffer-list-update-hook if Vrun_hooks is non-nil, and BUF is NULL
or does not have buffer hooks inhibited. BUF is NULL when called by
make-indirect-buffer, since it does not inhibit buffer hooks. */
/* Run buffer-list-update-hook if Vrun_hooks is non-nil and BUF does
not have buffer hooks inhibited. */
static void
run_buffer_list_update_hook (struct buffer *buf)
{
if (! (NILP (Vrun_hooks) || (buf && buf->inhibit_buffer_hooks)))
eassert (buf);
if (! (NILP (Vrun_hooks) || buf->inhibit_buffer_hooks))
call1 (Vrun_hooks, Qbuffer_list_update_hook);
}
@ -907,7 +907,7 @@ does not run the hooks `kill-buffer-hook',
set_buffer_internal_1 (old_b);
}
run_buffer_list_update_hook (NULL);
run_buffer_list_update_hook (b);
return buf;
}

View file

@ -42,8 +42,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#undef ts_node_end_byte
#undef ts_node_eq
#undef ts_node_field_name_for_child
#undef ts_node_first_child_for_byte
#undef ts_node_first_named_child_for_byte
#undef ts_node_has_error
#undef ts_node_is_extra
#undef ts_node_is_missing
@ -99,8 +97,6 @@ DEF_DLL_FN (TSNode, ts_node_descendant_for_byte_range,
DEF_DLL_FN (uint32_t, ts_node_end_byte, (TSNode));
DEF_DLL_FN (bool, ts_node_eq, (TSNode, TSNode));
DEF_DLL_FN (const char *, ts_node_field_name_for_child, (TSNode, uint32_t));
DEF_DLL_FN (TSNode, ts_node_first_child_for_byte, (TSNode, uint32_t));
DEF_DLL_FN (TSNode, ts_node_first_named_child_for_byte, (TSNode, uint32_t));
DEF_DLL_FN (bool, ts_node_has_error, (TSNode));
DEF_DLL_FN (bool, ts_node_is_extra, (TSNode));
DEF_DLL_FN (bool, ts_node_is_missing, (TSNode));
@ -174,8 +170,6 @@ init_treesit_functions (void)
LOAD_DLL_FN (library, ts_node_end_byte);
LOAD_DLL_FN (library, ts_node_eq);
LOAD_DLL_FN (library, ts_node_field_name_for_child);
LOAD_DLL_FN (library, ts_node_first_child_for_byte);
LOAD_DLL_FN (library, ts_node_first_named_child_for_byte);
LOAD_DLL_FN (library, ts_node_has_error);
LOAD_DLL_FN (library, ts_node_is_extra);
LOAD_DLL_FN (library, ts_node_is_missing);
@ -232,8 +226,6 @@ init_treesit_functions (void)
#define ts_node_end_byte fn_ts_node_end_byte
#define ts_node_eq fn_ts_node_eq
#define ts_node_field_name_for_child fn_ts_node_field_name_for_child
#define ts_node_first_child_for_byte fn_ts_node_first_child_for_byte
#define ts_node_first_named_child_for_byte fn_ts_node_first_named_child_for_byte
#define ts_node_has_error fn_ts_node_has_error
#define ts_node_is_extra fn_ts_node_is_extra
#define ts_node_is_missing fn_ts_node_is_missing
@ -2095,6 +2087,41 @@ return nil. */)
return make_treesit_node (XTS_NODE (node)->parser, sibling);
}
/* Our reimplementation of ts_node_first_child_for_byte. The current
implementation of that function has problems (see bug#60127), so
before it's fixed upstream, we use our own reimplementation of it.
Return true if there is a valid sibling, return false otherwise.
If the return value is false, the position of the cursor is
undefined. (We use cursor because technically we can't make a null
node for ourselves, also, using cursor is more convenient.)
TODO: Remove this function once tree-sitter fixed the bug. */
static bool treesit_cursor_first_child_for_byte
(TSTreeCursor *cursor, ptrdiff_t pos, bool named)
{
if (!ts_tree_cursor_goto_first_child (cursor))
return false;
TSNode node = ts_tree_cursor_current_node (cursor);
while (ts_node_end_byte (node) <= pos)
{
if (ts_tree_cursor_goto_next_sibling (cursor))
node = ts_tree_cursor_current_node (cursor);
else
/* Reached the end and still can't find a valid sibling. */
return false;
}
while (named && (!ts_node_is_named (node)))
{
if (ts_tree_cursor_goto_next_sibling (cursor))
node = ts_tree_cursor_current_node (cursor);
else
/* Reached the end and still can't find a named sibling. */
return false;
}
return true;
}
DEFUN ("treesit-node-first-child-for-pos",
Ftreesit_node_first_child_for_pos,
Streesit_node_first_child_for_pos, 2, 3, 0,
@ -2119,16 +2146,17 @@ Note that this function returns an immediate child, not the smallest
ptrdiff_t byte_pos = buf_charpos_to_bytepos (buf, XFIXNUM (pos));
TSNode treesit_node = XTS_NODE (node)->node;
TSNode child;
if (NILP (named))
child = ts_node_first_child_for_byte (treesit_node, byte_pos - visible_beg);
else
child = ts_node_first_named_child_for_byte (treesit_node,
byte_pos - visible_beg);
if (ts_node_is_null (child))
TSTreeCursor cursor = ts_tree_cursor_new (treesit_node);
ptrdiff_t treesit_pos = byte_pos - visible_beg;
bool success;
success = treesit_cursor_first_child_for_byte (&cursor, treesit_pos,
!NILP (named));
TSNode child = ts_tree_cursor_current_node (&cursor);
ts_tree_cursor_delete (&cursor);
if (!success)
return Qnil;
return make_treesit_node (XTS_NODE (node)->parser, child);
}
@ -3270,9 +3298,9 @@ a regexp. */)
Lisp_Object parser = XTS_NODE (root)->parser;
Lisp_Object parent = Fcons (Qnil, Qnil);
TSTreeCursor cursor;
if (!treesit_cursor_helper (&cursor, XTS_NODE (root)->node, parser))
return Qnil;
/* In this function we never traverse above NODE, so we don't need
to use treesit_cursor_helper. */
TSTreeCursor cursor = ts_tree_cursor_new (XTS_NODE (root)->node);
treesit_build_sparse_tree (&cursor, parent, predicate, process_fn,
the_limit, parser);

View file

@ -24483,6 +24483,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
}
#ifndef HAVE_EXT_TOOL_BAR
/* Now see if the touchpoint was previously on the tool bar.
If it was, release the tool bar. */
@ -24507,6 +24508,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
/* Now clear the tool bar device. */
FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
}
#endif
goto XI_OTHER;
}

View file

@ -19,8 +19,17 @@
;;; Commentary:
;; These tests all use `sasl' because, as of ERC 5.5, it's the one
;; and only local module.
;; A local module doubles as a minor mode whose mode variable and
;; associated local data can withstand service disruptions.
;; Unfortunately, the current implementation is too unwieldy to be
;; made public because it doesn't perform any of the boiler plate
;; needed to save and restore buffer-local and "network-local" copies
;; of user options. Ultimately, a user-friendly framework must fill
;; this void if third-party local modules are ever to become
;; practical.
;;
;; The following tests all use `sasl' because, as of ERC 5.5, it's the
;; only local module.
;;; Code:
@ -206,7 +215,7 @@
(erc-cmd-QUIT "")
(funcall expect 10 "finished")))
(ert-info ("Disabling works from a target buffer.")
(ert-info ("Disabling works from a target buffer")
(with-current-buffer "#chan"
(should erc-sasl-mode)
(call-interactively #'erc-sasl-disable)
@ -214,10 +223,9 @@
(should (local-variable-p 'erc-sasl-mode))
(should-not (buffer-local-value 'erc-sasl-mode (get-buffer "foonet")))
(erc-cmd-RECONNECT)
(with-current-buffer "#chan"
(funcall expect 10 "Some enigma, some riddle")
(should-not erc-sasl-mode) ; regression
(should (local-variable-p 'erc-sasl-mode))))
(funcall expect 10 "Some enigma, some riddle")
(should-not erc-sasl-mode) ; regression
(should (local-variable-p 'erc-sasl-mode)))
(with-current-buffer "foonet"
(should (local-variable-p 'erc-sasl-mode))
@ -239,4 +247,82 @@
(should erc-sasl-mode)
(funcall expect 10 "User modes for tester")))))
(defvar-local erc-scenarios-base-local-modules--local-var nil)
(define-erc-module -phony-sblm- nil
"Test module for `erc-scenarios-base-local-modules--var-persistence'."
((when-let ((vars (or erc--server-reconnecting erc--target-priors)))
(should (assq 'erc--phony-sblm--mode vars))
(setq erc-scenarios-base-local-modules--local-var
(alist-get 'erc-scenarios-base-local-modules--local-var vars)))
(setq erc-scenarios-base-local-modules--local-var
(or erc-scenarios-base-local-modules--local-var
(if erc--target 100 0))))
((kill-local-variable 'erc-scenarios-base-local-modules--local-var))
'local)
;; Note: this file has grown too expensive (time-wise) and must be
;; split up. When that happens, this test should be rewritten without
;; any time-saving hacks, namely, server-initiated JOINs and an
;; absence of QUITs. (That said, three connections in under 2 seconds
;; is pretty nice.)
(ert-deftest erc-scenarios-base-local-modules--var-persistence ()
:tags '(:expensive-test)
(erc-scenarios-common-with-cleanup
((erc-scenarios-common-dialog "base/reconnect")
(erc-server-flood-penalty 0.1)
(dumb-server (erc-d-run "localhost" t 'options 'options 'options))
(port (process-contact dumb-server :service))
(erc-modules (cons '-phony-sblm- (remq 'autojoin erc-modules)))
(expect (erc-d-t-make-expecter))
(server-buffer-name (format "127.0.0.1:%d" port)))
(ert-info ("Initial authentication succeeds as expected")
(with-current-buffer (erc :server "127.0.0.1"
:port port
:nick "tester"
:password "changeme"
:full-name "tester")
(should (string= (buffer-name) server-buffer-name)))
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "FooNet"))
(funcall expect 10 "This server is in debug mode")
(should erc--phony-sblm--mode)
(should (eql erc-scenarios-base-local-modules--local-var 0))
(setq erc-scenarios-base-local-modules--local-var 1)))
(ert-info ("Save module's local var in target buffer")
(with-current-buffer (erc-d-t-wait-for 10 (get-buffer "#chan"))
(should (eql erc-scenarios-base-local-modules--local-var 100))
(setq erc-scenarios-base-local-modules--local-var 101)
(funcall expect 20 "welcome")))
(with-current-buffer "FooNet" (funcall expect 20 "terminated"))
(ert-info ("Vars reused when mode was left enabled")
(with-current-buffer "#chan"
(erc-cmd-RECONNECT)
(funcall expect 20 "welcome")
(should (eql erc-scenarios-base-local-modules--local-var 101))
(erc--phony-sblm--mode -1))
(with-current-buffer "FooNet"
(funcall expect 10 "User modes for tester")
(should (eql erc-scenarios-base-local-modules--local-var 1))))
(with-current-buffer "FooNet" (funcall expect 20 "terminated"))
(ert-info ("Local binding gone when mode disabled in target")
(with-current-buffer "#chan"
(erc-cmd-RECONNECT)
(funcall expect 20 "welcome")
(should-not erc--phony-sblm--mode)
(should-not erc-scenarios-base-local-modules--local-var))
;; But value retained in server buffer, where mode is active.
(with-current-buffer "FooNet"
(funcall expect 10 "User modes for tester")
(should (eql erc-scenarios-base-local-modules--local-var 1))))))
;;; erc-scenarios-local-modules.el ends here

View file

@ -1251,18 +1251,28 @@
(setq calls nil)))))
(ert-deftest erc--merge-local-modes ()
(cl-letf (((get 'erc-b-mode 'erc-module) 'b)
((get 'erc-c-mode 'erc-module) 'c)
((get 'erc-d-mode 'erc-module) 'd)
((get 'erc-e-mode 'erc-module) 'e))
(ert-info ("No existing modes")
(let ((old '((a) (b . t)))
(new '(erc-c-mode erc-d-mode)))
(should (equal (erc--merge-local-modes new old)
'((erc-c-mode erc-d-mode))))))
(ert-info ("No existing modes")
(let ((old '((a) (b . t)))
(new '(erc-c-mode erc-d-mode)))
(should (equal (erc--merge-local-modes new old)
'((erc-c-mode erc-d-mode))))))
(ert-info ("Active existing added, inactive existing removed, deduped")
(let ((old '((a) (erc-b-mode) (c . t) (erc-d-mode . t) (erc-e-mode . t)))
(new '(erc-b-mode erc-d-mode)))
(should (equal (erc--merge-local-modes new old)
'((erc-d-mode erc-e-mode) . (erc-b-mode)))))))
(ert-info ("Active existing added, inactive existing removed, deduped")
(let ((old '((a) (erc-b-mode) (c . t) (erc-d-mode . t) (erc-e-mode . t)))
(new '(erc-b-mode erc-d-mode)))
(should (equal (erc--merge-local-modes new old)
'((erc-d-mode erc-e-mode) . (erc-b-mode))))))
(ert-info ("Non-module erc-prefixed mode ignored")
(let ((old '((erc-b-mode) (erc-f-mode . t) (erc-d-mode . t)))
(new '(erc-b-mode)))
(should (equal (erc--merge-local-modes new old)
'((erc-d-mode) . (erc-b-mode))))))))
(ert-deftest define-erc-module--global ()
(let ((global-module '(define-erc-module mname malias
@ -1300,13 +1310,15 @@ Some docstring"
(ignore c) (ignore d))
(defalias 'erc-malias-mode #'erc-mname-mode)
(put 'erc-malias-mode 'erc-module 'mname)
(put 'erc-mname-mode 'erc-module 'mname)
(put 'erc-mname-mode 'definition-name 'mname)
(put 'erc-mname-enable 'definition-name 'mname)
(put 'erc-mname-disable 'definition-name 'mname))))))
(ert-deftest define-erc-module--local ()
(let* ((global-module '(define-erc-module mname malias
(let* ((global-module '(define-erc-module mname nil ; no alias
"Some docstring"
((ignore a) (ignore b))
((ignore c) (ignore d))
@ -1353,8 +1365,7 @@ When called interactively, do so in all buffers for the current connection."
(setq erc-mname-mode nil)
(ignore c) (ignore d))))
(defalias 'erc-malias-mode #'erc-mname-mode)
(put 'erc-mname-mode 'erc-module 'mname)
(put 'erc-mname-mode 'definition-name 'mname)
(put 'erc-mname-enable 'definition-name 'mname)
(put 'erc-mname-disable 'definition-name 'mname))))))

View file

@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
((pass 10 "PASS :barnet:changeme"))
((nick 3 "NICK tester"))
((user 3 "USER user 0 * :tester")
((nick 10 "NICK tester"))
((user 10 "USER user 0 * :tester")
(0 ":irc.barnet.org 001 tester :Welcome to the barnet IRC Network tester")
(0 ":irc.barnet.org 002 tester :Your host is irc.barnet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.barnet.org 003 tester :This server was created Wed, 12 May 2021 07:41:08 UTC")
@ -17,7 +17,7 @@
(0 ":irc.barnet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.barnet.org 422 tester :MOTD File is missing"))
((mode-user 10.2 "MODE tester +i")
((mode-user 10 "MODE tester +i")
;; No mode answer ^
(0 ":tester!~u@xrir8fpe4d7ak.irc JOIN #chan")
@ -36,9 +36,9 @@
(0 ":irc.znc.in 306 tester :You have been marked as being away")
(0 ":irc.barnet.org 305 tester :You are no longer marked as being away"))
((~join 3 "JOIN #chan"))
((~join 10 "JOIN #chan"))
((mode 5 "MODE #chan")
((mode 10 "MODE #chan")
(0 ":irc.barnet.org 324 tester #chan +nt")
(0 ":irc.barnet.org 329 tester #chan 1620805269")
(0.1 ":joe!~u@svpn88yjcdj42.irc PRIVMSG #chan :mike: But, in defense, by mercy, 'tis most just.")

View file

@ -1,7 +1,7 @@
;; -*- mode: lisp-data; -*-
((pass 10 "PASS :foonet:changeme"))
((nick 3 "NICK tester"))
((user 3 "USER user 0 * :tester")
((nick 10 "NICK tester"))
((user 10 "USER user 0 * :tester")
(0 ":irc.foonet.org 001 tester :Welcome to the foonet IRC Network tester")
(0 ":irc.foonet.org 002 tester :Your host is irc.foonet.org, running version oragono-2.6.0-7481bf0385b95b16")
(0 ":irc.foonet.org 003 tester :This server was created Wed, 12 May 2021 07:41:09 UTC")
@ -17,7 +17,7 @@
(0 ":irc.foonet.org 266 tester 3 3 :Current global users 3, max 3")
(0 ":irc.foonet.org 422 tester :MOTD File is missing"))
((mode-user 10.2 "MODE tester +i")
((mode-user 10 "MODE tester +i")
;; No mode answer ^
(0 ":tester!~u@nvfhxvqm92rm6.irc JOIN #chan")
(0 ":irc.foonet.org 353 tester = #chan :alice @bob tester")
@ -36,9 +36,9 @@
(0 ":irc.foonet.org NOTICE tester :[07:00:32] This server is in debug mode and is logging all user I/O. If you do not wish for everything you send to be readable by the server owner(s), please disconnect.")
(0 ":irc.foonet.org 305 tester :You are no longer marked as being away"))
((~join 3 "JOIN #chan"))
((~join 10 "JOIN #chan"))
((mode 8 "MODE #chan")
((mode 10 "MODE #chan")
(0 ":irc.foonet.org 324 tester #chan +nt")
(0 ":irc.foonet.org 329 tester #chan 1620805271")
(0.1 ":alice!~u@svpn88yjcdj42.irc PRIVMSG #chan :bob: Grows, lives, and dies, in single blessedness.")

View file

@ -44,7 +44,8 @@
(should (equal-including-properties
last-prompt
(propertize
(format "%s $ " (directory-file-name default-directory))
(format "%s %s " (directory-file-name default-directory)
(if (= (file-user-uid) 0) "#" "$"))
'read-only t
'field 'prompt
'font-lock-face 'eshell-prompt
@ -68,7 +69,8 @@ This tests the case when `eshell-highlight-prompt' is nil."
(should (equal-including-properties
last-prompt
(propertize
(format "%s $ " (directory-file-name default-directory))
(format "%s %s " (directory-file-name default-directory)
(if (= (file-user-uid) 0) "#" "$"))
'field 'prompt
'front-sticky '(field)
'rear-nonsticky '(field))))

View file

@ -878,7 +878,18 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(zerop (nth 1 fsi))
(zerop (nth 2 fsi))))))
(ert-deftest tramp-archive-test47-auto-load ()
;; `file-user-uid' was introduced in Emacs 30.1.
(ert-deftest tramp-archive-test44-file-user-uid ()
"Check that `file-user-uid' returns proper values."
(skip-unless tramp-archive-enabled)
(skip-unless (fboundp 'file-user-uid))
(let ((default-directory tramp-archive-test-archive))
;; `file-user-uid' exists since Emacs 30.1. We don't want to see
;; compiler warnings for older Emacsen.
(should (integerp (with-no-warnings (file-user-uid))))))
(ert-deftest tramp-archive-test48-auto-load ()
"Check that `tramp-archive' autoloads properly."
:tags '(:expensive-test)
(skip-unless tramp-archive-enabled)
@ -923,7 +934,7 @@ This tests also `file-executable-p', `file-writable-p' and `set-file-modes'."
(format "(setq tramp-archive-enabled %s)" enabled))
(shell-quote-argument (format code file)))))))))))
(ert-deftest tramp-archive-test47-delay-load ()
(ert-deftest tramp-archive-test48-delay-load ()
"Check that `tramp-archive' is loaded lazily, only when needed."
:tags '(:expensive-test)
(skip-unless tramp-archive-enabled)

View file

@ -33,7 +33,7 @@
;; remote host, set this environment variable to "/dev/null" or
;; whatever is appropriate on your system.
;; For slow remote connections, `tramp-test44-asynchronous-requests'
;; For slow remote connections, `tramp-test45-asynchronous-requests'
;; might be too heavy. Setting $REMOTE_PARALLEL_PROCESSES to a proper
;; value less than 10 could help.
@ -6297,7 +6297,7 @@ INPUT, if non-nil, is a string sent to the process."
(skip-unless (and (fboundp 'file-locked-p) (fboundp 'make-lock-file-name)))
;; `lock-file', `unlock-file', `file-locked-p' and
;; `make-lock-file-name' exists since Emacs 28.1. We don't want to
;; `make-lock-file-name' exist since Emacs 28.1. We don't want to
;; see compiler warnings for older Emacsen.
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
@ -7076,11 +7076,40 @@ This requires restrictions of file name syntax."
(dotimes (i (length fsi))
(should (natnump (or (nth i fsi) 0))))))
;; `tramp-test44-asynchronous-requests' could be blocked. So we set a
;; `file-user-uid' was introduced in Emacs 30.1.
(ert-deftest tramp-test44-file-user-uid ()
"Check that `file-user-uid' and `tramp-get-remote-*' return proper values."
(skip-unless (tramp--test-enabled))
(let ((default-directory ert-remote-temporary-file-directory))
;; `file-user-uid' exists since Emacs 30.1. We don't want to see
;; compiler warnings for older Emacsen.
(when (fboundp 'file-user-uid)
(should (integerp (with-no-warnings (file-user-uid)))))
(with-parsed-tramp-file-name default-directory nil
(should (or (integerp (tramp-get-remote-uid v 'integer))
(null (tramp-get-remote-uid v 'integer))))
(should (or (stringp (tramp-get-remote-uid v 'string))
(null (tramp-get-remote-uid v 'string))))
(should (or (integerp (tramp-get-remote-gid v 'integer))
(null (tramp-get-remote-gid v 'integer))))
(should (or (stringp (tramp-get-remote-gid v 'string))
(null (tramp-get-remote-gid v 'string))))
(when-let ((groups (tramp-get-remote-groups v 'integer)))
(should (consp groups))
(dolist (group groups) (should (integerp group))))
(when-let ((groups (tramp-get-remote-groups v 'string)))
(should (consp groups))
(dolist (group groups) (should (stringp group)))))))
;; `tramp-test45-asynchronous-requests' could be blocked. So we set a
;; timeout of 300 seconds, and we send a SIGUSR1 signal after 300
;; seconds. Similar check is performed in the timer function.
(defconst tramp--test-asynchronous-requests-timeout 300
"Timeout for `tramp-test44-asynchronous-requests'.")
"Timeout for `tramp-test45-asynchronous-requests'.")
(defmacro tramp--test-with-proper-process-name-and-buffer (proc &rest body)
"Set \"process-name\" and \"process-buffer\" connection properties.
@ -7116,7 +7145,7 @@ This is needed in timer functions as well as process filters and sentinels."
(tramp-flush-connection-property v "process-buffer")))))
;; This test is inspired by Bug#16928.
(ert-deftest tramp-test44-asynchronous-requests ()
(ert-deftest tramp-test45-asynchronous-requests ()
"Check parallel asynchronous requests.
Such requests could arrive from timers, process filters and
process sentinels. They shall not disturb each other."
@ -7283,7 +7312,7 @@ process sentinels. They shall not disturb each other."
(unless (process-live-p proc)
(setq buffers (delq buf buffers))))))
;; Checks. All process output shall exists in the
;; Checks. All process output shall exist in the
;; respective buffers. All created files shall be
;; deleted.
(tramp--test-message "Check %s" (current-time-string))
@ -7309,10 +7338,10 @@ process sentinels. They shall not disturb each other."
(ignore-errors (cancel-timer timer))
(ignore-errors (delete-directory tmp-name 'recursive))))))
;; (tramp--test-deftest-direct-async-process tramp-test44-asynchronous-requests
;; (tramp--test-deftest-direct-async-process tramp-test45-asynchronous-requests
;; 'unstable)
(ert-deftest tramp-test45-dired-compress-file ()
(ert-deftest tramp-test46-dired-compress-file ()
"Check that Tramp (un)compresses normal files."
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
@ -7333,7 +7362,7 @@ process sentinels. They shall not disturb each other."
(should (string= tmp-name (dired-get-filename)))
(delete-file tmp-name)))
(ert-deftest tramp-test45-dired-compress-dir ()
(ert-deftest tramp-test46-dired-compress-dir ()
"Check that Tramp (un)compresses directories."
(skip-unless (tramp--test-enabled))
(skip-unless (tramp--test-sh-p))
@ -7355,7 +7384,7 @@ process sentinels. They shall not disturb each other."
(delete-directory tmp-name)
(delete-file (concat tmp-name ".tar.gz"))))
(ert-deftest tramp-test46-read-password ()
(ert-deftest tramp-test47-read-password ()
"Check Tramp password handling."
:tags '(:expensive-test)
(skip-unless (tramp--test-enabled))
@ -7415,7 +7444,7 @@ process sentinels. They shall not disturb each other."
(should (file-exists-p ert-remote-temporary-file-directory)))))))))
;; This test is inspired by Bug#29163.
(ert-deftest tramp-test47-auto-load ()
(ert-deftest tramp-test48-auto-load ()
"Check that Tramp autoloads properly."
;; If we use another syntax but `default', Tramp is already loaded
;; due to the `tramp-change-syntax' call.
@ -7440,7 +7469,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
(ert-deftest tramp-test47-delay-load ()
(ert-deftest tramp-test48-delay-load ()
"Check that Tramp is loaded lazily, only when needed."
;; Tramp is neither loaded at Emacs startup, nor when completing a
;; non-Tramp file name like "/foo". Completing a Tramp-alike file
@ -7470,7 +7499,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument (format code tm)))))))))
(ert-deftest tramp-test47-recursive-load ()
(ert-deftest tramp-test48-recursive-load ()
"Check that Tramp does not fail due to recursive load."
(skip-unless (tramp--test-enabled))
@ -7494,7 +7523,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code))))))))
(ert-deftest tramp-test47-remote-load-path ()
(ert-deftest tramp-test48-remote-load-path ()
"Check that Tramp autoloads its packages with remote `load-path'."
;; `tramp-cleanup-all-connections' is autoloaded from tramp-cmds.el.
;; It shall still work, when a remote file name is in the
@ -7519,7 +7548,7 @@ process sentinels. They shall not disturb each other."
(mapconcat #'shell-quote-argument load-path " -L ")
(shell-quote-argument code)))))))
(ert-deftest tramp-test48-unload ()
(ert-deftest tramp-test49-unload ()
"Check that Tramp and its subpackages unload completely.
Since it unloads Tramp, it shall be the last test to run."
:tags '(:expensive-test)
@ -7620,19 +7649,19 @@ If INTERACTIVE is non-nil, the tests are run interactively."
;; * file-name-case-insensitive-p
;; * memory-info
;; * tramp-get-home-directory
;; * tramp-get-remote-gid
;; * tramp-get-remote-groups
;; * tramp-get-remote-uid
;; * tramp-set-file-uid-gid
;; * Work on skipped tests. Make a comment, when it is impossible.
;; * Revisit expensive tests, once problems in `tramp-error' are solved.
;; * Fix `tramp-test06-directory-file-name' for "ftp".
;; * Check, why a process filter t doesn't work in
;; `tramp-test29-start-file-process' and
;; `tramp-test30-make-process'.
;; * Implement `tramp-test31-interrupt-process' and
;; `tramp-test31-signal-process' for "adb", "sshfs" and for direct
;; async processes. Check, why they don't run stable.
;; * Check, why direct async processes do not work for
;; `tramp-test44-asynchronous-requests'.
;; `tramp-test45-asynchronous-requests'.
(provide 'tramp-tests)

View file

@ -0,0 +1,94 @@
variable = foo(
[
qwe
], [
rty
], {
a: 3
}
)
tee = [
qwe
]
qux = [1,
2]
att = {a: 1,
b: 2}
a = 1 ? 2 :(
2 + 3
)
unless bismark
sink += 12
else
dog = 99
end
foo1 =
subject.update(
1
)
foo2 =
subject.
update(
# Might make sense to indent this to 'subject' instead; but this
# style seems more popular.
2
)
foo > bar &&
tee < qux
1 .. 2 &&
3
a = foo(j, k) -
bar_tee
qux = foo.fee ?
bar :
tee
with_paren = (a + b *
c * d +
12)
without_paren = a + b *
c * d +
12
{'a' => {
'b' => 'c',
'd' => %w(e f)
}
}
[1, 2, {
'b' => 'c',
'd' => %w(e f)
}
]
foo(a, {
a: b,
c: d
})
foo(foo, bar:
tee)
foo(foo, :bar =>
tee)
# Local Variables:
# mode: ruby-ts
# ruby-after-operator-indent: t
# ruby-block-indent: t
# ruby-method-call-indent: t
# ruby-method-params-indent: t
# End:

View file

@ -250,8 +250,12 @@ The whitespace before and including \"|\" on each line is removed."
(should (equal (buffer-string) orig))))
(kill-buffer buf)))))
(ruby-ts-deftest-indent "ruby-method-params-indent.rb")
(ruby-ts-deftest-indent "ruby-ts.rb")
(ruby-ts-deftest-indent "ruby-after-operator-indent.rb")
(ruby-ts-deftest-indent "ruby-block-indent.rb")
(ruby-ts-deftest-indent "ruby-method-call-indent.rb")
(ruby-ts-deftest-indent "ruby-method-params-indent.rb")
(ruby-ts-deftest-indent "ruby-parenless-call-arguments-indent.rb")
(provide 'ruby-ts-mode-tests)

View file

@ -8315,29 +8315,35 @@ dicta sunt, explicabo. "))
(remove-hook 'buffer-list-update-hook bluh))))
(ert-deftest buffer-tests-inhibit-buffer-hooks-indirect ()
"Indirect buffers do not call `get-buffer-create'."
(dolist (inhibit '(nil t))
(let ((base (get-buffer-create "foo" inhibit)))
"Test `make-indirect-buffer' argument INHIBIT-BUFFER-HOOKS."
(let* ( base run-bluh run-kbh run-kbqf
(bluh (lambda () (setq run-bluh t)))
(kbh (lambda () (setq run-kbh t)))
(kbqf (lambda () (setq run-kbqf t))))
(dolist (inhibit-base '(nil t))
(unwind-protect
(dotimes (_i 11)
(let* (flag*
(flag (lambda () (prog1 t (setq flag* t))))
(indirect (make-indirect-buffer base "foo[indirect]" nil
inhibit)))
(unwind-protect
(progn
(with-current-buffer indirect
(add-hook 'kill-buffer-query-functions flag nil t))
(kill-buffer indirect)
(if inhibit
(should-not flag*)
(should flag*)))
(let (kill-buffer-query-functions)
(let (indirect)
(setq base (generate-new-buffer " base" inhibit-base))
(dolist (inhibit-indirect '(nil t))
(dotimes (_ 11)
(unwind-protect
(let ((name (generate-new-buffer-name " indirect")))
(setq run-bluh nil run-kbh nil run-kbqf nil)
(add-hook 'buffer-list-update-hook bluh)
(with-current-buffer
(setq indirect (make-indirect-buffer
base name nil inhibit-indirect))
(add-hook 'kill-buffer-hook kbh nil t)
(add-hook 'kill-buffer-query-functions kbqf nil t)
(kill-buffer))
(should (xor inhibit-indirect run-bluh))
(should (xor inhibit-indirect run-kbh))
(should (xor inhibit-indirect run-kbqf)))
(remove-hook 'buffer-list-update-hook bluh)
(when (buffer-live-p indirect)
(kill-buffer indirect))))))
(let (kill-buffer-query-functions)
(when (buffer-live-p base)
(kill-buffer base)))))))
(when (buffer-live-p base)
(kill-buffer base))))))
(ert-deftest zero-length-overlays-and-not ()
(with-temp-buffer