[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
feature/android 6253e7e742 3/3: Merge remote-tracking branch 'origin/mas
From: |
Po Lu |
Subject: |
feature/android 6253e7e742 3/3: Merge remote-tracking branch 'origin/master' into feature/android |
Date: |
Tue, 17 Jan 2023 09:12:03 -0500 (EST) |
branch: feature/android
commit 6253e7e74249c7cdfa86723f0b91a1d207cb143e
Merge: 1b8258a1f2 96015c9c8c
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Merge remote-tracking branch 'origin/master' into feature/android
---
doc/lispref/files.texi | 6 +-
doc/lispref/os.texi | 10 ++
doc/misc/eshell.texi | 8 +
etc/NEWS | 6 +
lisp/emacs-lisp/byte-opt.el | 3 +
lisp/emacs-lisp/bytecomp.el | 2 +-
lisp/eshell/em-prompt.el | 2 +-
lisp/eshell/esh-var.el | 1 +
lisp/htmlfontify.el | 14 +-
lisp/net/tramp-adb.el | 1 +
lisp/net/tramp-archive.el | 7 +
lisp/net/tramp-crypt.el | 1 +
lisp/net/tramp-gvfs.el | 1 +
lisp/net/tramp-rclone.el | 1 +
lisp/net/tramp-sh.el | 1 +
lisp/net/tramp-smb.el | 1 +
lisp/net/tramp-sshfs.el | 1 +
lisp/net/tramp-sudoedit.el | 1 +
lisp/net/tramp.el | 13 +-
lisp/progmodes/cc-engine.el | 8 +-
lisp/progmodes/dockerfile-ts-mode.el | 4 +
lisp/progmodes/eglot.el | 24 +--
lisp/progmodes/js.el | 15 +-
lisp/progmodes/json-ts-mode.el | 2 +
lisp/progmodes/ruby-ts-mode.el | 32 +++-
lisp/progmodes/typescript-ts-mode.el | 14 +-
lisp/simple.el | 12 ++
lisp/subr.el | 6 +-
lisp/treesit.el | 1 -
lisp/use-package/use-package-core.el | 2 +-
lisp/use-package/use-package.el | 2 +-
src/w32fns.c | 16 +-
src/xterm.c | 188 ++++++++++++++++++++-
src/xterm.h | 17 ++
test/lisp/eshell/esh-var-tests.el | 4 +
.../lisp/progmodes/c-ts-mode-resources/indent.erts | 14 ++
.../progmodes/java-ts-mode-resources/indent.erts | 44 +++++
.../progmodes/java-ts-mode-resources/movement.erts | 154 +++++++++++++++++
test/lisp/progmodes/java-ts-mode-tests.el | 35 ++++
test/lisp/progmodes/ruby-ts-mode-tests.el | 1 +
.../typescript-ts-mode-resources/indent.erts | 73 ++++++++
test/lisp/progmodes/typescript-ts-mode-tests.el | 31 ++++
42 files changed, 714 insertions(+), 65 deletions(-)
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 5cc4c1e7dd..ad01e0f288 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -3390,7 +3390,8 @@ first, before handlers for jobs such as remote file
access.
@code{file-readable-p}, @code{file-regular-p},
@code{file-remote-p}, @code{file-selinux-context},
@code{file-symlink-p}, @code{file-system-info},
-@code{file-truename}, @code{file-writable-p},
+@code{file-truename}, @code{file-user-uid},
+@code{file-writable-p},
@code{find-backup-file-name},@*
@code{get-file-buffer},
@code{insert-directory},
@@ -3451,7 +3452,8 @@ first, before handlers for jobs such as remote file
access.
@code{file-readable-p}, @code{file-regular-p},
@code{file-remote-p}, @code{file-selinux-context},
@code{file-symlink-p}, @code{file-system-info},
-@code{file-truename}, @code{file-writable-p},
+@code{file-truename}, @code{file-user-uid},
+@code{file-writable-p},
@code{find-backup-file-name},
@code{get-file-buffer},
@code{insert-directory},
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 094e954e82..53ca128582 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1280,6 +1280,16 @@ This function returns the real @acronym{UID} of the user.
This function returns the effective @acronym{UID} of the user.
@end defun
+@defun file-user-uid
+This function returns the connection-local value for the user's
+effective @acronym{UID}. If @code{default-directory} is local, this
+is equivalent to @code{user-uid}, but for remote files (@pxref{Remote
+Files, , , emacs, The GNU Emacs Manual}), it will return the
+@acronym{UID} for the user associated with that remote connection; if
+the remote connection has no associated user, it will instead return
+-1.
+@end defun
+
@cindex GID
@defun group-gid
This function returns the effective @acronym{GID} of the Emacs process.
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index fc7d52eb71..c40ff58f42 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -983,6 +983,13 @@ whenever you change the current directory to a different
host
the value will automatically update to reflect the search path on that
host.
+@vindex $UID
+@item $UID
+This returns the effective @acronym{UID} for the current user. This
+variable is connection-aware, so when the current directory is remote,
+its value will be @acronym{UID} for the user associated with that
+remote connection.
+
@vindex $_
@item $_
This refers to the last argument of the last command. With a
@@ -1014,6 +1021,7 @@ that are currently visible in the Eshell window. They
are both
copied to the environment, so external commands invoked from
Eshell can consult them to do the right thing.
+@vindex $INSIDE_EMACS
@item $INSIDE_EMACS
This variable indicates to external commands that they are being
invoked from within Emacs so they can adjust their behavior if
diff --git a/etc/NEWS b/etc/NEWS
index 068f7a27db..cde6783349 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -235,6 +235,12 @@ compared reliably at all.
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,
+so it will return the remote UID for remote files (or -1 if the
+connection has no associated user).
+
* Changes in Emacs 30.1 on Non-Free Operating Systems
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index d7a0d851e0..039cebedb4 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -1380,6 +1380,9 @@ See Info node `(elisp) Integer Basics'."
;; (apply F ... (list X Y ...)) -> (funcall F ... X Y ...)
((eq (car-safe last) 'list)
`(funcall ,fn ,@(butlast (cddr form)) ,@(cdr last)))
+ ;; (apply F ... (cons X Y)) -> (apply F ... X Y)
+ ((eq (car-safe last) 'cons)
+ (append (butlast form) (cdr last)))
(t form)))
form)))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index 23d02ba92c..fb4b73b1c1 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -1575,7 +1575,7 @@ extra args."
"`%s' called with %d args to fill %d format field(s)" (car form)
nargs nfields)))))
-(dolist (elt '(format message error))
+(dolist (elt '(format message format-message error))
(put elt 'byte-compile-format-like t))
(defun byte-compile--suspicious-defcustom-choice (type)
diff --git a/lisp/eshell/em-prompt.el b/lisp/eshell/em-prompt.el
index 52d46282c5..b3a0fadf61 100644
--- a/lisp/eshell/em-prompt.el
+++ b/lisp/eshell/em-prompt.el
@@ -52,7 +52,7 @@ as is common with most shells."
(defcustom eshell-prompt-function
(lambda ()
(concat (abbreviate-file-name (eshell/pwd))
- (if (= (user-uid) 0) " # " " $ ")))
+ (if (= (file-user-uid) 0) " # " " $ ")))
"A function that returns the Eshell prompt string.
Make sure to update `eshell-prompt-regexp' so that it will match your
prompt."
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 811bb9957c..fd76a2c6f0 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -162,6 +162,7 @@ if they are quoted with a backslash."
("COLUMNS" ,(lambda () (window-body-width nil 'remap)) t t)
("LINES" ,(lambda () (window-body-height nil 'remap)) t t)
("INSIDE_EMACS" eshell-inside-emacs t)
+ ("UID" ,(lambda () (file-user-uid)) nil t)
;; for esh-ext.el
("PATH" (,(lambda () (string-join (eshell-get-path t) (path-separator)))
diff --git a/lisp/htmlfontify.el b/lisp/htmlfontify.el
index 0959405081..1ab33cc641 100644
--- a/lisp/htmlfontify.el
+++ b/lisp/htmlfontify.el
@@ -373,13 +373,13 @@ otherwise."
:type '(string))
(defcustom hfy-exclude-file-rules
- '("\\.flc$"
- "/CVS/.*"
- ".*~$"
- "/\\.git\\(?:/.*\\)?$")
- "Define some regular expressions to exclude files"
+ '("\\.flc\\'"
+ "/CVS/"
+ "~\\'"
+ "/\\.git\\(?:/\\|\\'\\)")
+ "Regular expressions matching files to exclude."
:tag "exclude-rules"
- :type '(list string)
+ :type '(repeat regexp)
:version "29.1")
(defcustom hfy-display-class nil
@@ -1835,7 +1835,7 @@ Strips any leading \"./\" from each filename."
(seq-some (lambda (r)
(string-match r f))
hfy-exclude-file-rules)))
- (directory-files-recursively "." ".*" nil t)))
+ (directory-files-recursively "." "" nil t)))
;; strip the filename off, return a directory name
;; not a particularly thorough implementation, but it will be
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 29b9f894ec..10f33e5f92 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -153,6 +153,7 @@ It is used for TCP/IP devices."
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-adb-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-adb-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-archive.el b/lisp/net/tramp-archive.el
index 3b1d568c12..b9cf85bd84 100644
--- a/lisp/net/tramp-archive.el
+++ b/lisp/net/tramp-archive.el
@@ -265,6 +265,7 @@ It must be supported by libarchive(3).")
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-archive-handle-file-system-info)
(file-truename . tramp-archive-handle-file-truename)
+ (file-user-uid . tramp-archive-handle-file-user-uid)
(file-writable-p . ignore)
(find-backup-file-name . ignore)
;; `get-file-buffer' performed by default handler.
@@ -701,6 +702,12 @@ 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
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 507fd43241..b9d0d96ecc 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -204,6 +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-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.
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index ea774d0b9b..02ceb2979f 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -798,6 +798,7 @@ It has been changed in GVFS 1.14.")
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-gvfs-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-rclone.el b/lisp/net/tramp-rclone.el
index b28f9f6495..9eb2a54cdc 100644
--- a/lisp/net/tramp-rclone.el
+++ b/lisp/net/tramp-rclone.el
@@ -118,6 +118,7 @@
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-rclone-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index acbb6aea13..46b1f61210 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -1086,6 +1086,7 @@ Format specifiers \"%s\" are replaced before the script
is used.")
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-sh-handle-file-system-info)
(file-truename . tramp-sh-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-sh-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index b3f0344f81..9d03490f1d 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -269,6 +269,7 @@ See `tramp-actions-before-shell' for more info.")
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-smb-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-smb-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-sshfs.el b/lisp/net/tramp-sshfs.el
index 27b2854e45..65c4bf23c3 100644
--- a/lisp/net/tramp-sshfs.el
+++ b/lisp/net/tramp-sshfs.el
@@ -124,6 +124,7 @@
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-sshfs-handle-file-system-info)
(file-truename . tramp-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-sshfs-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index ce080918e0..db7ac84287 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -114,6 +114,7 @@ See `tramp-actions-before-shell' for more info.")
(file-symlink-p . tramp-handle-file-symlink-p)
(file-system-info . tramp-sudoedit-handle-file-system-info)
(file-truename . tramp-sudoedit-handle-file-truename)
+ (file-user-uid . tramp-handle-file-user-uid)
(file-writable-p . tramp-sudoedit-handle-file-writable-p)
(find-backup-file-name . tramp-handle-find-backup-file-name)
;; `get-file-buffer' performed by default handler.
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 169cf1982b..fab1962d2b 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2632,7 +2632,9 @@ Must be handled by the callers."
'(exec-path make-nearby-temp-file make-process process-file
shell-command start-file-process temporary-file-directory
;; Emacs 29+ only.
- list-system-processes memory-info process-attributes))
+ list-system-processes memory-info process-attributes
+ ;; Emacs 30+ only.
+ file-user-uid))
default-directory)
;; PROC.
((member operation '(file-notify-rm-watch file-notify-valid-p))
@@ -3714,6 +3716,15 @@ Let-bind it when necessary.")
vec (concat "~" (substring filename (match-beginning 1))))
(tramp-make-tramp-file-name (tramp-dissect-file-name filename)))))
+(defun tramp-handle-file-user-uid ()
+ "Like `user-uid' for Tramp files."
+ (let ((v (tramp-dissect-file-name default-directory)))
+ (or (tramp-get-remote-uid v 'integer)
+ ;; Some handlers for `tramp-get-remote-uid' return nil if they
+ ;; can't get the UID; always return -1 in this case for
+ ;; consistency.
+ -1)))
+
(defun tramp-handle-access-file (filename string)
"Like `access-file' for Tramp files."
(setq filename (file-truename filename))
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index 8ac3ef6808..45d90ea243 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -10863,7 +10863,13 @@ This function might do hidden buffer changes."
;; types; other identifiers could just as well be
;; constants in C++.
(memq at-type '(known found)))))
- (throw 'at-decl-or-cast t)
+ (progn
+ ;; The user may be part way through typing a statement
+ ;; beginning with an identifier. This makes a 'maybe
+ ;; type in the following "declarator"'s arglist suspect.
+ (when (eq at-type 'maybe)
+ (setq unsafe-maybe t))
+ (throw 'at-decl-or-cast t))
;; CASE 7
;; Can't be a valid declaration or cast, but if we've found a
;; specifier it can't be anything else either, so treat it as
diff --git a/lisp/progmodes/dockerfile-ts-mode.el
b/lisp/progmodes/dockerfile-ts-mode.el
index 3f8766e671..1b91681f08 100644
--- a/lisp/progmodes/dockerfile-ts-mode.el
+++ b/lisp/progmodes/dockerfile-ts-mode.el
@@ -161,6 +161,10 @@ the subtrees."
(setq-local treesit-simple-indent-rules
dockerfile-ts-mode--indent-rules)
+ ;; Navigation
+ (setq-local treesit-sentence-type-regexp
+ "instruction")
+
;; Font-lock.
(setq-local treesit-font-lock-settings
dockerfile-ts-mode--font-lock-settings)
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index a846baa1b1..8ce1a8b7ba 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -1075,7 +1075,7 @@ suitable root directory for a given LSP server's
purposes."
;;;###autoload
(defun eglot (managed-major-mode project class contact language-id
- &optional interactive)
+ &optional _interactive)
"Start LSP server in support of PROJECT's buffers under MANAGED-MAJOR-MODE.
This starts a Language Server Protocol (LSP) server suitable for the
@@ -1112,17 +1112,17 @@ described in `eglot-server-programs', which see.
LANGUAGE-ID is the language ID string to send to the server for
MANAGED-MAJOR-MODE, which matters to a minority of servers.
-INTERACTIVE is t if called interactively."
- (interactive (append (eglot--guess-contact t) '(t)))
- (setq managed-major-mode (eglot--ensure-list managed-major-mode))
- (let* ((current-server (eglot-current-server))
- (live-p (and current-server (jsonrpc-running-p current-server))))
- (if (and live-p
- interactive
- (y-or-n-p "[eglot] Live process found, reconnect instead? "))
- (eglot-reconnect current-server interactive)
- (when live-p (ignore-errors (eglot-shutdown current-server)))
- (eglot--connect managed-major-mode project class contact language-id))))
+INTERACTIVE is ignored and provided for backward compatibility."
+ (interactive
+ (let ((current-server (eglot-current-server)))
+ (unless (or (null current-server)
+ (y-or-n-p "\
+[eglot] Shut down current connection before attempting new one?"))
+ (user-error "[eglot] Connection attempt aborted by user."))
+ (prog1 (append (eglot--guess-contact t) '(t))
+ (when current-server (ignore-errors (eglot-shutdown current-server))))))
+ (eglot--connect (eglot--ensure-list managed-major-mode)
+ project class contact language-id))
(defun eglot-reconnect (server &optional interactive)
"Reconnect to SERVER.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index fa3b4687ef..28305a0b39 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3454,13 +3454,16 @@ This function is intended for use in
`after-change-functions'."
((parent-is "statement_block") parent-bol js-indent-level)
;; JSX
- ((node-is "jsx_fragment") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_element") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_expression") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_self_closing_element") parent
typescript-ts-mode-indent-offset)
+ ((match "<" "jsx_fragment") parent 0)
+ ((parent-is "jsx_fragment") parent js-indent-level)
((node-is "jsx_closing_element") parent 0)
- ((node-is "/") parent 0)
- ((node-is ">") parent 0)))))
+ ((node-is "jsx_element") parent js-indent-level)
+ ((parent-is "jsx_element") parent js-indent-level)
+ ((parent-is "jsx_opening_element") parent js-indent-level)
+ ((parent-is "jsx_expression") parent-bol js-indent-level)
+ ((match "/" "jsx_self_closing_element") parent 0)
+ ((parent-is "jsx_self_closing_element") parent js-indent-level)
+ (no-node parent-bol 0)))))
(defvar js--treesit-keywords
'("as" "async" "await" "break" "case" "catch" "class" "const" "continue"
diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el
index fbcda22acc..f6a303290a 100644
--- a/lisp/progmodes/json-ts-mode.el
+++ b/lisp/progmodes/json-ts-mode.el
@@ -147,6 +147,8 @@ Return nil if there is no name or if NODE is not a defun
node."
(rx (or "pair" "object")))
(setq-local treesit-defun-name-function #'json-ts-mode--defun-name)
+ (setq-local treesit-sentence-type-regexp "pair")
+
;; Font-lock.
(setq-local treesit-font-lock-settings json-ts-mode--font-lock-settings)
(setq-local treesit-font-lock-feature-list
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index d68b57966b..939c054b04 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -780,12 +780,20 @@ i.e. expr of def foo(args) = expr is returned."
;; but with node set to the statement and parent set to
;; body_statement for all others. ... Fine. Be that way.
;; Ditto for "block" and "block_body"
- ((node-is "body_statement") parent-bol ruby-indent-level)
- ((parent-is "body_statement") (ruby-ts--bol
ruby-ts--grand-parent-node) ruby-indent-level)
- ((match "end" "do_block") parent-bol 0)
- ((n-p-gp "block_body" "block" nil) parent-bol ruby-indent-level)
- ((n-p-gp nil "block_body" "block") (ruby-ts--bol
ruby-ts--grand-parent-node) ruby-indent-level)
- ((match "}" "block") parent-bol 0)
+ ((node-is "body_statement")
+ (ruby-ts--block-indent-anchor ruby-ts--parent-node)
+ ruby-indent-level)
+ ((parent-is "body_statement")
+ (ruby-ts--block-indent-anchor ruby-ts--grand-parent-node)
+ ruby-indent-level)
+ ((match "end" "do_block") (ruby-ts--block-indent-anchor
ruby-ts--parent-node) 0)
+ ((n-p-gp "block_body" "block" nil)
+ (ruby-ts--block-indent-anchor ruby-ts--parent-node)
+ ruby-indent-level)
+ ((n-p-gp nil "block_body" "block")
+ (ruby-ts--block-indent-anchor ruby-ts--grand-parent-node)
+ ruby-indent-level)
+ ((match "}" "block") (ruby-ts--block-indent-anchor
ruby-ts--parent-node) 0)
;; Chained strings
((match "string" "chained_string") first-sibling 0)
@@ -794,6 +802,18 @@ i.e. expr of def foo(args) = expr is returned."
(catch-all parent-bol ruby-indent-level))))
`((ruby . ,common))))
+(defun ruby-ts--block-indent-anchor (block-node-getter)
+ (lambda (node parent _bol &rest _rest)
+ (let ((block-node (funcall block-node-getter node parent)))
+ (save-excursion
+ (goto-char
+ (treesit-node-start
+ (if ruby-block-indent
+ (ruby-ts--statement-ancestor block-node)
+ block-node)))
+ (back-to-indentation)
+ (point)))))
+
(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)))
diff --git a/lisp/progmodes/typescript-ts-mode.el
b/lisp/progmodes/typescript-ts-mode.el
index cd631d048e..f7bf7ed7e4 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -97,13 +97,15 @@ Argument LANGUAGE is either `typescript' or `tsx'."
((parent-is "binary_expression") parent-bol
typescript-ts-mode-indent-offset)
,@(when (eq language 'tsx)
- `(((node-is "jsx_fragment") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_element") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_expression") parent typescript-ts-mode-indent-offset)
- ((node-is "jsx_self_closing_element") parent
typescript-ts-mode-indent-offset)
+ `(((match "<" "jsx_fragment") parent 0)
+ ((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset)
((node-is "jsx_closing_element") parent 0)
- ((node-is "/") parent 0)
- ((node-is ">") parent 0)))
+ ((node-is "jsx_element") parent typescript-ts-mode-indent-offset)
+ ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset)
+ ((parent-is "jsx_opening_element") parent
typescript-ts-mode-indent-offset)
+ ((parent-is "jsx_expression") parent-bol
typescript-ts-mode-indent-offset)
+ ((match "/" "jsx_self_closing_element") parent 0)
+ ((parent-is "jsx_self_closing_element") parent
typescript-ts-mode-indent-offset)))
(no-node parent-bol 0))))
(defvar typescript-ts-mode--keywords
diff --git a/lisp/simple.el b/lisp/simple.el
index 4b09f41de5..844cfa68b0 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -4730,6 +4730,18 @@ Also see the `async-shell-command-buffer' variable."
action))
(user-error "Shell command in progress"))))
+(defun file-user-uid ()
+ "Return the connection-local effective uid.
+This is similar to `user-uid', but may invoke a file name handler
+based on `default-directory'. See Info node `(elisp)Magic File
+Names'.
+
+If a file name handler is unable to retrieve the effective uid,
+this function will instead return -1."
+ (if-let ((handler (find-file-name-handler default-directory 'file-user-uid)))
+ (funcall handler 'file-user-uid)
+ (user-uid)))
+
(defun max-mini-window-lines (&optional frame)
"Compute maximum number of lines for echo area in FRAME.
As defined by `max-mini-window-height'. FRAME defaults to the
diff --git a/lisp/subr.el b/lisp/subr.el
index 1762c94a43..f909b63aab 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -2562,12 +2562,14 @@ The variable list SPEC is the same as in `if-let'."
Evaluate each binding in turn, stopping if a binding value is nil.
If all bindings are non-nil, eval BODY and repeat.
-The variable list SPEC is the same as in `if-let'."
+The variable list SPEC is the same as in `if-let*'."
(declare (indent 1) (debug if-let))
(let ((done (gensym "done")))
`(catch ',done
(while t
- (if-let ,spec
+ ;; This is `if-let*', not `if-let', deliberately, despite the
+ ;; name of this macro. See bug#60758.
+ (if-let* ,spec
(progn
,@body)
(throw ',done nil))))))
diff --git a/lisp/treesit.el b/lisp/treesit.el
index e9f5a8b37b..69bfff21df 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1152,7 +1152,6 @@ See `treesit-simple-indent-presets'.")
(and (>= (point) comment-start-bol)
adaptive-fill-regexp
(looking-at adaptive-fill-regexp)
- (> (match-end 0) (match-beginning 0))
(match-end 0))))))
;; TODO: Document.
(cons 'grand-parent
diff --git a/lisp/use-package/use-package-core.el
b/lisp/use-package/use-package-core.el
index 379e119b60..7ab5bdc276 100644
--- a/lisp/use-package/use-package-core.el
+++ b/lisp/use-package/use-package-core.el
@@ -65,7 +65,7 @@
:link '(custom-manual "(use-package) Top")
:version "29.1")
-(defconst use-package-version "2.4.4"
+(defconst use-package-version "2.4.5"
"This version of `use-package'.")
(defcustom use-package-keywords
diff --git a/lisp/use-package/use-package.el b/lisp/use-package/use-package.el
index 7682468522..1b63a6d651 100644
--- a/lisp/use-package/use-package.el
+++ b/lisp/use-package/use-package.el
@@ -5,7 +5,7 @@
;; Author: John Wiegley <johnw@newartisans.com>
;; Maintainer: John Wiegley <johnw@newartisans.com>
;; Created: 17 Jun 2012
-;; Version: 2.4.4
+;; Version: 2.4.5
;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
;; Keywords: dotemacs startup speed config package extensions
;; URL: https://github.com/jwiegley/use-package
diff --git a/src/w32fns.c b/src/w32fns.c
index 192d3ddf27..b4192a5ffa 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -10396,8 +10396,8 @@ to be converted to forward slashes by the caller. */)
#endif /* WINDOWSNT */
/* Query a value from the Windows Registry (under HKCU and HKLM),
- where `key` is the registry key, `name` is the name, and `lpdwtype`
- is a pointer to the return value's type. `lpwdtype` can be NULL if
+ where `key' is the registry key, `name' is the name, and `lpdwtype'
+ is a pointer to the return value's type. `lpwdtype' can be NULL if
you do not care about the type.
Returns: pointer to the value, or null pointer if the key/name does
@@ -10664,7 +10664,7 @@ pops up the Windows Run dialog, <lwindow>-<Pause> pops
up the "System
Properties" dialog, etc. On Windows 10, no \"Windows\" key
combinations are normally handed to applications. To enable Emacs to
process \"Windows\" key combinations, use the function
-`w32-register-hot-key`.
+`w32-register-hot-key'.
For Windows 98/ME, see the doc string of `w32-phantom-key-code'. */);
Vw32_pass_lwindow_to_system = Qt;
@@ -10683,7 +10683,7 @@ pops up the Windows Run dialog, <rwindow>-<Pause> pops
up the "System
Properties" dialog, etc. On Windows 10, no \"Windows\" key
combinations are normally handed to applications. To enable Emacs to
process \"Windows\" key combinations, use the function
-`w32-register-hot-key`.
+`w32-register-hot-key'.
For Windows 98/ME, see the doc string of `w32-phantom-key-code'. */);
Vw32_pass_rwindow_to_system = Qt;
@@ -10698,7 +10698,7 @@ acting on \"Windows\" key events when
`w32-pass-lwindow-to-system' or
`w32-pass-rwindow-to-system' is nil.
This variable is only used on Windows 98 and ME. For other Windows
-versions, see the documentation of the `w32-register-hot-key`
+versions, see the documentation of the `w32-register-hot-key'
function. */);
/* Although 255 is technically not a valid key code, it works and
means that this hack won't interfere with any real key code. */
@@ -10732,7 +10732,7 @@ The value can be hyper, super, meta, alt, control or
shift for the
respective modifier, or nil to appear as the `lwindow' key.
Any other value will cause the key to be ignored.
-Also see the documentation of the `w32-register-hot-key` function. */);
+Also see the documentation of the `w32-register-hot-key' function. */);
Vw32_lwindow_modifier = Qnil;
DEFVAR_LISP ("w32-rwindow-modifier",
@@ -10742,7 +10742,7 @@ The value can be hyper, super, meta, alt, control or
shift for the
respective modifier, or nil to appear as the `rwindow' key.
Any other value will cause the key to be ignored.
-Also see the documentation of the `w32-register-hot-key` function. */);
+Also see the documentation of the `w32-register-hot-key' function. */);
Vw32_rwindow_modifier = Qnil;
DEFVAR_LISP ("w32-apps-modifier",
@@ -11271,7 +11271,7 @@ globals_of_w32fns (void)
get_proc_addr (hm_kernel32, "SetThreadDescription");
/* Support OS dark mode on Windows 10 version 1809 and higher.
- See `w32_applytheme` which uses appropriate APIs per version of Windows.
+ See `w32_applytheme' which uses appropriate APIs per version of Windows.
For future wretches who may need to understand Windows build numbers:
https://docs.microsoft.com/en-us/windows/release-health/release-information
*/
diff --git a/src/xterm.c b/src/xterm.c
index 028bb7582c..1373045393 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -5750,7 +5750,8 @@ xi_device_from_id (struct x_display_info *dpyinfo, int
deviceid)
static void
xi_link_touch_point (struct xi_device_t *device,
- int detail, double x, double y)
+ int detail, double x, double y,
+ struct frame *frame)
{
struct xi_touch_point_t *touchpoint;
@@ -5759,6 +5760,7 @@ xi_link_touch_point (struct xi_device_t *device,
touchpoint->x = x;
touchpoint->y = y;
touchpoint->number = detail;
+ touchpoint->frame = frame;
device->touchpoints = touchpoint;
}
@@ -5787,6 +5789,36 @@ xi_unlink_touch_point (int detail,
return false;
}
+/* Unlink all touch points associated with the frame F.
+ This is done upon unmapping or destroying F's window, because
+ touch point delivery after that point is undefined. */
+
+static void
+xi_unlink_touch_points (struct frame *f)
+{
+ struct xi_device_t *device;
+ struct xi_touch_point_t **next, *last;
+ int i;
+
+ for (i = 0; i < FRAME_DISPLAY_INFO (f)->num_devices; ++i)
+ {
+ device = &FRAME_DISPLAY_INFO (f)->devices[i];
+
+ /* Now unlink all touch points on DEVICE matching F. */
+
+ for (next = &device->touchpoints; (last = *next);)
+ {
+ if (last->frame == f)
+ {
+ *next = last->next;
+ xfree (last);
+ }
+ else
+ next = &last->next;
+ }
+ }
+}
+
static struct xi_touch_point_t *
xi_find_touch_point (struct xi_device_t *device, int detail)
{
@@ -13535,6 +13567,10 @@ xi_disable_devices (struct x_display_info *dpyinfo,
#ifdef HAVE_XINPUT2_2
struct xi_touch_point_t *tem, *last;
#endif
+#if defined HAVE_XINPUT2_2 && !defined HAVE_EXT_TOOL_BAR
+ struct x_output *output;
+ Lisp_Object tail, frame;
+#endif
/* Don't pointlessly copy dpyinfo->devices if there are no devices
to disable. */
@@ -13577,6 +13613,34 @@ xi_disable_devices (struct x_display_info *dpyinfo,
tem = tem->next;
xfree (last);
}
+
+#ifndef HAVE_EXT_TOOL_BAR
+
+ /* Now look through each frame on DPYINFO. If it has an
+ outstanding tool bar press for this device, release
+ the tool bar. */
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (!FRAME_X_P (XFRAME (frame))
+ || (FRAME_DISPLAY_INFO (XFRAME (frame))
+ != dpyinfo))
+ continue;
+
+ output = FRAME_OUTPUT_DATA (XFRAME (frame));
+
+ if (output->tool_bar_touch_device
+ == dpyinfo->devices[i].device_id)
+ {
+ if (XFRAME (frame)->last_tool_bar_item != -1
+ && WINDOWP (XFRAME (frame)->tool_bar_window))
+ handle_tool_bar_click (XFRAME (frame), 0, 0,
+ false, 0);
+
+ output->tool_bar_touch_device = 0;
+ }
+ }
+#endif
#endif
goto out;
@@ -24209,6 +24273,73 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
#endif
+#ifndef HAVE_EXT_TOOL_BAR
+ /* Is this a touch from a direct touch device that is in
+ the tool-bar? */
+ if (device->direct_p
+ && WINDOWP (f->tool_bar_window)
+ && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
+ {
+ Lisp_Object window;
+ int x = xev->event_x;
+ int y = xev->event_y;
+
+ window = window_from_coordinates (f, x, y, 0, true, true);
+ /* Ignore button release events if the mouse
+ wasn't previously pressed on the tool bar.
+ We do this because otherwise selecting some
+ text with the mouse and then releasing it on
+ the tool bar doesn't stop selecting text,
+ since the tool bar eats the button up
+ event. */
+ tool_bar_p = EQ (window, f->tool_bar_window);
+
+ /* If this touch has started in the tool bar, do not
+ send it to Lisp. Instead, simulate a tool bar
+ click, releasing it once it goes away. */
+
+ if (tool_bar_p)
+ {
+ /* Call note_mouse_highlight on the tool bar
+ item. Otherwise, get_tool_bar_item will
+ return 1.
+
+ This is not necessary when mouse-highlight is
+ nil. */
+
+ if (!NILP (Vmouse_highlight))
+ {
+ note_mouse_highlight (f, x, y);
+
+ /* Always allow future mouse motion to
+ update the mouse highlight, no matter
+ where it is. */
+ memset (&dpyinfo->last_mouse_glyph, 0,
+ sizeof dpyinfo->last_mouse_glyph);
+ dpyinfo->last_mouse_glyph_frame = f;
+ }
+
+ handle_tool_bar_click_with_device (f, x, y, true, 0,
+ (source
+ ? source->name : Qt));
+
+ /* Flush any changes made by that to the front
+ buffer. */
+ x_flush_dirty_back_buffer_on (f);
+
+ /* Record the device and the touch ID on the
+ frame. That way, Emacs knows when to dismiss
+ the tool bar click later. */
+
+ FRAME_OUTPUT_DATA (f)->tool_bar_touch_device
+ = device->device_id;
+ FRAME_OUTPUT_DATA (f)->tool_bar_touch_id = xev->detail;
+
+ goto XI_OTHER;
+ }
+ }
+#endif
+
if (!menu_bar_p && !tool_bar_p)
{
if (f && device->direct_p)
@@ -24218,13 +24349,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_catch_errors (dpyinfo->display);
if (x_input_grab_touch_events)
- XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
- xev->detail, xev->event,
XIAcceptTouch);
+ XIAllowTouchEvents (dpyinfo->display,
+ xev->deviceid,
+ xev->detail, xev->event,
+ XIAcceptTouch);
if (!x_had_errors_p (dpyinfo->display))
{
- xi_link_touch_point (device, xev->detail,
xev->event_x,
- xev->event_y);
+ xi_link_touch_point (device, xev->detail,
+ xev->event_x,
+ xev->event_y, f);
inev.ie.kind = TOUCHSCREEN_BEGIN_EVENT;
inev.ie.timestamp = xev->time;
@@ -24299,10 +24433,11 @@ handle_one_xevent (struct x_display_info *dpyinfo,
for (touchpoint = device->touchpoints;
touchpoint; touchpoint = touchpoint->next)
{
- arg = Fcons (list3i (lrint (touchpoint->x),
- lrint (touchpoint->y),
- lrint (touchpoint->number)),
- arg);
+ if (touchpoint->frame == f)
+ arg = Fcons (list3i (lrint (touchpoint->x),
+ lrint (touchpoint->y),
+ lrint (touchpoint->number)),
+ arg);
}
if (source)
@@ -24348,6 +24483,31 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
}
+ /* Now see if the touchpoint was previously on the tool bar.
+ If it was, release the tool bar. */
+
+ if (!f)
+ f = x_window_to_frame (dpyinfo, xev->event);
+
+ if (f && (FRAME_OUTPUT_DATA (f)->tool_bar_touch_id
+ == xev->detail))
+ {
+ if (f->last_tool_bar_item != -1)
+ handle_tool_bar_click_with_device (f, xev->event_x,
+ xev->event_y,
+ false, 0,
+ (source
+ ? source->name
+ : Qnil));
+
+ /* Cancel any outstanding mouse highlight. */
+ note_mouse_highlight (f, -1, -1);
+ x_flush_dirty_back_buffer_on (f);
+
+ /* Now clear the tool bar device. */
+ FRAME_OUTPUT_DATA (f)->tool_bar_touch_device = 0;
+ }
+
goto XI_OTHER;
}
@@ -28453,6 +28613,11 @@ x_make_frame_invisible (struct frame *f)
block_input ();
+#ifdef HAVE_XINPUT2_2
+ /* Remove any touch points associated with F. */
+ xi_unlink_touch_points (f);
+#endif
+
/* Before unmapping the window, update the WM_SIZE_HINTS property to claim
that the current position of the window is user-specified, rather than
program-specified, so that when the window is mapped again, it will be
@@ -28658,6 +28823,11 @@ x_free_frame_resources (struct frame *f)
xi_handle_delete_frame (dpyinfo, f);
#endif
+#ifdef HAVE_XINPUT2_2
+ /* Remove any touch points associated with F. */
+ xi_unlink_touch_points (f);
+#endif
+
/* If a display connection is dead, don't try sending more
commands to the X server. */
if (dpyinfo->display)
diff --git a/src/xterm.h b/src/xterm.h
index d768ba7ff8..28ae00ca19 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -257,10 +257,17 @@ struct xi_scroll_valuator_t
struct xi_touch_point_t
{
+ /* The next touch point in this list. */
struct xi_touch_point_t *next;
+ /* The touchpoint detail. */
int number;
+
+ /* The last known X and Y position of the touchpoint. */
double x, y;
+
+ /* The frame associated with this touch point. */
+ struct frame *frame;
};
#endif
@@ -1295,6 +1302,16 @@ struct x_output
VisibilityFullyObscured, but is set to something else in
handle_one_xevent. */
int visibility_state;
+
+#ifdef HAVE_XINPUT2_2
+ /* The touch ID of the last touch point to have touched the tool
+ bar. */
+ int tool_bar_touch_id;
+
+ /* The device that last touched the tool bar. 0 if no device
+ touched the tool bar. */
+ int tool_bar_touch_device;
+#endif
};
enum
diff --git a/test/lisp/eshell/esh-var-tests.el
b/test/lisp/eshell/esh-var-tests.el
index 3f602798db..0cc1b92266 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -746,6 +746,10 @@ it, since the setter is nil."
(format "cd %s" ert-remote-temporary-file-directory))
(eshell-match-command-output "echo $PATH" (regexp-quote remote-path)))))
+(ert-deftest esh-var-test/uid-var ()
+ "Test that $UID is equivalent to (user-uid) for local directories."
+ (eshell-command-result-equal "echo $UID" (user-uid)))
+
(ert-deftest esh-var-test/last-status-var-lisp-command ()
"Test using the \"last exit status\" ($?) variable with a Lisp command"
(with-temp-eshell
diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
index 71524e273f..70fce68b0e 100644
--- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts
+++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts
@@ -133,6 +133,20 @@ Name: Multiline Block Comments 4 (bug#60270)
*/
=-=-=
+Name: Multiline Block Comments 5 (bug#60270)
+
+=-=
+/*
+line one
+line 2
+ */
+=-=
+/*
+ line one
+ line 2
+ */
+=-=-=
+
Code:
(lambda ()
diff --git a/test/lisp/progmodes/java-ts-mode-resources/indent.erts
b/test/lisp/progmodes/java-ts-mode-resources/indent.erts
new file mode 100644
index 0000000000..e59d5fed8e
--- /dev/null
+++ b/test/lisp/progmodes/java-ts-mode-resources/indent.erts
@@ -0,0 +1,44 @@
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq java-ts-mode-indent-offset 2)
+ (java-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Point-Char: |
+
+Name: Basic
+
+=-=
+public class Basic {
+ public void basic() {
+ return;
+ }
+}
+=-=-=
+
+Name: Empty Line
+
+=-=
+public class EmptyLine {
+ public void emptyLine() {
+ |
+ }
+}
+=-=-=
+
+Name: Statements
+
+=-=
+if (x) {
+ for (var foo : foos) {
+ |
+ }
+} else if (y) {
+ for (int i = 0; x < foos.size(); i++) {
+ return;
+ }
+} else {
+ return;
+}
+=-=-=
diff --git a/test/lisp/progmodes/java-ts-mode-resources/movement.erts
b/test/lisp/progmodes/java-ts-mode-resources/movement.erts
new file mode 100644
index 0000000000..23639b1f5f
--- /dev/null
+++ b/test/lisp/progmodes/java-ts-mode-resources/movement.erts
@@ -0,0 +1,154 @@
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (forward-sentence 1))
+
+Point-Char: |
+
+Name: forward-sentence moves over if
+
+=-=
+public class Basic {
+ public void basic() {
+ |if (x) {
+
+ }
+ log.info("some text: {}", text);
+ return;
+ }
+}
+=-=
+public class Basic {
+ public void basic() {
+ if (x) {
+
+ }|
+ log.info("some text: {}", text);
+ return;
+ }
+}
+=-=-=
+
+Name: forward-sentence moves over method invocation
+
+=-=
+public class Basic {
+ public void basic() {
+ |log.info("some text: {}", text);
+ }
+}
+=-=
+public class Basic {
+ public void basic() {
+ log.info("some text: {}", text);|
+ }
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (forward-sentence 2))
+
+Name: forward-sentence moves over multiple statements
+
+=-=
+public class Basic {
+ public void basic() {
+ |return;
+ return;
+ }
+}
+=-=
+public class Basic {
+ public void basic() {
+ return;
+ return;|
+ }
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (backward-sentence 1))
+
+Name: backward-sentence moves over one statement
+
+=-=
+public class Basic {
+ public void basic() {
+ return;|
+ }
+}
+=-=
+public class Basic {
+ public void basic() {
+ |return;
+ }
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (beginning-of-defun))
+
+Name: beginning-of-defun moves to defun start
+
+=-=
+public class Basic {
+ public void basic() {
+ return;|
+ }
+}
+=-=
+public class Basic {
+| public void basic() {
+ return;
+ }
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (beginning-of-defun)
+ (beginning-of-defun))
+
+Name: beginning-of-defun moves to class
+
+=-=
+public class Basic {
+ public void basic() {
+ return;|
+ }
+}
+=-=
+|public class Basic {
+ public void basic() {
+ return;
+ }
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (java-ts-mode)
+ (end-of-defun))
+
+Name: end-of-defun moves to defun end
+
+=-=
+public class Basic {
+ public void basic() {
+ return;|
+ }
+}
+=-=
+public class Basic {
+ public void basic() {
+ return;
+ }
+|}
+=-=-=
diff --git a/test/lisp/progmodes/java-ts-mode-tests.el
b/test/lisp/progmodes/java-ts-mode-tests.el
new file mode 100644
index 0000000000..4fd8fc3019
--- /dev/null
+++ b/test/lisp/progmodes/java-ts-mode-tests.el
@@ -0,0 +1,35 @@
+;;; java-ts-mode-tests.el --- Tests for Tree-sitter-based Java mode -*-
lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'treesit)
+
+(ert-deftest java-ts-mode-test-indentation ()
+ (skip-unless (treesit-ready-p 'java))
+ (ert-test-erts-file (ert-resource-file "indent.erts")))
+
+(ert-deftest java-ts-mode-test-movement ()
+ (skip-unless (treesit-ready-p 'java))
+ (ert-test-erts-file (ert-resource-file "movement.erts")))
+
+(provide 'java-ts-mode-tests)
+;;; java-ts-mode-tests.el ends here
diff --git a/test/lisp/progmodes/ruby-ts-mode-tests.el
b/test/lisp/progmodes/ruby-ts-mode-tests.el
index b2c990f8e5..eaf6367a30 100644
--- a/test/lisp/progmodes/ruby-ts-mode-tests.el
+++ b/test/lisp/progmodes/ruby-ts-mode-tests.el
@@ -251,6 +251,7 @@ The whitespace before and including \"|\" on each line is
removed."
(kill-buffer buf)))))
(ruby-ts-deftest-indent "ruby-method-params-indent.rb")
+(ruby-ts-deftest-indent "ruby-block-indent.rb")
(provide 'ruby-ts-mode-tests)
diff --git a/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
b/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
new file mode 100644
index 0000000000..146ee76574
--- /dev/null
+++ b/test/lisp/progmodes/typescript-ts-mode-resources/indent.erts
@@ -0,0 +1,73 @@
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq typescript-ts-mode-indent-offset 2)
+ (typescript-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Point-Char: |
+
+Name: Basic indentation
+
+=-=
+const foo = () => {
+ console.log("bar");
+ if (x) {
+ return y;
+ } else if (y) {
+ return u;
+ }
+ return baz.x()
+ ? true
+ : false;
+}
+=-=-=
+
+Code:
+ (lambda ()
+ (setq indent-tabs-mode nil)
+ (setq tsx-ts-mode-indent-offset 2)
+ (tsx-ts-mode)
+ (indent-region (point-min) (point-max)))
+
+Name: JSX indentation
+
+=-=
+const foo = (props) => {
+ return (
+ <div>
+ <div>
+ <div>
+ <div>
+ {
+ props.foo
+ ? Hello, foo!
+ : Hello, World!;
+ }
+ </div>
+ </div>
+ </div>
+ </div>
+ );
+}
+=-=-=
+
+Name: JSX indentation with attributes
+
+=-=
+const foo = (props) => {
+ return (
+ <div
+ className={foo}
+ onClick={() => {
+ alert('???');
+ return () => {
+ return 5+5;
+ };
+ }}
+ >
+ <p>Some text</p>
+ </div>
+ );
+}
+=-=-=
diff --git a/test/lisp/progmodes/typescript-ts-mode-tests.el
b/test/lisp/progmodes/typescript-ts-mode-tests.el
new file mode 100644
index 0000000000..126f5e3298
--- /dev/null
+++ b/test/lisp/progmodes/typescript-ts-mode-tests.el
@@ -0,0 +1,31 @@
+;;; typescript-ts-mode-tests.el --- Tests for Tree-sitter-based TypeScript
mode -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+
+(require 'ert)
+(require 'ert-x)
+(require 'treesit)
+
+(ert-deftest typescript-ts-mode-test-indentation ()
+ (skip-unless (treesit-ready-p 'typescript))
+ (ert-test-erts-file (ert-resource-file "indent.erts")))
+
+(provide 'typescript-ts-mode-tests)
+;;; typescript-ts-mode-tests.el ends here