aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPo Lu2023-04-03 08:12:03 +0800
committerPo Lu2023-04-03 08:12:03 +0800
commit8bca62d552a3ca5dc262f916055d9d443d360af8 (patch)
treebce57bc68ebf8f3490d5fee6b986b245ae594649
parent1d84b4b28659b5f2cc60872ce095e3887bed6fdd (diff)
parentc108132d3bb69d0cc8d2e0222a781dff9abca087 (diff)
downloademacs-8bca62d552a3ca5dc262f916055d9d443d360af8.tar.gz
emacs-8bca62d552a3ca5dc262f916055d9d443d360af8.zip
Merge remote-tracking branch 'origin/master' into feature/android
-rw-r--r--CONTRIBUTE10
-rw-r--r--doc/emacs/display.texi2
-rw-r--r--doc/lispref/customize.texi9
-rw-r--r--doc/lispref/text.texi25
-rw-r--r--doc/misc/tramp.texi9
-rw-r--r--etc/EGLOT-NEWS48
-rw-r--r--etc/NEWS2
-rw-r--r--lisp/custom.el4
-rw-r--r--lisp/emacs-lisp/comp.el41
-rw-r--r--lisp/emacs-lisp/eldoc.el12
-rw-r--r--lisp/emacs-lisp/package-vc.el5
-rw-r--r--lisp/eshell/esh-cmd.el32
-rw-r--r--lisp/eshell/esh-proc.el11
-rw-r--r--lisp/eshell/eshell.el53
-rw-r--r--lisp/help.el4
-rw-r--r--lisp/loadup.el6
-rw-r--r--lisp/net/eww.el13
-rw-r--r--lisp/progmodes/eglot.el366
-rw-r--r--lisp/progmodes/typescript-ts-mode.el25
-rw-r--r--lisp/simple.el12
-rw-r--r--src/comp.c8
-rw-r--r--src/eval.c3
-rw-r--r--src/xdisp.c5
-rw-r--r--test/lisp/eshell/esh-proc-tests.el53
-rw-r--r--test/lisp/eshell/eshell-tests.el44
-rw-r--r--test/src/comp-tests.el18
-rw-r--r--test/src/eval-tests.el19
27 files changed, 542 insertions, 297 deletions
diff --git a/CONTRIBUTE b/CONTRIBUTE
index dcf34f48fe5..f56ba1df630 100644
--- a/CONTRIBUTE
+++ b/CONTRIBUTE
@@ -110,7 +110,7 @@ admin/notes/bug-triage.
110 110
111Any change that matters to end-users should have an entry in etc/NEWS. 111Any change that matters to end-users should have an entry in etc/NEWS.
112Try to start each NEWS entry with a sentence that summarizes the entry 112Try to start each NEWS entry with a sentence that summarizes the entry
113and takes just one line -- this will allow to read NEWS in Outline 113and takes just one line -- this will allow reading NEWS in Outline
114mode after hiding the body of each entry. 114mode after hiding the body of each entry.
115 115
116Doc-strings should be updated together with the code. 116Doc-strings should be updated together with the code.
@@ -123,7 +123,7 @@ Think about whether your change requires updating the manuals. If you
123know it does not, mark the NEWS entry with "---". If you know 123know it does not, mark the NEWS entry with "---". If you know
124that *all* the necessary documentation updates have been made as part 124that *all* the necessary documentation updates have been made as part
125of your changes or those by others, mark the entry with "+++". 125of your changes or those by others, mark the entry with "+++".
126Otherwise do not mark it. 126Otherwise, do not mark it.
127 127
128If your change requires updating the manuals to document new 128If your change requires updating the manuals to document new
129functions/commands/variables/faces, then use the proper Texinfo 129functions/commands/variables/faces, then use the proper Texinfo
@@ -400,7 +400,7 @@ the commit to master, by starting the commit message with "Backport:".
400The gitmerge function excludes these commits from the merge to the master. 400The gitmerge function excludes these commits from the merge to the master.
401 401
402Some changes should not be merged to master at all, for whatever 402Some changes should not be merged to master at all, for whatever
403reasons. These should be marked by including something like "Do not 403reason. These should be marked by including something like "Do not
404merge to master" or anything that matches gitmerge-skip-regexp (see 404merge to master" or anything that matches gitmerge-skip-regexp (see
405admin/gitmerge.el) in the commit message. 405admin/gitmerge.el) in the commit message.
406 406
@@ -449,8 +449,8 @@ files intended for use only with Emacs version 24.5 and later.
449 449
450*** Useful files in the admin/ directory 450*** Useful files in the admin/ directory
451 451
452See all the files in admin/notes/* . In particular, see 452See all the files in 'admin/notes/*'. In particular, see
453admin/notes/newfile, see admin/notes/repo. 453'admin/notes/newfile' and 'admin/notes/repo'.
454 454
455The file admin/MAINTAINERS records the areas of interest of frequent 455The file admin/MAINTAINERS records the areas of interest of frequent
456Emacs contributors. If you are making changes in one of the files 456Emacs contributors. If you are making changes in one of the files
diff --git a/doc/emacs/display.texi b/doc/emacs/display.texi
index 7ec843180b8..6b2eb014c82 100644
--- a/doc/emacs/display.texi
+++ b/doc/emacs/display.texi
@@ -154,7 +154,7 @@ the buffer will be momentarily unfontified.
154@vindex redisplay-skip-fontification-on-input 154@vindex redisplay-skip-fontification-on-input
155Finally, a third alternative to these variables is 155Finally, a third alternative to these variables is
156@code{redisplay-skip-fontification-on-input}. If this variable is 156@code{redisplay-skip-fontification-on-input}. If this variable is
157non-@code{nil}, skip some fontifications is there's input pending. 157non-@code{nil}, skip some fontifications if there's input pending.
158This usually does not affect the display because redisplay is 158This usually does not affect the display because redisplay is
159completely skipped anyway if input was pending, but it can make 159completely skipped anyway if input was pending, but it can make
160scrolling smoother by avoiding unnecessary fontification. 160scrolling smoother by avoiding unnecessary fontification.
diff --git a/doc/lispref/customize.texi b/doc/lispref/customize.texi
index 308145def55..6015c134d21 100644
--- a/doc/lispref/customize.texi
+++ b/doc/lispref/customize.texi
@@ -378,8 +378,15 @@ the option as a Lisp variable); preferably, though, it should not
378modify its value argument destructively. The default for 378modify its value argument destructively. The default for
379@var{setfunction} is @code{set-default-toplevel-value}. 379@var{setfunction} is @code{set-default-toplevel-value}.
380 380
381If defined, @var{setfunction} will also be called when evaluating a
382@code{defcustom} form with @kbd{C-M-x} in Emacs Lisp mode and when the
383@var{option}'s value is changed via the @code{setopt} macro
384(@pxref{Setting Variables, setopt}).
385
381If you specify this keyword, the variable's documentation string 386If you specify this keyword, the variable's documentation string
382should describe how to do the same job in hand-written Lisp code. 387should describe how to do the same job in hand-written Lisp code,
388either by invoking @var{setfunction} directly or by using
389@code{setopt}.
383 390
384@item :get @var{getfunction} 391@item :get @var{getfunction}
385@kindex get@r{, @code{defcustom} keyword} 392@kindex get@r{, @code{defcustom} keyword}
diff --git a/doc/lispref/text.texi b/doc/lispref/text.texi
index 0a48beab8b8..4c13185b0dd 100644
--- a/doc/lispref/text.texi
+++ b/doc/lispref/text.texi
@@ -3765,18 +3765,19 @@ Consecutive characters with the same @code{field} property constitute a
3765@item cursor 3765@item cursor
3766@kindex cursor @r{(text property)} 3766@kindex cursor @r{(text property)}
3767Normally, the cursor is displayed at the beginning or the end of any 3767Normally, the cursor is displayed at the beginning or the end of any
3768overlay and text property strings present at the current buffer 3768overlay and text property strings that ``hide'' (i.e., are displayed
3769position. You can instead tell Emacs to place the cursor on any 3769instead of) the current buffer position. You can instead tell Emacs
3770desired character of these strings by giving that character a 3770to place the cursor on any desired character of these strings by
3771non-@code{nil} @code{cursor} text property. In addition, if the value 3771giving that character a non-@code{nil} @code{cursor} text property.
3772of the @code{cursor} property is an integer, it specifies the number 3772In addition, if the value of the @code{cursor} property is an integer,
3773of buffer's character positions, starting with the position where the 3773it specifies the number of buffer's character positions, starting with
3774overlay or the @code{display} property begins, for which the cursor 3774the position where the overlay or the @code{display} property begins,
3775should be displayed on that character. Specifically, if the value of 3775for which the cursor should be displayed on that character.
3776the @code{cursor} property of a character is the number @var{n}, the 3776Specifically, if the value of the @code{cursor} property of a
3777cursor will be displayed on this character for any buffer position in 3777character is the number @var{n}, the cursor will be displayed on this
3778the range @code{[@var{ovpos}..@var{ovpos}+@var{n})}, where @var{ovpos} 3778character for any buffer position in the range
3779is the overlay's starting position given by @code{overlay-start} 3779@code{[@var{ovpos}..@var{ovpos}+@var{n})}, where @var{ovpos} is the
3780overlay's starting position given by @code{overlay-start}
3780(@pxref{Managing Overlays}), or the position where the @code{display} 3781(@pxref{Managing Overlays}), or the position where the @code{display}
3781text property begins in the buffer. 3782text property begins in the buffer.
3782 3783
diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi
index 46ef5146136..65892f8621e 100644
--- a/doc/misc/tramp.texi
+++ b/doc/misc/tramp.texi
@@ -2383,10 +2383,11 @@ This uses also the settings in @code{tramp-sh-extra-args}.
2383@vindex RemoteCommand@r{, ssh option} 2383@vindex RemoteCommand@r{, ssh option}
2384@strong{Note}: If you use an @option{ssh}-based method for connection, 2384@strong{Note}: If you use an @option{ssh}-based method for connection,
2385do @emph{not} set the @option{RemoteCommand} option in your 2385do @emph{not} set the @option{RemoteCommand} option in your
2386@command{ssh} configuration, for example to @command{screen}. On the 2386@command{ssh} configuration to something like @command{screen}. If
2387other hand, some @option{ssh}-based methods, like @option{sshx} or 2387used, @option{RemoteCommand} must open an interactive shell on the
2388@option{scpx}, silently overwrite a @option{RemoteCommand} option of 2388remote host. On the other hand, some @option{ssh}-based methods, like
2389the configuration file. 2389@option{sshx} or @option{scpx}, silently overwrite a
2390@option{RemoteCommand} option of the configuration file.
2390 2391
2391 2392
2392@subsection Other remote shell setup hints 2393@subsection Other remote shell setup hints
diff --git a/etc/EGLOT-NEWS b/etc/EGLOT-NEWS
index dd04e677285..2872cdd05cf 100644
--- a/etc/EGLOT-NEWS
+++ b/etc/EGLOT-NEWS
@@ -18,6 +18,54 @@ to look up issue github#1234, go to
18https://github.com/joaotavora/eglot/issues/1234. 18https://github.com/joaotavora/eglot/issues/1234.
19 19
20 20
21* Changes in upcoming Eglot 1.14
22
23** Faster, more responsive completion
24
25Eglot takes advantage of LSP's "isIncomplete" flag in responses to
26completion requests to drive new completion-caching mechanism for the
27duration of each completion session. Once a full set of completions
28is obtained for a given position, the server needn't be contacted in
29many scenarios, resulting in significantly less communication
30overhead. This works with the popular Company package and stock
31completion-at-point interfaces.
32
33A variable 'eglot-cache-session-completions', t by default, controls
34this. The mechanism was tested with ccls, jdtls, pylsp, golsp and
35clangd. Notably, the C/C++ language server Clangd version 15 has a
36bug in its "isIcomplete" flag (it is fixed in later versions). If you
37run into problems, disable this mechanism like so:
38
39(add-hook 'c-common-mode-hook
40 (lambda () (setq-local eglot-cache-session-completions nil)))
41
42** At-point documentation less obtrusive in echo area
43
44Eglot takes advantage of new features of ElDoc to separate short
45documentation strings from large ones, sending the former to be shown in
46the ElDoc's echo area and the latter to be shown in other outlets,
47such as the *eldoc* buffer obtainable with 'C-h .'.
48
49** New variable 'eglot-prefer-plaintext'
50
51Customize this to t to opt-in to docstrings in plain text instead of
52Markdown.
53
54(bug#61373)
55
56** Progress indicators inhabit the mode-line by default
57
58To switch to the echo area, customize 'eglot-report-progress' to
59'messages'. To switch off progress reporting completely, set to nil.
60
61** Snippet support is easier to enable
62
63The user needn't manually activate 'yas-minor-mode' or
64'yas-global-mode'. If YASnippet is installed and the server supports
65snippets, it is used automatically, unless the symbol 'yasnippet' has
66been added to 'eglot-stay-out-of'.
67
68
21* Changes in Eglot 1.13 (15/03/2023) 69* Changes in Eglot 1.13 (15/03/2023)
22 70
23** ELPA installations on Emacs 26.3 are supported again. 71** ELPA installations on Emacs 26.3 are supported again.
diff --git a/etc/NEWS b/etc/NEWS
index a63a2f837f5..74ad886db07 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -356,6 +356,8 @@ The new functions 'touch-screen-track-tap' and
356'touch-screen-track-drag' handle tracking common touch screen gestures 356'touch-screen-track-drag' handle tracking common touch screen gestures
357from within a command. 357from within a command.
358 358
359** New var 'inhibit-auto-fill' to temporarily prevent auto-fill.
360
359** Functions and variables to transpose sexps 361** Functions and variables to transpose sexps
360 362
361+++ 363+++
diff --git a/lisp/custom.el b/lisp/custom.el
index fa77e5c2c56..083349e3591 100644
--- a/lisp/custom.el
+++ b/lisp/custom.el
@@ -280,7 +280,9 @@ The following keywords are meaningful:
280 when using the Customize user interface. It takes two arguments, 280 when using the Customize user interface. It takes two arguments,
281 the symbol to set and the value to give it. The function should 281 the symbol to set and the value to give it. The function should
282 not modify its value argument destructively. The default choice 282 not modify its value argument destructively. The default choice
283 of function is `set-default-toplevel-value'. 283 of function is `set-default-toplevel-value'. If this keyword is
284 defined, modifying the value of SYMBOL via `setopt' will call the
285 function specified by VALUE to install the new value.
284:get VALUE should be a function to extract the value of symbol. 286:get VALUE should be a function to extract the value of symbol.
285 The function takes one argument, a symbol, and should return 287 The function takes one argument, a symbol, and should return
286 the current value for that symbol. The default choice of function 288 the current value for that symbol. The default choice of function
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index a5ed5df117d..841b0ebf29d 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -1764,27 +1764,32 @@ Return value is the fall-through block name."
1764 (_ (signal 'native-ice 1764 (_ (signal 'native-ice
1765 '("missing previous setimm while creating a switch"))))) 1765 '("missing previous setimm while creating a switch")))))
1766 1766
1767(defun comp--func-arity (subr-name)
1768 "Like `func-arity' but invariant against primitive redefinitions.
1769SUBR-NAME is the name of function."
1770 (or (gethash subr-name comp-subr-arities-h)
1771 (func-arity subr-name)))
1772
1767(defun comp-emit-set-call-subr (subr-name sp-delta) 1773(defun comp-emit-set-call-subr (subr-name sp-delta)
1768 "Emit a call for SUBR-NAME. 1774 "Emit a call for SUBR-NAME.
1769SP-DELTA is the stack adjustment." 1775SP-DELTA is the stack adjustment."
1770 (let ((subr (symbol-function subr-name)) 1776 (let* ((nargs (1+ (- sp-delta)))
1771 (nargs (1+ (- sp-delta)))) 1777 (arity (comp--func-arity subr-name))
1772 (let* ((arity (func-arity subr)) 1778 (minarg (car arity))
1773 (minarg (car arity)) 1779 (maxarg (cdr arity)))
1774 (maxarg (cdr arity))) 1780 (when (eq maxarg 'unevalled)
1775 (when (eq maxarg 'unevalled) 1781 (signal 'native-ice (list "subr contains unevalled args" subr-name)))
1776 (signal 'native-ice (list "subr contains unevalled args" subr-name))) 1782 (if (eq maxarg 'many)
1777 (if (eq maxarg 'many) 1783 ;; callref case.
1778 ;; callref case. 1784 (comp-emit-set-call (comp-callref subr-name nargs (comp-sp)))
1779 (comp-emit-set-call (comp-callref subr-name nargs (comp-sp))) 1785 ;; Normal call.
1780 ;; Normal call. 1786 (unless (and (>= maxarg nargs) (<= minarg nargs))
1781 (unless (and (>= maxarg nargs) (<= minarg nargs)) 1787 (signal 'native-ice
1782 (signal 'native-ice 1788 (list "incoherent stack adjustment" nargs maxarg minarg)))
1783 (list "incoherent stack adjustment" nargs maxarg minarg))) 1789 (let* ((subr-name subr-name)
1784 (let* ((subr-name subr-name) 1790 (slots (cl-loop for i from 0 below maxarg
1785 (slots (cl-loop for i from 0 below maxarg 1791 collect (comp-slot-n (+ i (comp-sp))))))
1786 collect (comp-slot-n (+ i (comp-sp)))))) 1792 (comp-emit-set-call (apply #'comp-call (cons subr-name slots)))))))
1787 (comp-emit-set-call (apply #'comp-call (cons subr-name slots))))))))
1788 1793
1789(eval-when-compile 1794(eval-when-compile
1790 (defun comp-op-to-fun (x) 1795 (defun comp-op-to-fun (x)
diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el
index ef4cda4650f..1eb0d38c5ce 100644
--- a/lisp/emacs-lisp/eldoc.el
+++ b/lisp/emacs-lisp/eldoc.el
@@ -5,7 +5,7 @@
5;; Author: Noah Friedman <friedman@splode.com> 5;; Author: Noah Friedman <friedman@splode.com>
6;; Keywords: extensions 6;; Keywords: extensions
7;; Created: 1995-10-06 7;; Created: 1995-10-06
8;; Version: 1.13.0 8;; Version: 1.14.0
9;; Package-Requires: ((emacs "26.3")) 9;; Package-Requires: ((emacs "26.3"))
10 10
11;; This is a GNU ELPA :core package. Avoid functionality that is not 11;; This is a GNU ELPA :core package. Avoid functionality that is not
@@ -448,17 +448,17 @@ documentation-displaying frontends. For example, KEY can be:
448 `eldoc-display-in-echo-area' and `eldoc-display-in-buffer' will 448 `eldoc-display-in-echo-area' and `eldoc-display-in-buffer' will
449 use when displaying `:thing''s value. 449 use when displaying `:thing''s value.
450 450
451* `:origin', VALUE being the member of
452 `eldoc-documentation-functions' where DOCSTRING
453 originated. `eldoc-display-in-buffer' may use this organize the
454 documentation buffer accordingly.
455
456* `:echo', controlling how `eldoc-display-in-echo-area' should 451* `:echo', controlling how `eldoc-display-in-echo-area' should
457 present this documentation item in the echo area, to save 452 present this documentation item in the echo area, to save
458 space. If VALUE is a string, echo it instead of DOCSTRING. If 453 space. If VALUE is a string, echo it instead of DOCSTRING. If
459 a number, only echo DOCSTRING up to that character position. 454 a number, only echo DOCSTRING up to that character position.
460 If `skip', don't echo DOCSTRING at all. 455 If `skip', don't echo DOCSTRING at all.
461 456
457The additional KEY `:origin' is always added by ElDoc, its VALUE
458being the member of `eldoc-documentation-functions' where
459DOCSTRING originated. `eldoc-display-functions' may use this
460information to organize display of multiple docstrings.
461
462Finally, major modes should modify this hook locally, for 462Finally, major modes should modify this hook locally, for
463example: 463example:
464 (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t) 464 (add-hook \\='eldoc-documentation-functions #\\='foo-mode-eldoc nil t)
diff --git a/lisp/emacs-lisp/package-vc.el b/lisp/emacs-lisp/package-vc.el
index ba3a75851ca..ddc7ec4679b 100644
--- a/lisp/emacs-lisp/package-vc.el
+++ b/lisp/emacs-lisp/package-vc.el
@@ -41,9 +41,6 @@
41 41
42;; - Allow maintaining patches that are ported back onto regular 42;; - Allow maintaining patches that are ported back onto regular
43;; packages and maintained between versions. 43;; packages and maintained between versions.
44;;
45;; - Add a heuristic for guessing a `:lisp-dir' when cloning directly
46;; from a URL.
47 44
48;;; Code: 45;;; Code:
49 46
@@ -58,7 +55,7 @@
58(defgroup package-vc nil 55(defgroup package-vc nil
59 "Manage packages from VC checkouts." 56 "Manage packages from VC checkouts."
60 :group 'package 57 :group 'package
61 :link '(custom-manual "(emacs) Package from Source") 58 :link '(custom-manual "(emacs) Fetching Package Sources")
62 :prefix "package-vc-" 59 :prefix "package-vc-"
63 :version "29.1") 60 :version "29.1")
64 61
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index f0c6a146dfd..94aa2ed8906 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -421,7 +421,8 @@ hooks should be run before and after the command."
421 (string= (car eshell--sep-terms) ";")) 421 (string= (car eshell--sep-terms) ";"))
422 (eshell-parse-pipeline cmd) 422 (eshell-parse-pipeline cmd)
423 `(eshell-do-subjob 423 `(eshell-do-subjob
424 (list ,(eshell-parse-pipeline cmd))))) 424 (cons :eshell-background
425 ,(eshell-parse-pipeline cmd)))))
425 (setq eshell--sep-terms (cdr eshell--sep-terms)) 426 (setq eshell--sep-terms (cdr eshell--sep-terms))
426 (if eshell-in-pipeline-p 427 (if eshell-in-pipeline-p
427 cmd 428 cmd
@@ -893,7 +894,7 @@ This is used on systems where async subprocesses are not supported."
893 (set headproc nil) 894 (set headproc nil)
894 (set tailproc nil) 895 (set tailproc nil)
895 (progn 896 (progn
896 ,(if (fboundp 'make-process) 897 ,(if eshell-supports-asynchronous-processes
897 `(eshell-do-pipelines ,pipeline) 898 `(eshell-do-pipelines ,pipeline)
898 `(let ((tail-handles (eshell-duplicate-handles 899 `(let ((tail-handles (eshell-duplicate-handles
899 eshell-current-handles))) 900 eshell-current-handles)))
@@ -1036,7 +1037,12 @@ produced by `eshell-parse-command'."
1036 (cadr result))) 1037 (cadr result)))
1037 1038
1038(defun eshell-eval-command (command &optional input) 1039(defun eshell-eval-command (command &optional input)
1039 "Evaluate the given COMMAND iteratively." 1040 "Evaluate the given COMMAND iteratively.
1041Return the process (or head and tail processes) created by
1042COMMAND, if any. If COMMAND is a background command, return the
1043process(es) in a cons cell like:
1044
1045 (:eshell-background . PROCESS)"
1040 (if eshell-current-command 1046 (if eshell-current-command
1041 ;; We can just stick the new command at the end of the current 1047 ;; We can just stick the new command at the end of the current
1042 ;; one, and everything will happen as it should. 1048 ;; one, and everything will happen as it should.
@@ -1052,20 +1058,12 @@ produced by `eshell-parse-command'."
1052 (erase-buffer) 1058 (erase-buffer)
1053 (insert "command: \"" input "\"\n"))) 1059 (insert "command: \"" input "\"\n")))
1054 (setq eshell-current-command command) 1060 (setq eshell-current-command command)
1055 (let* ((delim (catch 'eshell-incomplete 1061 (let* (result
1056 (eshell-resume-eval))) 1062 (delim (catch 'eshell-incomplete
1057 (val (car-safe delim))) 1063 (ignore (setq result (eshell-resume-eval))))))
1058 ;; If the return value of `eshell-resume-eval' is wrapped in a 1064 (when delim
1059 ;; list, it indicates that the command was run asynchronously. 1065 (error "Unmatched delimiter: %S" delim))
1060 ;; In that case, unwrap the value before checking the delimiter 1066 result)))
1061 ;; value.
1062 (if (and val
1063 (not (eshell-processp val))
1064 (not (eq val t)))
1065 (error "Unmatched delimiter: %S" val)
1066 ;; Eshell-command expect a list like (<process>) to know if the
1067 ;; command should be async or not.
1068 (or (and (eshell-processp val) delim) val)))))
1069 1067
1070(defun eshell-resume-command (proc status) 1068(defun eshell-resume-command (proc status)
1071 "Resume the current command when a process ends." 1069 "Resume the current command when a process ends."
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index a86e7502795..00e0c8014e1 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -97,6 +97,9 @@ information, for example."
97 97
98;;; Internal Variables: 98;;; Internal Variables:
99 99
100(defvar eshell-supports-asynchronous-processes (fboundp 'make-process)
101 "Non-nil if Eshell can create asynchronous processes.")
102
100(defvar eshell-current-subjob-p nil) 103(defvar eshell-current-subjob-p nil)
101 104
102(defvar eshell-process-list nil 105(defvar eshell-process-list nil
@@ -296,7 +299,7 @@ Used only on systems which do not support async subprocesses.")
296 (coding-system-change-eol-conversion locale-coding-system 299 (coding-system-change-eol-conversion locale-coding-system
297 'unix)))) 300 'unix))))
298 (cond 301 (cond
299 ((fboundp 'make-process) 302 (eshell-supports-asynchronous-processes
300 (unless (or ;; FIXME: It's not currently possible to use a 303 (unless (or ;; FIXME: It's not currently possible to use a
301 ;; stderr process for remote files. 304 ;; stderr process for remote files.
302 (file-remote-p default-directory) 305 (file-remote-p default-directory)
@@ -367,6 +370,8 @@ Used only on systems which do not support async subprocesses.")
367 (erase-buffer) 370 (erase-buffer)
368 (set-buffer oldbuf) 371 (set-buffer oldbuf)
369 (run-hook-with-args 'eshell-exec-hook command) 372 (run-hook-with-args 'eshell-exec-hook command)
373 ;; XXX: This doesn't support sending stdout and stderr to
374 ;; separate places.
370 (setq exit-status 375 (setq exit-status
371 (apply #'call-process-region 376 (apply #'call-process-region
372 (append (list eshell-last-sync-output-start (point) 377 (append (list eshell-last-sync-output-start (point)
@@ -392,10 +397,6 @@ Used only on systems which do not support async subprocesses.")
392 (setq lbeg lend) 397 (setq lbeg lend)
393 (set-buffer proc-buf)) 398 (set-buffer proc-buf))
394 (set-buffer oldbuf)) 399 (set-buffer oldbuf))
395 (require 'esh-mode)
396 (declare-function eshell-update-markers "esh-mode" (pmark))
397 (defvar eshell-last-output-end) ;Defined in esh-mode.el.
398 (eshell-update-markers eshell-last-output-end)
399 ;; Simulate the effect of eshell-sentinel. 400 ;; Simulate the effect of eshell-sentinel.
400 (eshell-close-handles 401 (eshell-close-handles
401 (if (numberp exit-status) exit-status -1) 402 (if (numberp exit-status) exit-status -1)
diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el
index 7d2c0335db2..15fc2ae6310 100644
--- a/lisp/eshell/eshell.el
+++ b/lisp/eshell/eshell.el
@@ -272,43 +272,38 @@ information on Eshell, see Info node `(eshell)Top'."
272 272
273(declare-function eshell-add-input-to-history "em-hist" (input)) 273(declare-function eshell-add-input-to-history "em-hist" (input))
274 274
275;;;###autoload 275(defun eshell-read-command (&optional prompt)
276(defun eshell-command (&optional command arg) 276 "Read an Eshell command from the minibuffer, prompting with PROMPT."
277 "Execute the Eshell command string COMMAND. 277 (let ((prompt (or prompt "Emacs shell command: "))
278With prefix ARG, insert output into the current buffer at point." 278 (eshell-non-interactive-p t))
279 (interactive)
280 (unless arg
281 (setq arg current-prefix-arg))
282 (let ((eshell-non-interactive-p t))
283 ;; Enable `eshell-mode' only in this minibuffer. 279 ;; Enable `eshell-mode' only in this minibuffer.
284 (minibuffer-with-setup-hook (lambda () 280 (minibuffer-with-setup-hook (lambda ()
285 (eshell-mode) 281 (eshell-mode)
286 (eshell-command-mode +1)) 282 (eshell-command-mode +1))
287 (unless command 283 (let ((command (read-from-minibuffer prompt)))
288 (setq command (read-from-minibuffer "Emacs shell command: ")) 284 (when (eshell-using-module 'eshell-hist)
289 (if (eshell-using-module 'eshell-hist) 285 (eshell-add-input-to-history command))
290 (eshell-add-input-to-history command))))) 286 command))))
291 (unless command 287
292 (error "No command specified!")) 288;;;###autoload
293 ;; redirection into the current buffer is achieved by adding an 289(defun eshell-command (command &optional to-current-buffer)
294 ;; output redirection to the end of the command, of the form 290 "Execute the Eshell command string COMMAND.
295 ;; 'COMMAND >>> #<buffer BUFFER>'. This will not interfere with 291If TO-CURRENT-BUFFER is non-nil (interactively, with the prefix
296 ;; other redirections, since multiple redirections merely cause the 292argument), then insert output into the current buffer at point."
297 ;; output to be copied to multiple target locations 293 (interactive (list (eshell-read-command)
298 (if arg 294 current-prefix-arg))
299 (setq command
300 (concat command
301 (format " >>> #<buffer %s>"
302 (buffer-name (current-buffer))))))
303 (save-excursion 295 (save-excursion
304 (let ((buf (set-buffer (generate-new-buffer " *eshell cmd*"))) 296 (let ((stdout (if to-current-buffer (current-buffer) t))
297 (buf (set-buffer (generate-new-buffer " *eshell cmd*")))
305 (eshell-non-interactive-p t)) 298 (eshell-non-interactive-p t))
306 (eshell-mode) 299 (eshell-mode)
307 (let* ((proc (eshell-eval-command 300 (let* ((proc (eshell-eval-command
308 (list 'eshell-commands 301 `(let ((eshell-current-handles
309 (eshell-parse-command command)))) 302 (eshell-create-handles ,stdout 'insert))
303 (eshell-current-subjob-p))
304 ,(eshell-parse-command command))))
310 intr 305 intr
311 (bufname (if (and proc (listp proc)) 306 (bufname (if (eq (car-safe proc) :eshell-background)
312 "*Eshell Async Command Output*" 307 "*Eshell Async Command Output*"
313 (setq intr t) 308 (setq intr t)
314 "*Eshell Command Output*"))) 309 "*Eshell Command Output*")))
@@ -326,7 +321,7 @@ With prefix ARG, insert output into the current buffer at point."
326 (while (and (bolp) (not (bobp))) 321 (while (and (bolp) (not (bobp)))
327 (delete-char -1))) 322 (delete-char -1)))
328 (cl-assert (and buf (buffer-live-p buf))) 323 (cl-assert (and buf (buffer-live-p buf)))
329 (unless arg 324 (unless to-current-buffer
330 (let ((len (if (not intr) 2 325 (let ((len (if (not intr) 2
331 (count-lines (point-min) (point-max))))) 326 (count-lines (point-min) (point-max)))))
332 (cond 327 (cond
diff --git a/lisp/help.el b/lisp/help.el
index 3e94b5046e5..6eac037df2c 100644
--- a/lisp/help.el
+++ b/lisp/help.el
@@ -689,6 +689,10 @@ To record all your input, use `open-dribble-file'."
689 (with-current-buffer standard-output 689 (with-current-buffer standard-output
690 (goto-char (point-min)) 690 (goto-char (point-min))
691 (let ((comment-start ";; ") 691 (let ((comment-start ";; ")
692 ;; Prevent 'comment-indent' from handling a single
693 ;; semicolon as the beginning of a comment.
694 (comment-start-skip ";; ")
695 (comment-use-syntax nil)
692 (comment-column 24)) 696 (comment-column 24))
693 (while (not (eobp)) 697 (while (not (eobp))
694 (comment-indent) 698 (comment-indent)
diff --git a/lisp/loadup.el b/lisp/loadup.el
index 15267cca3be..0a28c0592d0 100644
--- a/lisp/loadup.el
+++ b/lisp/loadup.el
@@ -496,7 +496,13 @@ lost after dumping")))
496;; At this point, we're ready to resume undo recording for scratch. 496;; At this point, we're ready to resume undo recording for scratch.
497(buffer-enable-undo "*scratch*") 497(buffer-enable-undo "*scratch*")
498 498
499(defvar comp-subr-arities-h)
499(when (featurep 'native-compile) 500(when (featurep 'native-compile)
501 ;; Save the arity for all primitives so the compiler can always
502 ;; retrive it even in case of redefinition.
503 (mapatoms (lambda (f)
504 (when (subr-primitive-p (symbol-function f))
505 (puthash f (func-arity f) comp-subr-arities-h))))
500 ;; Fix the compilation unit filename to have it working when 506 ;; Fix the compilation unit filename to have it working when
501 ;; installed or if the source directory got moved. This is set to be 507 ;; installed or if the source directory got moved. This is set to be
502 ;; a pair in the form of: 508 ;; a pair in the form of:
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 3c7140ef5cc..a66332904de 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -64,22 +64,23 @@ The action to be taken can be further customized via
64 :version "28.1" 64 :version "28.1"
65 :type 'regexp) 65 :type 'regexp)
66 66
67(defcustom eww-download-directory "~/Downloads/" 67(defcustom eww-default-download-directory "~/Downloads/"
68 "Default directory where `eww' saves downloaded files." 68 "Default directory where `eww' saves downloaded files.
69Used by `eww--download-directory', which see."
69 :version "29.1" 70 :version "29.1"
70 :group 'eww 71 :group 'eww
71 :type 'directory) 72 :type 'directory)
72 73
73(defun eww--download-directory () 74(defun eww--download-directory ()
74 "Return the name of the EWW download directory. 75 "Return the name of the EWW download directory.
75The default is specified by `eww-download-directory'; however, 76The default is specified by `eww-default-download-directory'; however,
76if that directory doesn't exist and the DOWNLOAD XDG user directory 77if that directory doesn't exist and the DOWNLOAD XDG user directory
77is defined, use the latter instead." 78is defined, use the latter instead."
78 (or (and (file-exists-p eww-download-directory) 79 (or (and (file-exists-p eww-default-download-directory)
79 eww-download-directory) 80 eww-default-download-directory)
80 (when-let ((dir (xdg-user-dir "DOWNLOAD"))) 81 (when-let ((dir (xdg-user-dir "DOWNLOAD")))
81 (file-name-as-directory dir)) 82 (file-name-as-directory dir))
82 eww-download-directory)) 83 eww-default-download-directory))
83 84
84(defcustom eww-download-directory 'eww--download-directory 85(defcustom eww-download-directory 'eww--download-directory
85 "Directory where files will downloaded. 86 "Directory where files will downloaded.
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 3072095aeb2..93af5f2123b 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -97,34 +97,29 @@
97 97
98(require 'imenu) 98(require 'imenu)
99(require 'cl-lib) 99(require 'cl-lib)
100(require 'project) 100
101(require 'url-parse) 101(require 'url-parse)
102(require 'url-util) 102(require 'url-util)
103(require 'pcase) 103(require 'pcase)
104(require 'compile) ; for some faces 104(require 'compile) ; for some faces
105(require 'warnings) 105(require 'warnings)
106(require 'flymake)
107(require 'xref)
108(eval-when-compile 106(eval-when-compile
109 (require 'subr-x)) 107 (require 'subr-x))
110(require 'jsonrpc)
111(require 'filenotify) 108(require 'filenotify)
112(require 'ert) 109(require 'ert)
113(require 'array) 110
114(require 'external-completion) 111;; These dependencies are also GNU ELPA core packages. Because of
115 112;; bug#62576, since there is a risk that M-x package-install, despite
116;; ElDoc is preloaded in Emacs, so `require'-ing won't guarantee we are 113;; having installed them, didn't correctly re-load them over the
117;; using the latest version from GNU Elpa when we load eglot.el. Use an 114;; built-in versions.
118;; heuristic to see if we need to `load' it in Emacs < 28. 115(eval-and-compile
119(if (and (< emacs-major-version 28) 116 (load "project")
120 (not (boundp 'eldoc-documentation-strategy))) 117 (load "eldoc")
121 (load "eldoc") 118 (load "seq")
122 (require 'eldoc)) 119 (load "flymake")
123 120 (load "xref")
124;; Similar issue as above for Emacs 26.3 and seq.el. 121 (load "jsonrpc")
125(if (< emacs-major-version 27) 122 (load "external-completion"))
126 (load "seq")
127 (require 'seq))
128 123
129;; forward-declare, but don't require (Emacs 28 doesn't seem to care) 124;; forward-declare, but don't require (Emacs 28 doesn't seem to care)
130(defvar markdown-fontify-code-blocks-natively) 125(defvar markdown-fontify-code-blocks-natively)
@@ -452,6 +447,10 @@ This can be useful when using docker to run a language server.")
452 (if (>= emacs-major-version 27) (executable-find command remote) 447 (if (>= emacs-major-version 27) (executable-find command remote)
453 (executable-find command))) 448 (executable-find command)))
454 449
450(defun eglot--accepted-formats ()
451 (if (and (not eglot-prefer-plaintext) (fboundp 'gfm-view-mode))
452 ["markdown" "plaintext"] ["plaintext"]))
453
455 454
456;;; Message verification helpers 455;;; Message verification helpers
457;;; 456;;;
@@ -782,15 +781,12 @@ treated as in `eglot--dbind'."
782 :tagSupport (:valueSet [1])) 781 :tagSupport (:valueSet [1]))
783 :contextSupport t) 782 :contextSupport t)
784 :hover (list :dynamicRegistration :json-false 783 :hover (list :dynamicRegistration :json-false
785 :contentFormat 784 :contentFormat (eglot--accepted-formats))
786 (if (and (not eglot-prefer-plaintext)
787 (fboundp 'gfm-view-mode))
788 ["markdown" "plaintext"]
789 ["plaintext"]))
790 :signatureHelp (list :dynamicRegistration :json-false 785 :signatureHelp (list :dynamicRegistration :json-false
791 :signatureInformation 786 :signatureInformation
792 `(:parameterInformation 787 `(:parameterInformation
793 (:labelOffsetSupport t) 788 (:labelOffsetSupport t)
789 :documentationFormat ,(eglot--accepted-formats)
794 :activeParameterSupport t)) 790 :activeParameterSupport t))
795 :references `(:dynamicRegistration :json-false) 791 :references `(:dynamicRegistration :json-false)
796 :definition (list :dynamicRegistration :json-false 792 :definition (list :dynamicRegistration :json-false
@@ -916,7 +912,7 @@ SERVER."
916 (unwind-protect 912 (unwind-protect
917 (progn 913 (progn
918 (setf (eglot--shutdown-requested server) t) 914 (setf (eglot--shutdown-requested server) t)
919 (jsonrpc-request server :shutdown nil :timeout (or timeout 1.5)) 915 (eglot--request server :shutdown nil :timeout (or timeout 1.5))
920 (jsonrpc-notify server :exit nil)) 916 (jsonrpc-notify server :exit nil))
921 ;; Now ask jsonrpc.el to shut down the server. 917 ;; Now ask jsonrpc.el to shut down the server.
922 (jsonrpc-shutdown server (not preserve-buffers)) 918 (jsonrpc-shutdown server (not preserve-buffers))
@@ -1469,6 +1465,18 @@ CONNECT-ARGS are passed as additional arguments to
1469 (line-beginning-position n)))) 1465 (line-beginning-position n))))
1470 "Return position of first character in current line.") 1466 "Return position of first character in current line.")
1471 1467
1468(cl-defun eglot--request (server method params &key
1469 immediate
1470 timeout cancel-on-input
1471 cancel-on-input-retval)
1472 "Like `jsonrpc-request', but for Eglot LSP requests.
1473Unless IMMEDIATE, send pending changes before making request."
1474 (unless immediate (eglot--signal-textDocument/didChange))
1475 (jsonrpc-request server method params
1476 :timeout timeout
1477 :cancel-on-input cancel-on-input
1478 :cancel-on-input-retval cancel-on-input-retval))
1479
1472 1480
1473;;; Encoding fever 1481;;; Encoding fever
1474;;; 1482;;;
@@ -1633,10 +1641,9 @@ If optional MARKER, return a marker instead"
1633 (normalized (if (and (not remote-prefix) 1641 (normalized (if (and (not remote-prefix)
1634 (eq system-type 'windows-nt) 1642 (eq system-type 'windows-nt)
1635 (cl-plusp (length retval))) 1643 (cl-plusp (length retval)))
1636 (substring retval 1) 1644 (w32-long-file-name (substring retval 1))
1637 retval))) 1645 retval)))
1638 (concat remote-prefix normalized)) 1646 (concat remote-prefix normalized))
1639
1640 uri))) 1647 uri)))
1641 1648
1642(defun eglot--snippet-expansion-fn () 1649(defun eglot--snippet-expansion-fn ()
@@ -1767,9 +1774,9 @@ and just return it. PROMPT shouldn't end with a question mark."
1767(defun eglot--plist-keys (plist) "Get keys of a plist." 1774(defun eglot--plist-keys (plist) "Get keys of a plist."
1768 (cl-loop for (k _v) on plist by #'cddr collect k)) 1775 (cl-loop for (k _v) on plist by #'cddr collect k))
1769 1776
1770(defun eglot--ensure-list (x) (if (listp x) x (list x))) 1777(defalias 'eglot--ensure-list
1771(when (fboundp 'ensure-list) ; Emacs 28 or later 1778 (if (fboundp 'ensure-list) #'ensure-list
1772 (define-obsolete-function-alias 'eglot--ensure-list #'ensure-list "29.1")) 1779 (lambda (x) (if (listp x) x (list x)))))
1773 1780
1774 1781
1775;;; Minor modes 1782;;; Minor modes
@@ -1850,6 +1857,8 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
1850 (unless (eglot--stay-out-of-p 'xref) 1857 (unless (eglot--stay-out-of-p 'xref)
1851 (add-hook 'xref-backend-functions 'eglot-xref-backend nil t)) 1858 (add-hook 'xref-backend-functions 'eglot-xref-backend nil t))
1852 (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t) 1859 (add-hook 'completion-at-point-functions #'eglot-completion-at-point nil t)
1860 (add-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush nil t)
1861 (add-hook 'company-after-completion-hook #'eglot--capf-session-flush nil t)
1853 (add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t) 1862 (add-hook 'change-major-mode-hook #'eglot--managed-mode-off nil t)
1854 (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t) 1863 (add-hook 'post-self-insert-hook 'eglot--post-self-insert-hook nil t)
1855 (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t) 1864 (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t)
@@ -1881,6 +1890,8 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
1881 (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t) 1890 (remove-hook 'after-save-hook 'eglot--signal-textDocument/didSave t)
1882 (remove-hook 'xref-backend-functions 'eglot-xref-backend t) 1891 (remove-hook 'xref-backend-functions 'eglot-xref-backend t)
1883 (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t) 1892 (remove-hook 'completion-at-point-functions #'eglot-completion-at-point t)
1893 (remove-hook 'completion-in-region-mode-hook #'eglot--capf-session-flush t)
1894 (remove-hook 'company-after-completion-hook #'eglot--capf-session-flush t)
1884 (remove-hook 'change-major-mode-hook #'eglot--managed-mode-off t) 1895 (remove-hook 'change-major-mode-hook #'eglot--managed-mode-off t)
1885 (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t) 1896 (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t)
1886 (remove-hook 'pre-command-hook 'eglot--pre-command-hook t) 1897 (remove-hook 'pre-command-hook 'eglot--pre-command-hook t)
@@ -1904,6 +1915,7 @@ Use `eglot-managed-p' to determine if current buffer is managed.")
1904(defun eglot--managed-mode-off () 1915(defun eglot--managed-mode-off ()
1905 "Turn off `eglot--managed-mode' unconditionally." 1916 "Turn off `eglot--managed-mode' unconditionally."
1906 (remove-overlays nil nil 'eglot--overlay t) 1917 (remove-overlays nil nil 'eglot--overlay t)
1918 (eglot-inlay-hints-mode -1)
1907 (eglot--managed-mode -1)) 1919 (eglot--managed-mode -1))
1908 1920
1909(defun eglot-current-server () 1921(defun eglot-current-server ()
@@ -2148,8 +2160,8 @@ still unanswered LSP requests to the server\n")))
2148 (server command arguments) 2160 (server command arguments)
2149 "Execute COMMAND on SERVER with `:workspace/executeCommand'. 2161 "Execute COMMAND on SERVER with `:workspace/executeCommand'.
2150COMMAND is a symbol naming the command." 2162COMMAND is a symbol naming the command."
2151 (jsonrpc-request server :workspace/executeCommand 2163 (eglot--request server :workspace/executeCommand
2152 `(:command ,(format "%s" command) :arguments ,arguments))) 2164 `(:command ,(format "%s" command) :arguments ,arguments)))
2153 2165
2154(cl-defmethod eglot-handle-notification 2166(cl-defmethod eglot-handle-notification
2155 (_server (_method (eql window/showMessage)) &key type message) 2167 (_server (_method (eql window/showMessage)) &key type message)
@@ -2453,16 +2465,6 @@ Records BEG, END and PRE-CHANGE-LENGTH locally."
2453 (run-hooks 'eglot--document-changed-hook) 2465 (run-hooks 'eglot--document-changed-hook)
2454 (setq eglot--change-idle-timer nil)))))))) 2466 (setq eglot--change-idle-timer nil))))))))
2455 2467
2456;; HACK! Launching a deferred sync request with outstanding changes is a
2457;; bad idea, since that might lead to the request never having a
2458;; chance to run, because `jsonrpc-connection-ready-p'.
2459(advice-add #'jsonrpc-request :before
2460 (cl-function (lambda (_proc _method _params &key
2461 deferred &allow-other-keys)
2462 (when (and eglot--managed-mode deferred)
2463 (eglot--signal-textDocument/didChange))))
2464 '((name . eglot--signal-textDocument/didChange)))
2465
2466(defvar-local eglot-workspace-configuration () 2468(defvar-local eglot-workspace-configuration ()
2467 "Configure LSP servers specifically for a given project. 2469 "Configure LSP servers specifically for a given project.
2468 2470
@@ -2615,8 +2617,8 @@ When called interactively, use the currently active server"
2615 (when (eglot--server-capable :textDocumentSync :willSaveWaitUntil) 2617 (when (eglot--server-capable :textDocumentSync :willSaveWaitUntil)
2616 (ignore-errors 2618 (ignore-errors
2617 (eglot--apply-text-edits 2619 (eglot--apply-text-edits
2618 (jsonrpc-request server :textDocument/willSaveWaitUntil params 2620 (eglot--request server :textDocument/willSaveWaitUntil params
2619 :timeout 0.5)))))) 2621 :timeout 0.5))))))
2620 2622
2621(defun eglot--signal-textDocument/didSave () 2623(defun eglot--signal-textDocument/didSave ()
2622 "Maybe send textDocument/didSave to server." 2624 "Maybe send textDocument/didSave to server."
@@ -2728,8 +2730,8 @@ If BUFFER, switch to it before."
2728 (propertize (alist-get kind eglot--symbol-kind-names "Unknown") 2730 (propertize (alist-get kind eglot--symbol-kind-names "Unknown")
2729 'face 'shadow)) 2731 'face 'shadow))
2730 'eglot--lsp-workspaceSymbol wss))) 2732 'eglot--lsp-workspaceSymbol wss)))
2731 (jsonrpc-request (eglot--current-server-or-lose) :workspace/symbol 2733 (eglot--request (eglot--current-server-or-lose) :workspace/symbol
2732 `(:query ,pat))))) 2734 `(:query ,pat)))))
2733 2735
2734(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot))) 2736(cl-defmethod xref-backend-identifier-completion-table ((_backend (eql eglot)))
2735 "Yet another tricky connection between LSP and Elisp completion semantics." 2737 "Yet another tricky connection between LSP and Elisp completion semantics."
@@ -2785,7 +2787,7 @@ If BUFFER, switch to it before."
2785 (cadr (split-string (symbol-name method) 2787 (cadr (split-string (symbol-name method)
2786 "/")))))) 2788 "/"))))))
2787 (let ((response 2789 (let ((response
2788 (jsonrpc-request 2790 (eglot--request
2789 (eglot--current-server-or-lose) 2791 (eglot--current-server-or-lose)
2790 method (append (eglot--TextDocumentPositionParams) extra-params)))) 2792 method (append (eglot--TextDocumentPositionParams) extra-params))))
2791 (eglot--collecting-xrefs (collect) 2793 (eglot--collecting-xrefs (collect)
@@ -2848,9 +2850,9 @@ If BUFFER, switch to it before."
2848 (eglot--lambda ((SymbolInformation) name location) 2850 (eglot--lambda ((SymbolInformation) name location)
2849 (eglot--dbind ((Location) uri range) location 2851 (eglot--dbind ((Location) uri range) location
2850 (collect (eglot--xref-make-match name uri range)))) 2852 (collect (eglot--xref-make-match name uri range))))
2851 (jsonrpc-request (eglot--current-server-or-lose) 2853 (eglot--request (eglot--current-server-or-lose)
2852 :workspace/symbol 2854 :workspace/symbol
2853 `(:query ,pattern)))))) 2855 `(:query ,pattern))))))
2854 2856
2855(defun eglot-format-buffer () 2857(defun eglot-format-buffer ()
2856 "Format contents of current buffer." 2858 "Format contents of current buffer."
@@ -2882,7 +2884,7 @@ for which LSP on-type-formatting should be requested."
2882 '(:textDocument/formatting :documentFormattingProvider nil))))) 2884 '(:textDocument/formatting :documentFormattingProvider nil)))))
2883 (eglot--server-capable-or-lose cap) 2885 (eglot--server-capable-or-lose cap)
2884 (eglot--apply-text-edits 2886 (eglot--apply-text-edits
2885 (jsonrpc-request 2887 (eglot--request
2886 (eglot--current-server-or-lose) 2888 (eglot--current-server-or-lose)
2887 method 2889 method
2888 (cl-list* 2890 (cl-list*
@@ -2891,8 +2893,14 @@ for which LSP on-type-formatting should be requested."
2891 :insertSpaces (if indent-tabs-mode :json-false t) 2893 :insertSpaces (if indent-tabs-mode :json-false t)
2892 :insertFinalNewline (if require-final-newline t :json-false) 2894 :insertFinalNewline (if require-final-newline t :json-false)
2893 :trimFinalNewlines (if delete-trailing-lines t :json-false)) 2895 :trimFinalNewlines (if delete-trailing-lines t :json-false))
2894 args) 2896 args)))))
2895 :deferred method)))) 2897
2898(defvar eglot-cache-session-completions t
2899 "If non-nil Eglot caches data during completion sessions.")
2900
2901(defvar eglot--capf-session :none "A cache used by `eglot-completion-at-point'.")
2902
2903(defun eglot--capf-session-flush (&optional _) (setq eglot--capf-session :none))
2896 2904
2897(defun eglot-completion-at-point () 2905(defun eglot-completion-at-point ()
2898 "Eglot's `completion-at-point' function." 2906 "Eglot's `completion-at-point' function."
@@ -2909,41 +2917,50 @@ for which LSP on-type-formatting should be requested."
2909 :sortText))))) 2917 :sortText)))))
2910 (metadata `(metadata (category . eglot) 2918 (metadata `(metadata (category . eglot)
2911 (display-sort-function . ,sort-completions))) 2919 (display-sort-function . ,sort-completions)))
2912 resp items (cached-proxies :none) 2920 (local-cache :none)
2921 (bounds (bounds-of-thing-at-point 'symbol))
2922 (orig-pos (point))
2923 (resolved (make-hash-table))
2913 (proxies 2924 (proxies
2914 (lambda () 2925 (lambda ()
2915 (if (listp cached-proxies) cached-proxies 2926 (if (listp local-cache) local-cache
2916 (setq resp 2927 (let* ((resp (eglot--request server
2917 (jsonrpc-request server 2928 :textDocument/completion
2918 :textDocument/completion 2929 (eglot--CompletionParams)
2919 (eglot--CompletionParams) 2930 :cancel-on-input t))
2920 :deferred :textDocument/completion 2931 (items (append
2921 :cancel-on-input t)) 2932 (if (vectorp resp) resp (plist-get resp :items))
2922 (setq items (append 2933 nil))
2923 (if (vectorp resp) resp (plist-get resp :items)) 2934 (cachep (and (listp resp) items
2924 nil)) 2935 eglot-cache-session-completions
2925 (setq cached-proxies 2936 (eq (plist-get resp :isIncomplete) :json-false)))
2926 (mapcar 2937 (bounds (or bounds
2927 (jsonrpc-lambda 2938 (cons (point) (point))))
2928 (&rest item &key label insertText insertTextFormat 2939 (proxies
2929 textEdit &allow-other-keys) 2940 (mapcar
2930 (let ((proxy 2941 (jsonrpc-lambda
2931 ;; Snippet or textEdit, it's safe to 2942 (&rest item &key label insertText insertTextFormat
2932 ;; display/insert the label since 2943 textEdit &allow-other-keys)
2933 ;; it'll be adjusted. If no usable 2944 (let ((proxy
2934 ;; insertText at all, label is best, 2945 ;; Snippet or textEdit, it's safe to
2935 ;; too. 2946 ;; display/insert the label since
2936 (cond ((or (eql insertTextFormat 2) 2947 ;; it'll be adjusted. If no usable
2937 textEdit 2948 ;; insertText at all, label is best,
2938 (null insertText) 2949 ;; too.
2939 (string-empty-p insertText)) 2950 (cond ((or (eql insertTextFormat 2)
2940 (string-trim-left label)) 2951 textEdit
2941 (t insertText)))) 2952 (null insertText)
2942 (unless (zerop (length proxy)) 2953 (string-empty-p insertText))
2943 (put-text-property 0 1 'eglot--lsp-item item proxy)) 2954 (string-trim-left label))
2944 proxy)) 2955 (t insertText))))
2945 items))))) 2956 (unless (zerop (length proxy))
2946 (resolved (make-hash-table)) 2957 (put-text-property 0 1 'eglot--lsp-item item proxy))
2958 proxy))
2959 items)))
2960 ;; (trace-values "Requested" (length proxies) cachep bounds)
2961 (setq eglot--capf-session
2962 (if cachep (list bounds proxies resolved orig-pos) :none))
2963 (setq local-cache proxies)))))
2947 (resolve-maybe 2964 (resolve-maybe
2948 ;; Maybe completion/resolve JSON object `lsp-comp' into 2965 ;; Maybe completion/resolve JSON object `lsp-comp' into
2949 ;; another JSON object, if at all possible. Otherwise, 2966 ;; another JSON object, if at all possible. Otherwise,
@@ -2954,13 +2971,21 @@ for which LSP on-type-formatting should be requested."
2954 (if (and (eglot--server-capable :completionProvider 2971 (if (and (eglot--server-capable :completionProvider
2955 :resolveProvider) 2972 :resolveProvider)
2956 (plist-get lsp-comp :data)) 2973 (plist-get lsp-comp :data))
2957 (jsonrpc-request server :completionItem/resolve 2974 (eglot--request server :completionItem/resolve
2958 lsp-comp :cancel-on-input t) 2975 lsp-comp :cancel-on-input t)
2959 lsp-comp))))) 2976 lsp-comp))))))
2960 (bounds (bounds-of-thing-at-point 'symbol))) 2977 (unless bounds (setq bounds (cons (point) (point))))
2978 (when (and (consp eglot--capf-session)
2979 (= (car bounds) (car (nth 0 eglot--capf-session)))
2980 (>= (cdr bounds) (cdr (nth 0 eglot--capf-session))))
2981 (setq local-cache (nth 1 eglot--capf-session)
2982 resolved (nth 2 eglot--capf-session)
2983 orig-pos (nth 3 eglot--capf-session))
2984 ;; (trace-values "Recalling cache" (length local-cache) bounds orig-pos)
2985 )
2961 (list 2986 (list
2962 (or (car bounds) (point)) 2987 (car bounds)
2963 (or (cdr bounds) (point)) 2988 (cdr bounds)
2964 (lambda (probe pred action) 2989 (lambda (probe pred action)
2965 (cond 2990 (cond
2966 ((eq action 'metadata) metadata) ; metadata 2991 ((eq action 'metadata) metadata) ; metadata
@@ -3031,7 +3056,7 @@ for which LSP on-type-formatting should be requested."
3031 :company-require-match 'never 3056 :company-require-match 'never
3032 :company-prefix-length 3057 :company-prefix-length
3033 (save-excursion 3058 (save-excursion
3034 (when (car bounds) (goto-char (car bounds))) 3059 (goto-char (car bounds))
3035 (when (listp completion-capability) 3060 (when (listp completion-capability)
3036 (looking-back 3061 (looking-back
3037 (regexp-opt 3062 (regexp-opt
@@ -3039,6 +3064,7 @@ for which LSP on-type-formatting should be requested."
3039 (eglot--bol)))) 3064 (eglot--bol))))
3040 :exit-function 3065 :exit-function
3041 (lambda (proxy status) 3066 (lambda (proxy status)
3067 (eglot--capf-session-flush)
3042 (when (memq status '(finished exact)) 3068 (when (memq status '(finished exact))
3043 ;; To assist in using this whole `completion-at-point' 3069 ;; To assist in using this whole `completion-at-point'
3044 ;; function inside `completion-in-region', ensure the exit 3070 ;; function inside `completion-in-region', ensure the exit
@@ -3062,17 +3088,12 @@ for which LSP on-type-formatting should be requested."
3062 (let ((snippet-fn (and (eql insertTextFormat 2) 3088 (let ((snippet-fn (and (eql insertTextFormat 2)
3063 (eglot--snippet-expansion-fn)))) 3089 (eglot--snippet-expansion-fn))))
3064 (cond (textEdit 3090 (cond (textEdit
3065 ;; Undo (yes, undo) the newly inserted completion. 3091 ;; Revert buffer back to state when the edit
3066 ;; If before completion the buffer was "foo.b" and 3092 ;; was obtained from server. If a `proxy'
3067 ;; now is "foo.bar", `proxy' will be "bar". We 3093 ;; "bar" was obtained from a buffer with
3068 ;; want to delete only "ar" (`proxy' minus the 3094 ;; "foo.b", the LSP edit applies to that'
3069 ;; symbol whose bounds we've calculated before) 3095 ;; state, _not_ the current "foo.bar".
3070 ;; (github#160). 3096 (delete-region orig-pos (point))
3071 (delete-region (+ (- (point) (length proxy))
3072 (if bounds
3073 (- (cdr bounds) (car bounds))
3074 0))
3075 (point))
3076 (eglot--dbind ((TextEdit) range newText) textEdit 3097 (eglot--dbind ((TextEdit) range newText) textEdit
3077 (pcase-let ((`(,beg . ,end) 3098 (pcase-let ((`(,beg . ,end)
3078 (eglot--range-region range))) 3099 (eglot--range-region range)))
@@ -3095,62 +3116,57 @@ for which LSP on-type-formatting should be requested."
3095 (mapconcat #'eglot--format-markup 3116 (mapconcat #'eglot--format-markup
3096 (if (vectorp contents) contents (list contents)) "\n")) 3117 (if (vectorp contents) contents (list contents)) "\n"))
3097 3118
3098(defun eglot--sig-info (sigs active-sig sig-help-active-param) 3119(defun eglot--sig-info (sig &optional _activep sig-help-active-param)
3099 (cl-loop 3120 (eglot--dbind ((SignatureInformation) label documentation parameters activeParameter)
3100 for (sig . moresigs) on (append sigs nil) for i from 0 3121 sig
3101 concat 3122 (with-temp-buffer
3102 (eglot--dbind ((SignatureInformation) label documentation parameters activeParameter) sig 3123 (save-excursion (insert label))
3103 (with-temp-buffer 3124 (let ((active-param (or activeParameter sig-help-active-param))
3104 (save-excursion (insert label)) 3125 params-start params-end)
3105 (let ((active-param (or activeParameter sig-help-active-param)) 3126 ;; Ad-hoc attempt to parse label as <name>(<params>)
3106 params-start params-end) 3127 (when (looking-at "\\([^(]*\\)(\\([^)]+\\))")
3107 ;; Ad-hoc attempt to parse label as <name>(<params>) 3128 (setq params-start (match-beginning 2) params-end (match-end 2))
3108 (when (looking-at "\\([^(]*\\)(\\([^)]+\\))") 3129 (add-face-text-property (match-beginning 1) (match-end 1)
3109 (setq params-start (match-beginning 2) params-end (match-end 2)) 3130 'font-lock-function-name-face))
3110 (add-face-text-property (match-beginning 1) (match-end 1) 3131 ;; Decide whether to add one-line-summary to signature line
3111 'font-lock-function-name-face)) 3132 (when (and (stringp documentation)
3112 (when (eql i active-sig) 3133 (string-match "[[:space:]]*\\([^.\r\n]+[.]?\\)"
3113 ;; Decide whether to add one-line-summary to signature line 3134 documentation))
3114 (when (and (stringp documentation) 3135 (setq documentation (match-string 1 documentation))
3115 (string-match "[[:space:]]*\\([^.\r\n]+[.]?\\)" 3136 (unless (string-prefix-p (string-trim documentation) label)
3116 documentation)) 3137 (goto-char (point-max))
3117 (setq documentation (match-string 1 documentation)) 3138 (insert ": " (eglot--format-markup documentation))))
3118 (unless (string-prefix-p (string-trim documentation) label) 3139 ;; Decide what to do with the active parameter...
3119 (goto-char (point-max)) 3140 (when (and active-param (< -1 active-param (length parameters)))
3120 (insert ": " (eglot--format-markup documentation)))) 3141 (eglot--dbind ((ParameterInformation) label documentation)
3121 ;; Decide what to do with the active parameter... 3142 (aref parameters active-param)
3122 (when (and (eql i active-sig) active-param 3143 ;; ...perhaps highlight it in the formals list
3123 (< -1 active-param (length parameters))) 3144 (when params-start
3124 (eglot--dbind ((ParameterInformation) label documentation) 3145 (goto-char params-start)
3125 (aref parameters active-param) 3146 (pcase-let
3126 ;; ...perhaps highlight it in the formals list 3147 ((`(,beg ,end)
3127 (when params-start 3148 (if (stringp label)
3128 (goto-char params-start) 3149 (let ((case-fold-search nil))
3129 (pcase-let 3150 (and (re-search-forward
3130 ((`(,beg ,end) 3151 (concat "\\<" (regexp-quote label) "\\>")
3152 params-end t)
3153 (list (match-beginning 0) (match-end 0))))
3154 (mapcar #'1+ (append label nil)))))
3155 (if (and beg end)
3156 (add-face-text-property
3157 beg end
3158 'eldoc-highlight-function-argument))))
3159 ;; ...and/or maybe add its doc on a line by its own.
3160 (when documentation
3161 (goto-char (point-max))
3162 (insert "\n"
3163 (propertize
3131 (if (stringp label) 3164 (if (stringp label)
3132 (let ((case-fold-search nil)) 3165 label
3133 (and (re-search-forward 3166 (apply #'buffer-substring (mapcar #'1+ label)))
3134 (concat "\\<" (regexp-quote label) "\\>") 3167 'face 'eldoc-highlight-function-argument)
3135 params-end t) 3168 ": " (eglot--format-markup documentation))))))
3136 (list (match-beginning 0) (match-end 0)))) 3169 (buffer-string))))
3137 (mapcar #'1+ (append label nil)))))
3138 (if (and beg end)
3139 (add-face-text-property
3140 beg end
3141 'eldoc-highlight-function-argument))))
3142 ;; ...and/or maybe add its doc on a line by its own.
3143 (when documentation
3144 (goto-char (point-max))
3145 (insert "\n"
3146 (propertize
3147 (if (stringp label)
3148 label
3149 (apply #'buffer-substring (mapcar #'1+ label)))
3150 'face 'eldoc-highlight-function-argument)
3151 ": " (eglot--format-markup documentation))))))
3152 (buffer-string))))
3153 when moresigs concat "\n"))
3154 3170
3155(defun eglot-signature-eldoc-function (cb) 3171(defun eglot-signature-eldoc-function (cb)
3156 "A member of `eldoc-documentation-functions', for signatures." 3172 "A member of `eldoc-documentation-functions', for signatures."
@@ -3163,11 +3179,12 @@ for which LSP on-type-formatting should be requested."
3163 (eglot--lambda ((SignatureHelp) 3179 (eglot--lambda ((SignatureHelp)
3164 signatures activeSignature activeParameter) 3180 signatures activeSignature activeParameter)
3165 (eglot--when-buffer-window buf 3181 (eglot--when-buffer-window buf
3166 (funcall cb 3182 (let ((active-sig (and (cl-plusp (length signatures))
3167 (unless (seq-empty-p signatures) 3183 (aref signatures (or activeSignature 0)))))
3168 (eglot--sig-info signatures 3184 (if (not active-sig) (funcall cb nil)
3169 activeSignature 3185 (funcall cb
3170 activeParameter))))) 3186 (mapconcat #'eglot--sig-info signatures "\n")
3187 :echo (eglot--sig-info active-sig t activeParameter))))))
3171 :deferred :textDocument/signatureHelp)) 3188 :deferred :textDocument/signatureHelp))
3172 t)) 3189 t))
3173 3190
@@ -3255,11 +3272,11 @@ Returns a list as described in docstring of `imenu--index-alist'."
3255 (seq-group-by 3272 (seq-group-by
3256 (lambda (obj) (plist-get obj :kind)) 3273 (lambda (obj) (plist-get obj :kind))
3257 (mapcan #'unfurl 3274 (mapcan #'unfurl
3258 (jsonrpc-request (eglot--current-server-or-lose) 3275 (eglot--request (eglot--current-server-or-lose)
3259 :textDocument/documentSymbol 3276 :textDocument/documentSymbol
3260 `(:textDocument 3277 `(:textDocument
3261 ,(eglot--TextDocumentIdentifier)) 3278 ,(eglot--TextDocumentIdentifier))
3262 :cancel-on-input non-essential)))))) 3279 :cancel-on-input non-essential))))))
3263 3280
3264(cl-defun eglot--apply-text-edits (edits &optional version) 3281(cl-defun eglot--apply-text-edits (edits &optional version)
3265 "Apply EDITS for current buffer if at VERSION, or if it's nil." 3282 "Apply EDITS for current buffer if at VERSION, or if it's nil."
@@ -3330,9 +3347,9 @@ Returns a list as described in docstring of `imenu--index-alist'."
3330 (symbol-name (symbol-at-point))))) 3347 (symbol-name (symbol-at-point)))))
3331 (eglot--server-capable-or-lose :renameProvider) 3348 (eglot--server-capable-or-lose :renameProvider)
3332 (eglot--apply-workspace-edit 3349 (eglot--apply-workspace-edit
3333 (jsonrpc-request (eglot--current-server-or-lose) 3350 (eglot--request (eglot--current-server-or-lose)
3334 :textDocument/rename `(,@(eglot--TextDocumentPositionParams) 3351 :textDocument/rename `(,@(eglot--TextDocumentPositionParams)
3335 :newName ,newname)) 3352 :newName ,newname))
3336 current-prefix-arg)) 3353 current-prefix-arg))
3337 3354
3338(defun eglot--region-bounds () 3355(defun eglot--region-bounds ()
@@ -3358,7 +3375,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
3358 (eglot--server-capable-or-lose :codeActionProvider) 3375 (eglot--server-capable-or-lose :codeActionProvider)
3359 (let* ((server (eglot--current-server-or-lose)) 3376 (let* ((server (eglot--current-server-or-lose))
3360 (actions 3377 (actions
3361 (jsonrpc-request 3378 (eglot--request
3362 server 3379 server
3363 :textDocument/codeAction 3380 :textDocument/codeAction
3364 (list :textDocument (eglot--TextDocumentIdentifier) 3381 (list :textDocument (eglot--TextDocumentIdentifier)
@@ -3370,8 +3387,7 @@ at point. With prefix argument, prompt for ACTION-KIND."
3370 when (cdr (assoc 'eglot-lsp-diag 3387 when (cdr (assoc 'eglot-lsp-diag
3371 (eglot--diag-data diag))) 3388 (eglot--diag-data diag)))
3372 collect it)] 3389 collect it)]
3373 ,@(when action-kind `(:only [,action-kind])))) 3390 ,@(when action-kind `(:only [,action-kind]))))))
3374 :deferred t))
3375 ;; Redo filtering, in case the `:only' didn't go through. 3391 ;; Redo filtering, in case the `:only' didn't go through.
3376 (actions (cl-loop for a across actions 3392 (actions (cl-loop for a across actions
3377 when (or (not action-kind) 3393 when (or (not action-kind)
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index b21b1fd2cef..ef87bb29d52 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -41,6 +41,16 @@
41 :safe 'integerp 41 :safe 'integerp
42 :group 'typescript) 42 :group 'typescript)
43 43
44(defface typescript-ts-jsx-tag-face
45 '((t . (:inherit font-lock-function-call-face)))
46 "Face for HTML tags like <div> and <p> in JSX."
47 :group 'typescript)
48
49(defface typescript-ts-jsx-attribute-face
50 '((t . (:inherit font-lock-constant-face)))
51 "Face for HTML attributes like name and id in JSX."
52 :group 'typescript)
53
44(defvar typescript-ts-mode--syntax-table 54(defvar typescript-ts-mode--syntax-table
45 (let ((table (make-syntax-table))) 55 (let ((table (make-syntax-table)))
46 ;; Taken from the cc-langs version 56 ;; Taken from the cc-langs version
@@ -284,17 +294,17 @@ Argument LANGUAGE is either `typescript' or `tsx'."
284 :feature 'jsx 294 :feature 'jsx
285 `((jsx_opening_element 295 `((jsx_opening_element
286 [(nested_identifier (identifier)) (identifier)] 296 [(nested_identifier (identifier)) (identifier)]
287 @font-lock-function-call-face) 297 @typescript-ts-jsx-tag-face)
288 298
289 (jsx_closing_element 299 (jsx_closing_element
290 [(nested_identifier (identifier)) (identifier)] 300 [(nested_identifier (identifier)) (identifier)]
291 @font-lock-function-call-face) 301 @typescript-ts-jsx-tag-face)
292 302
293 (jsx_self_closing_element 303 (jsx_self_closing_element
294 [(nested_identifier (identifier)) (identifier)] 304 [(nested_identifier (identifier)) (identifier)]
295 @font-lock-function-call-face) 305 @typescript-ts-jsx-tag-face)
296 306
297 (jsx_attribute (property_identifier) @font-lock-constant-face)) 307 (jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face))
298 308
299 :language language 309 :language language
300 :feature 'number 310 :feature 'number
@@ -438,7 +448,12 @@ See `treesit-sexp-type-regexp' for more information.")
438 448
439;;;###autoload 449;;;###autoload
440(define-derived-mode tsx-ts-mode typescript-ts-base-mode "TypeScript[TSX]" 450(define-derived-mode tsx-ts-mode typescript-ts-base-mode "TypeScript[TSX]"
441 "Major mode for editing TypeScript." 451 "Major mode for editing TSX and JSX documents.
452
453This major mode defines two additional JSX-specific faces:
454`typescript-ts-jsx-attribute-face' and
455`typescript-ts-jsx-attribute-face' that are used for HTML tags
456and attributes, respectively."
442 :group 'typescript 457 :group 'typescript
443 :syntax-table typescript-ts-mode--syntax-table 458 :syntax-table typescript-ts-mode--syntax-table
444 459
diff --git a/lisp/simple.el b/lisp/simple.el
index c7687519f4b..8f6c00cf54b 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -623,7 +623,7 @@ A non-nil INTERACTIVE argument means to run the `post-self-insert-hook'."
623 (beforepos (point)) 623 (beforepos (point))
624 (last-command-event ?\n) 624 (last-command-event ?\n)
625 ;; Don't auto-fill if we have a prefix argument. 625 ;; Don't auto-fill if we have a prefix argument.
626 (auto-fill-function (if arg nil auto-fill-function)) 626 (inhibit-auto-fill (or inhibit-auto-fill arg))
627 (arg (prefix-numeric-value arg)) 627 (arg (prefix-numeric-value arg))
628 (procsym (make-symbol "newline-postproc")) ;(bug#46326) 628 (procsym (make-symbol "newline-postproc")) ;(bug#46326)
629 (postproc 629 (postproc
@@ -8919,11 +8919,15 @@ unless optional argument SOFT is non-nil."
8919 ;; If we're not inside a comment, just try to indent. 8919 ;; If we're not inside a comment, just try to indent.
8920 (t (indent-according-to-mode)))))) 8920 (t (indent-according-to-mode))))))
8921 8921
8922(defvar inhibit-auto-fill nil
8923 "Non-nil means to do as if `auto-fill-mode' was disabled.")
8924
8922(defun internal-auto-fill () 8925(defun internal-auto-fill ()
8923 "The function called by `self-insert-command' to perform auto-filling." 8926 "The function called by `self-insert-command' to perform auto-filling."
8924 (when (or (not comment-start) 8927 (unless (or inhibit-auto-fill
8925 (not comment-auto-fill-only-comments) 8928 (and comment-start
8926 (nth 4 (syntax-ppss))) 8929 comment-auto-fill-only-comments
8930 (not (nth 4 (syntax-ppss)))))
8927 (funcall auto-fill-function))) 8931 (funcall auto-fill-function)))
8928 8932
8929(defvar normal-auto-fill-function 'do-auto-fill 8933(defvar normal-auto-fill-function 'do-auto-fill
diff --git a/src/comp.c b/src/comp.c
index 5cbe441dd7f..9ff3efedbdd 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -5910,6 +5910,14 @@ For internal use. */);
5910 Vcomp_loaded_comp_units_h = 5910 Vcomp_loaded_comp_units_h =
5911 CALLN (Fmake_hash_table, QCweakness, Qvalue, QCtest, Qequal); 5911 CALLN (Fmake_hash_table, QCweakness, Qvalue, QCtest, Qequal);
5912 5912
5913 DEFVAR_LISP ("comp-subr-arities-h", Vcomp_subr_arities_h,
5914 doc: /* Hash table recording the arity of Lisp primitives.
5915This is in case they are redefined so the compiler still knows how to
5916compile calls to them.
5917subr-name -> arity
5918For internal use. */);
5919 Vcomp_subr_arities_h = CALLN (Fmake_hash_table, QCtest, Qequal);
5920
5913 Fprovide (intern_c_string ("native-compile"), Qnil); 5921 Fprovide (intern_c_string ("native-compile"), Qnil);
5914#endif /* #ifdef HAVE_NATIVE_COMP */ 5922#endif /* #ifdef HAVE_NATIVE_COMP */
5915 5923
diff --git a/src/eval.c b/src/eval.c
index eb40c953f96..1a4d3ad0307 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -3400,7 +3400,7 @@ DEFUN ("fetch-bytecode", Ffetch_bytecode, Sfetch_bytecode,
3400 return object; 3400 return object;
3401} 3401}
3402 3402
3403/* Return true if SYMBOL currently has a let-binding 3403/* Return true if SYMBOL's default currently has a let-binding
3404 which was made in the buffer that is now current. */ 3404 which was made in the buffer that is now current. */
3405 3405
3406bool 3406bool
@@ -3415,6 +3415,7 @@ let_shadows_buffer_binding_p (struct Lisp_Symbol *symbol)
3415 struct Lisp_Symbol *let_bound_symbol = XSYMBOL (specpdl_symbol (p)); 3415 struct Lisp_Symbol *let_bound_symbol = XSYMBOL (specpdl_symbol (p));
3416 eassert (let_bound_symbol->u.s.redirect != SYMBOL_VARALIAS); 3416 eassert (let_bound_symbol->u.s.redirect != SYMBOL_VARALIAS);
3417 if (symbol == let_bound_symbol 3417 if (symbol == let_bound_symbol
3418 && p->kind != SPECPDL_LET_LOCAL /* bug#62419 */
3418 && EQ (specpdl_where (p), buf)) 3419 && EQ (specpdl_where (p), buf))
3419 return 1; 3420 return 1;
3420 } 3421 }
diff --git a/src/xdisp.c b/src/xdisp.c
index 7cde3d30885..046d1f78452 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -18593,8 +18593,9 @@ try_scrolling (Lisp_Object window, bool just_this_one_p,
18593 start_display (&it, w, startp); 18593 start_display (&it, w, startp);
18594 18594
18595 if (arg_scroll_conservatively) 18595 if (arg_scroll_conservatively)
18596 amount_to_scroll = max (dy, frame_line_height 18596 amount_to_scroll
18597 * max (scroll_step, temp_scroll_step)); 18597 = min (max (dy, frame_line_height),
18598 frame_line_height * arg_scroll_conservatively);
18598 else if (scroll_step || temp_scroll_step) 18599 else if (scroll_step || temp_scroll_step)
18599 amount_to_scroll = scroll_max; 18600 amount_to_scroll = scroll_max;
18600 else 18601 else
diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el
index 8e02fbb5497..fa20efa71e1 100644
--- a/test/lisp/eshell/esh-proc-tests.el
+++ b/test/lisp/eshell/esh-proc-tests.el
@@ -192,6 +192,59 @@ pipeline."
192 "stdout\nstderr\n")))) 192 "stdout\nstderr\n"))))
193 193
194 194
195;; Synchronous processes
196
197;; These tests check that synchronous subprocesses (only used on
198;; MS-DOS by default) work correctly. To help them run on MS-DOS as
199;; well, we use the Emacs executable as our subprocess to test
200;; against; that way, users don't need to have GNU coreutils (or
201;; similar) installed.
202
203(defsubst esh-proc-test/emacs-command (command)
204 "Evaluate COMMAND in a new Emacs batch instance."
205 (mapconcat #'shell-quote-argument
206 `(,(expand-file-name invocation-name invocation-directory)
207 "-Q" "--batch" "--eval" ,(prin1-to-string command))
208 " "))
209
210(defvar esh-proc-test/emacs-echo
211 (esh-proc-test/emacs-command '(princ "hello\n"))
212 "A command that prints \"hello\" to stdout using Emacs.")
213
214(defvar esh-proc-test/emacs-upcase
215 (esh-proc-test/emacs-command
216 '(princ (upcase (concat (read-string "") "\n"))))
217 "A command that upcases the text from stdin using Emacs.")
218
219(ert-deftest esh-proc-test/synchronous-proc/simple/interactive ()
220 "Test that synchronous processes work in an interactive shell."
221 (let ((eshell-supports-asynchronous-processes nil))
222 (with-temp-eshell
223 (eshell-match-command-output esh-proc-test/emacs-echo
224 "\\`hello\n"))))
225
226(ert-deftest esh-proc-test/synchronous-proc/simple/command-result ()
227 "Test that synchronous processes work via `eshell-command-result'."
228 (let ((eshell-supports-asynchronous-processes nil))
229 (eshell-command-result-equal esh-proc-test/emacs-echo
230 "hello\n")))
231
232(ert-deftest esh-proc-test/synchronous-proc/pipeline/interactive ()
233 "Test that synchronous pipelines work in an interactive shell."
234 (let ((eshell-supports-asynchronous-processes nil))
235 (with-temp-eshell
236 (eshell-match-command-output (concat esh-proc-test/emacs-echo " | "
237 esh-proc-test/emacs-upcase)
238 "\\`HELLO\n"))))
239
240(ert-deftest esh-proc-test/synchronous-proc/pipeline/command-result ()
241 "Test that synchronous pipelines work via `eshell-command-result'."
242 (let ((eshell-supports-asynchronous-processes nil))
243 (eshell-command-result-equal (concat esh-proc-test/emacs-echo " | "
244 esh-proc-test/emacs-upcase)
245 "HELLO\n")))
246
247
195;; Killing processes 248;; Killing processes
196 249
197(ert-deftest esh-proc-test/kill-process/foreground-only () 250(ert-deftest esh-proc-test/kill-process/foreground-only ()
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index 743cc28b9b5..390f75cfbb9 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -107,6 +107,50 @@
107 (format template "format \"%s\" eshell-in-pipeline-p") 107 (format template "format \"%s\" eshell-in-pipeline-p")
108 "nil"))) 108 "nil")))
109 109
110(ert-deftest eshell-test/eshell-command/simple ()
111 "Test that the `eshell-command' function writes to the current buffer."
112 (skip-unless (executable-find "echo"))
113 (ert-with-temp-directory eshell-directory-name
114 (let ((eshell-history-file-name nil))
115 (with-temp-buffer
116 (eshell-command "*echo hi" t)
117 (should (equal (buffer-string) "hi\n"))))))
118
119(ert-deftest eshell-test/eshell-command/pipeline ()
120 "Test that the `eshell-command' function writes to the current buffer.
121This test uses a pipeline for the command."
122 (skip-unless (and (executable-find "echo")
123 (executable-find "cat")))
124 (ert-with-temp-directory eshell-directory-name
125 (let ((eshell-history-file-name nil))
126 (with-temp-buffer
127 (eshell-command "*echo hi | *cat" t)
128 (should (equal (buffer-string) "hi\n"))))))
129
130(ert-deftest eshell-test/eshell-command/background ()
131 "Test that `eshell-command' works for background commands."
132 (skip-unless (executable-find "echo"))
133 (ert-with-temp-directory eshell-directory-name
134 (let ((orig-processes (process-list))
135 (eshell-history-file-name nil))
136 (with-temp-buffer
137 (eshell-command "*echo hi &" t)
138 (eshell-wait-for (lambda () (equal (process-list) orig-processes)))
139 (should (equal (buffer-string) "hi\n"))))))
140
141(ert-deftest eshell-test/eshell-command/background-pipeline ()
142 "Test that `eshell-command' works for background commands.
143This test uses a pipeline for the command."
144 (skip-unless (and (executable-find "echo")
145 (executable-find "cat")))
146 (ert-with-temp-directory eshell-directory-name
147 (let ((orig-processes (copy-tree (process-list)))
148 (eshell-history-file-name nil))
149 (with-temp-buffer
150 (eshell-command "*echo hi | *cat &" t)
151 (eshell-wait-for (lambda () (equal (process-list) orig-processes)))
152 (should (equal (buffer-string) "hi\n"))))))
153
110(ert-deftest eshell-test/command-running-p () 154(ert-deftest eshell-test/command-running-p ()
111 "Modeline should show no command running" 155 "Modeline should show no command running"
112 (with-temp-eshell 156 (with-temp-eshell
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
index 926ba27e563..c5e5b346adb 100644
--- a/test/src/comp-tests.el
+++ b/test/src/comp-tests.el
@@ -446,7 +446,7 @@ https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html."
446 (should (equal comp-test-primitive-advice '(3 4)))) 446 (should (equal comp-test-primitive-advice '(3 4))))
447 (advice-remove #'+ f)))) 447 (advice-remove #'+ f))))
448 448
449(defvar comp-test-primitive-redefine-args) 449(defvar comp-test-primitive-redefine-args nil)
450(comp-deftest primitive-redefine () 450(comp-deftest primitive-redefine ()
451 "Test effectiveness of primitive redefinition." 451 "Test effectiveness of primitive redefinition."
452 (cl-letf ((comp-test-primitive-redefine-args nil) 452 (cl-letf ((comp-test-primitive-redefine-args nil)
@@ -532,6 +532,22 @@ https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html."
532 (should (subr-native-elisp-p 532 (should (subr-native-elisp-p
533 (symbol-function 'comp-test-48029-nonascii-žžž-f)))) 533 (symbol-function 'comp-test-48029-nonascii-žžž-f))))
534 534
535(comp-deftest 61917-1 ()
536 "Verify we can compile calls to redefined primitives with
537dedicated byte-op code."
538 (let (x
539 (f (lambda (fn &rest args)
540 (setq comp-test-primitive-redefine-args args))))
541 (advice-add #'delete-region :around f)
542 (unwind-protect
543 (setf x (native-compile
544 '(lambda ()
545 (delete-region 1 2))))
546 (should (subr-native-elisp-p x))
547 (funcall x)
548 (advice-remove #'delete-region f)
549 (should (equal comp-test-primitive-redefine-args '(1 2))))))
550
535 551
536;;;;;;;;;;;;;;;;;;;;; 552;;;;;;;;;;;;;;;;;;;;;
537;; Tromey's tests. ;; 553;; Tromey's tests. ;;
diff --git a/test/src/eval-tests.el b/test/src/eval-tests.el
index 1e7edca3bac..e0a27439ba2 100644
--- a/test/src/eval-tests.el
+++ b/test/src/eval-tests.el
@@ -247,4 +247,23 @@ expressions works for identifiers starting with period."
247 (should (equal (string-trim (buffer-string)) 247 (should (equal (string-trim (buffer-string))
248 expected-messages)))))))) 248 expected-messages))))))))
249 249
250(defvar-local eval-test--local-var 'global)
251
252(ert-deftest eval-test--bug62419 ()
253 (with-temp-buffer
254 (setq eval-test--local-var 'first-local)
255 (let ((eval-test--local-var t))
256 (kill-local-variable 'eval-test--local-var)
257 (setq eval-test--local-var 'second-local)
258 (should (eq eval-test--local-var 'second-local)))
259 ;; FIXME: It's not completely clear if exiting the above `let'
260 ;; should restore the buffer-local binding to `first-local'
261 ;; (i.e. reset the value of the second buffer-local binding to the
262 ;; first's initial value) or should do nothing (on the principle that
263 ;; the first buffer-local binding doesn't exists any more so there's
264 ;; nothing to restore). I think both semantics make sense.
265 ;;(should (eq eval-test--local-var 'first-local))
266 )
267 (should (eq eval-test--local-var 'global)))
268
250;;; eval-tests.el ends here 269;;; eval-tests.el ends here