summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/emacs/misc.texi177
-rw-r--r--doc/lispref/functions.texi14
-rw-r--r--doc/lispref/help.texi18
-rw-r--r--doc/lispref/modes.texi8
-rw-r--r--doc/lispref/parsing.texi14
-rw-r--r--doc/lispref/symbols.texi17
-rw-r--r--doc/misc/org.org11
-rw-r--r--etc/NEWS.298
-rw-r--r--lisp/align.el3
-rw-r--r--lisp/font-lock.el9
-rw-r--r--lisp/org/ob-core.el14
-rw-r--r--lisp/org/ob-shell.el2
-rw-r--r--lisp/org/org-macs.el11
-rw-r--r--lisp/org/org-persist.el2
-rw-r--r--lisp/org/org-table.el1
-rw-r--r--lisp/org/org-version.el2
-rw-r--r--lisp/org/org.el22
-rw-r--r--lisp/org/ox.el1
-rw-r--r--lisp/progmodes/c-ts-mode.el174
-rw-r--r--lisp/progmodes/go-ts-mode.el107
-rw-r--r--lisp/progmodes/gud.el5
-rw-r--r--lisp/progmodes/js.el5
-rw-r--r--lisp/progmodes/project.el2
-rw-r--r--lisp/progmodes/python.el36
-rw-r--r--lisp/progmodes/ruby-ts-mode.el17
-rw-r--r--lisp/progmodes/typescript-ts-mode.el22
-rw-r--r--lisp/progmodes/xref.el2
-rw-r--r--lisp/simple.el67
-rw-r--r--lisp/treesit.el61
-rw-r--r--lisp/vc/diff-mode.el14
-rw-r--r--src/callint.c12
-rw-r--r--src/pgtkfns.c2
-rw-r--r--src/print.c9
-rw-r--r--test/lisp/progmodes/python-tests.el10
-rw-r--r--test/lisp/progmodes/ruby-mode-resources/ruby.rb2
35 files changed, 583 insertions, 298 deletions
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index c706b727e6f..88d4188d144 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -2702,40 +2702,16 @@ when point is on the first byte of a multibyte sequence in the file.
@cindex restore session
@cindex remember editing session
@cindex reload files
-@cindex desktop
-@vindex desktop-restore-frames
- Use the desktop library to save the state of Emacs from one session
-to another. Once you save the Emacs @dfn{desktop}---the buffers,
-their file names, major modes, buffer positions, and so on---then
-subsequent Emacs sessions reload the saved desktop. By default,
-the desktop also tries to save the frame and window configuration.
-To disable this, set @code{desktop-restore-frames} to @code{nil}.
-(See that variable's documentation for some related options
-that you can customize to fine-tune this behavior.)
-
-@vindex desktop-files-not-to-save
-Information about buffers visiting remote files is not saved by
-default. Customize the variable @code{desktop-files-not-to-save} to
-change this.
-
-@vindex frameset-filter-alist
- When the desktop restores the frame and window configuration, it
-uses the recorded values of frame parameters, disregarding any
-settings for those parameters you have in your init file (@pxref{Init
-File}). This means that frame parameters such as fonts and faces for
-the restored frames will come from the desktop file, where they were
-saved when you exited your previous Emacs session; any settings for
-those parameters in your init file will be ignored. To disable this,
-customize the value of @code{frameset-filter-alist} to filter out the
-frame parameters you don't want to be restored.
+@cindex desktop configuration
+ You can use the desktop library to save the state of Emacs from one
+session to another. The saved Emacs @dfn{desktop configuration}
+includes the buffers, their file names, major modes, buffer positions,
+window and frame configuration, and some important global variables.
-@findex desktop-save
@vindex desktop-save-mode
- You can save the desktop manually with the command @kbd{M-x
-desktop-save}. You can also enable automatic saving of the desktop
-when you exit Emacs, and automatic restoration of the last saved
-desktop when Emacs starts: use the Customization buffer (@pxref{Easy
+@findex desktop-save-mode
+ To enable this feature, use the Customization buffer (@pxref{Easy
Customization}) to set @code{desktop-save-mode} to @code{t} for future
sessions, or add this line in your init file (@pxref{Init File}):
@@ -2743,51 +2719,34 @@ sessions, or add this line in your init file (@pxref{Init File}):
(desktop-save-mode 1)
@end example
-@findex desktop-change-dir
-@findex desktop-revert
@vindex desktop-path
+@vindex desktop-auto-save-timeout
If you turn on @code{desktop-save-mode} in your init file, then when
-Emacs starts, it looks for a saved desktop in the current directory.
-(More precisely, it looks in the directories specified by
-@code{desktop-path}, and uses the first desktop it finds.)
-Thus, you can have separate saved desktops in different directories,
-and the starting directory determines which one Emacs reloads. You
-can save the current desktop and reload one saved in another directory
-by typing @kbd{M-x desktop-change-dir}. Typing @kbd{M-x
-desktop-revert} reverts to the desktop previously reloaded.
-
- Specify the option @samp{--no-desktop} on the command line when you
-don't want it to reload any saved desktop. This turns off
-@code{desktop-save-mode} for the current session. Starting Emacs with
-the @samp{--no-init-file} option also disables desktop reloading,
-since it bypasses the init file, where @code{desktop-save-mode} is
-usually turned on.
-
-@vindex desktop-restore-eager
- By default, all the buffers in the desktop are restored in one go.
-However, this may be slow if there are a lot of buffers in the
-desktop. You can specify the maximum number of buffers to restore
-immediately with the variable @code{desktop-restore-eager}; the
-remaining buffers are restored lazily, when Emacs is idle.
-
-@findex desktop-clear
-@vindex desktop-globals-to-clear
-@vindex desktop-clear-preserve-buffers-regexp
- Type @kbd{M-x desktop-clear} to empty the Emacs desktop. This kills
-all buffers except for internal ones, and clears the global variables
-listed in @code{desktop-globals-to-clear}. If you want this to
-preserve certain buffers, customize the variable
-@code{desktop-clear-preserve-buffers-regexp}, whose value is a regular
-expression matching the names of buffers not to kill.
+Emacs starts, it looks for a saved desktop in @code{desktop-path}
+(which defaults to @code{user-emacs-directory} and then your home
+directory) and uses the first desktop it finds. While Emacs runs with
+@code{desktop-save-mode} turned on, it by default auto-saves the
+desktop whenever any of the desktop configuration changes. The
+variable @code{desktop-auto-save-timeout} determines how frequently
+Emacs checks for modifications to your desktop. The desktop is also
+saved when you exit Emacs.
- If you want to save minibuffer history from one session to
-another, use the @code{savehist} library.
+@cindex disable restoring of desktop configuration
+ Specify the option @samp{--no-desktop} on the Emacs command line
+when you don't want it to reload any saved desktop configurations.
+This turns off @code{desktop-save-mode} for the current session.
+Starting Emacs with the @samp{--no-init-file} option also disables
+desktop reloading, since it bypasses the init file, where
+@code{desktop-save-mode} is usually turned on.
-@vindex desktop-auto-save-timeout
- While Emacs runs with @code{desktop-save-mode} turned on, it by
-default auto-saves the desktop whenever any of it changes. The
-variable @code{desktop-auto-save-timeout} determines how frequently
-Emacs checks for modifications to your desktop.
+@findex desktop-change-dir
+@findex desktop-revert
+ You can have separate saved desktop configurations in different
+directories; starting Emacs from a directory where you have a saved
+desktop configuration will restore that configuration. You can save
+the current desktop and reload the one saved in another directory by
+typing @kbd{M-x desktop-change-dir}. Typing @kbd{M-x desktop-revert}
+reverts to the previously reloaded desktop.
@vindex desktop-load-locked-desktop
The file in which Emacs saves the desktop is locked while the
@@ -2798,12 +2757,13 @@ will by default ask you whether to use the locked desktop file. You
can avoid the question by customizing the variable
@code{desktop-load-locked-desktop} to either @code{nil}, which means
never load the desktop in this case, or @code{t}, which means load the
-desktop without asking. Finally, the @code{check-pid} value means to
-load the file if the Emacs process that has locked the desktop is not
-running on the local machine. This should not be used in
-circumstances where the locking Emacs might still be running on
-another machine. This could be the case in multi-user environments
-where your home directory is mounted remotely using NFS or similar.
+desktop without asking. You can also customize the variable to the
+special value @code{check-pid}, which means to load the file if the
+Emacs process that has locked the desktop is not running on the local
+machine. This should not be used in circumstances where the locking
+Emacs might still be running on another machine, which could be the
+case in multi-user environments where your home directory is mounted
+remotely using NFS or similar.
@cindex desktop restore in daemon mode
When Emacs starts in daemon mode, it cannot ask you any questions,
@@ -2813,10 +2773,67 @@ the desktop in daemon mode is somewhat problematic for other reasons:
e.g., the daemon cannot use GUI features, so parameters such as frame
position, size, and decorations cannot be restored. For that reason,
you may wish to delay restoring the desktop in daemon mode until the
-first client connects, by calling @code{desktop-read} in a hook
-function that you add to @code{server-after-make-frame-hook}
+first client connects, by calling @code{desktop-read} (see below) in a
+hook function that you add to @code{server-after-make-frame-hook}
(@pxref{Creating Frames,,, elisp, The Emacs Lisp Reference Manual}).
+@findex desktop-save
+@findex desktop-read
+ Whenever you want, you can use the command @kbd{M-x desktop-save} to
+force immediate saving of the current desktop. This is useful either
+if you do not want to use the automatic desktop restoration, and thus
+don't turn on @code{desktop-save-mode}, or when you have made
+significant changes to the desktop, and want to make sure the
+configuration doesn't get lost if Emacs or your system crashes. You
+can use @kbd{M-x desktop-read} to restore a previously-saved desktop
+if the current Emacs session didn't load any desktop yet.
+
+@vindex desktop-restore-frames
+ By default, the desktop tries to save and restore the frame and
+window configuration. To disable this, set
+@code{desktop-restore-frames} to @code{nil}. (See that variable's
+documentation for some related options that you can customize to
+fine-tune this behavior.)
+
+@vindex frameset-filter-alist
+ When the desktop restores the frame and window configuration, it
+uses the recorded values of frame parameters, disregarding any
+settings for those parameters you have in your init file (@pxref{Init
+File}). This means that frame parameters such as fonts and faces for
+the restored frames will come from the desktop file, where they were
+saved when you exited your previous Emacs session; any settings for
+those parameters in your init file will be ignored. To disable this,
+customize the value of @code{frameset-filter-alist} to filter out the
+frame parameters you don't want to be restored; they will then be set
+according to your customizations in the init file.
+
+@vindex desktop-files-not-to-save
+ Information about buffers visiting remote files is not saved by
+default. Customize the variable @code{desktop-files-not-to-save} to
+change this.
+
+@vindex desktop-restore-eager
+ By default, all the buffers in the desktop are restored in one go.
+However, this may be slow if there are a lot of buffers in the
+desktop. You can specify the maximum number of buffers to restore
+immediately with the variable @code{desktop-restore-eager}; the
+remaining buffers are restored lazily, when Emacs is idle.
+
+@findex desktop-clear
+@vindex desktop-globals-to-clear
+@vindex desktop-clear-preserve-buffers-regexp
+ Type @kbd{M-x desktop-clear} to empty the Emacs desktop; this can be
+useful, for example, if you want to switch to another desktop by
+invoking @kbd{M-x desktop-read} next. The @code{desktop-clear}
+command kills all buffers except for internal ones, and clears the
+global variables listed in @code{desktop-globals-to-clear}. If you
+want it to preserve certain buffers, customize the variable
+@code{desktop-clear-preserve-buffers-regexp}, whose value is a regular
+expression matching the names of buffers not to kill.
+
+ If you want to save minibuffer history from one session to
+another, use the @code{savehist} library.
+
@node Recursive Edit
@section Recursive Editing Levels
@cindex recursive editing level
diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi
index 3a8eddb93ea..f5572e447d3 100644
--- a/doc/lispref/functions.texi
+++ b/doc/lispref/functions.texi
@@ -685,6 +685,20 @@ Here are some examples:
@end group
@end example
+@cindex defining functions dynamically
+Most Emacs functions are part of the source code of Lisp programs, and
+are defined when the Emacs Lisp reader reads the program source before
+executing it. However, you can also define functions dynamically at
+run time, e.g., by generating @code{defun} calls when your program's
+code is executed. If you do this, be aware that Emacs's Help
+commands, such as @kbd{C-h f}, which present in the @file{*Help*}
+buffer a button to jump to the function's definition, might be unable
+to find the source code because generating a function dynamically
+usually looks very different from the usual static calls to
+@code{defun}. You can make the job of finding the code which
+generates such functions easier by using the @code{definition-name}
+property, @pxref{Standard Properties}.
+
@cindex override existing functions
@cindex redefine existing functions
Be careful not to redefine existing functions unintentionally.
diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi
index de5ed76c7f7..59b6b6dab1d 100644
--- a/doc/lispref/help.texi
+++ b/doc/lispref/help.texi
@@ -69,14 +69,14 @@ Variables}. The string is stored in the variable's
@cindex @file{DOC} (documentation) file
Sometimes, Emacs does not keep documentation strings in memory.
There are two such circumstances. Firstly, to save memory, the
-documentation for preloaded functions and variables (including
-primitives) is kept in a file named @file{DOC}, in the directory
-specified by @code{doc-directory} (@pxref{Accessing Documentation}).
-Secondly, when a function or variable is loaded from a byte-compiled
-file, Emacs avoids loading its documentation string (@pxref{Docs and
-Compilation}). In both cases, Emacs looks up the documentation string
-from the file only when needed, such as when the user calls @kbd{C-h
-f} (@code{describe-function}) for a function.
+documentation for primitive functions (@pxref{What Is a Function}) and
+built-in variables is kept in a file named @file{DOC}, in the
+directory specified by @code{doc-directory} (@pxref{Accessing
+Documentation}). Secondly, when a function or variable is loaded from
+a byte-compiled file, Emacs avoids loading its documentation string
+(@pxref{Docs and Compilation}). In both cases, Emacs looks up the
+documentation string from the file only when needed, such as when the
+user calls @kbd{C-h f} (@code{describe-function}) for a function.
Documentation strings can contain special @dfn{key substitution
sequences}, referring to key bindings which are looked up only when
@@ -303,7 +303,7 @@ for in the directory @code{doc-directory}. Usually @var{filename} is
@defvar doc-directory
This variable holds the name of the directory which should contain the
file @code{"DOC"} that contains documentation strings for
-built-in and preloaded functions and variables.
+built-in functions and variables.
In most cases, this is the same as @code{data-directory}. They may be
different when you run Emacs from the directory where you built it,
diff --git a/doc/lispref/modes.texi b/doc/lispref/modes.texi
index b2dd294ea28..ff372edb3ff 100644
--- a/doc/lispref/modes.texi
+++ b/doc/lispref/modes.texi
@@ -4936,10 +4936,10 @@ Each @var{matcher} or @var{anchor} is a function that takes three
arguments: @var{node}, @var{parent}, and @var{bol}. The argument
@var{bol} is the buffer position whose indentation is required: the
position of the first non-whitespace character after the beginning of
-the line. The argument @var{node} is the largest (highest-in-tree)
-node that starts at that position; and @var{parent} is the parent of
-@var{node}. However, when that position is in a whitespace or inside
-a multi-line string, no node can start at that position, so
+the line. The argument @var{node} is the largest node that starts at
+that position (and is not a root node); and @var{parent} is the parent
+of @var{node}. However, when that position is in a whitespace or
+inside a multi-line string, no node can start at that position, so
@var{node} is @code{nil}. In that case, @var{parent} would be the
smallest node that spans that position.
diff --git a/doc/lispref/parsing.texi b/doc/lispref/parsing.texi
index 9635427f940..b55af912f9b 100644
--- a/doc/lispref/parsing.texi
+++ b/doc/lispref/parsing.texi
@@ -540,11 +540,15 @@ This function returns the list of @var{parser}'s notifier functions.
Here's some terminology and conventions we use when documenting
tree-sitter functions.
-We talk about a node being ``smaller'' or ``larger'', and ``lower'' or
-``higher''. A smaller and lower node is lower in the syntax tree and
-therefore spans a smaller portion of buffer text; a larger and higher
-node is higher up in the syntax tree, it contains many smaller nodes
-as its children, and therefore spans a larger portion of text.
+A node in a syntax tree spans some portion of the program text in the
+buffer. We say that a node is ``smaller'' or ``larger'' than another
+if it spans, respectively, a smaller or larger portion of buffer text
+than the other node. Since nodes that are deeper (``lower'') in the
+tree are children of the nodes that are ``higher'' in the tree, it
+follows that a lower node will always be smaller than a node that is
+higher in the node hierarchy. A node that is higher up in the syntax
+tree contains one or more smaller nodes as its children, and therefore
+spans a larger portion of buffer text.
When a function cannot find a node, it returns @code{nil}. For
convenience, all functions that take a node as argument and return
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi
index 183367c0cda..5b53cbe310a 100644
--- a/doc/lispref/symbols.texi
+++ b/doc/lispref/symbols.texi
@@ -555,6 +555,23 @@ value, saved value, customized-but-unsaved value, and themed values.
Do not set them directly; they are managed by @code{defcustom} and
related functions. @xref{Variable Definitions}.
+@item definition-name
+This property is used to find the definition of a symbol in the source
+code, when it might be hard to find the definition by textual search
+of the source file. For example, a @code{define-derived-mode}
+(@pxref{Derived Modes}) might define a mode-specific function or a
+variable implicitly; or your Lisp program might generate a run-time
+call to @code{defun} to define a function (@pxref{Defining
+Functions}). In these and similar cases, the @code{definition-name}
+property of the symbol should be another symbol whose definition can
+be found by textual search and whose code defines the original symbol.
+In the example with @code{define-derived-mode}, the value of this
+property of the functions and variables it defines should be the mode
+symbol. The Emacs Help commands such as @kbd{C-h f} (@pxref{Help,,,
+emacs, The GNU Emacs Manual}) use this property to show the definition
+of a symbol via a button in the @file{*Help*} buffer where the
+symbol's documentation is shown.
+
@item disabled
If the value is non-@code{nil}, the named function is disabled as a
command. @xref{Disabling Commands}.
diff --git a/doc/misc/org.org b/doc/misc/org.org
index ed3eb0626f2..7ca2cce9e7f 100644
--- a/doc/misc/org.org
+++ b/doc/misc/org.org
@@ -1249,11 +1249,12 @@ After the drawer.
#+findex: org-insert-drawer
You can interactively insert a drawer at point by calling
~org-insert-drawer~, which is bound to {{{kbd(C-c C-x d)}}}. With an
-active region, this command puts the region inside the drawer. With
-a prefix argument, this command calls ~org-insert-property-drawer~,
-which creates a =PROPERTIES= drawer right below the current headline.
-Org mode uses this special drawer for storing properties (see
-[[*Properties and Columns]]). You cannot use it for anything else.
+active region, this command puts the region inside the drawer. With a
+prefix argument, this command calls non-interactive function
+~org-insert-property-drawer~, which creates a =PROPERTIES= drawer
+right below the current headline. Org mode uses this special drawer
+for storing properties (see [[*Properties and Columns]]). You cannot use
+it for anything else.
Completion over drawer keywords is also possible using
{{{kbd(M-TAB)}}}[fn:6].
diff --git a/etc/NEWS.29 b/etc/NEWS.29
index 5901b2718e9..a28f5c9a65a 100644
--- a/etc/NEWS.29
+++ b/etc/NEWS.29
@@ -797,10 +797,10 @@ filter/sentinel error has been handled.
** New faces for font-lock.
These faces are primarily meant for use with tree-sitter. They are:
'font-lock-bracket-face', 'font-lock-delimiter-face',
-'font-lock-escape-face', 'font-lock-number-face',
-'font-lock-regexp-face',
-'font-lock-misc-punctuation-face', 'font-lock-operator-face',
-'font-lock-property-face', and 'font-lock-punctuation-face'.
+'font-lock-escape-face', 'font-lock-misc-punctuation-face',
+'font-lock-number-face', 'font-lock-operator-face',
+'font-lock-property-face', and 'font-lock-punctuation-face',
+'font-lock-regexp-face'.
+++
** New face 'variable-pitch-text'.
diff --git a/lisp/align.el b/lisp/align.el
index 569186d241d..79a75dcec79 100644
--- a/lisp/align.el
+++ b/lisp/align.el
@@ -179,7 +179,8 @@ If nil, then no messages will ever be printed to the minibuffer."
:type '(choice (const :tag "Align a large region silently" nil) integer)
:group 'align)
-(defcustom align-c++-modes '(c++-mode c-mode java-mode)
+(defcustom align-c++-modes '( c++-mode c-mode java-mode
+ c-ts-mode c++-ts-mode)
"A list of modes whose syntax resembles C/C++."
:type '(repeat symbol)
:group 'align)
diff --git a/lisp/font-lock.el b/lisp/font-lock.el
index 99df8fb9e06..1fa45379b9f 100644
--- a/lisp/font-lock.el
+++ b/lisp/font-lock.el
@@ -1183,7 +1183,7 @@ This function is the default `font-lock-fontify-region-function'."
(setq font-lock-syntactically-fontified end))
(font-lock-fontify-syntactic-keywords-region start end)))
(unless font-lock-keywords-only
- (funcall font-lock-fontify-syntactically-function beg end loudly))
+ (font-lock-fontify-syntactically-region beg end loudly))
(font-lock-fontify-keywords-region beg end loudly)
`(jit-lock-bounds ,beg . ,end))))
@@ -1531,6 +1531,12 @@ START should be at the beginning of a line."
(defvar font-lock-comment-end-skip nil
"If non-nil, Font Lock mode uses this instead of `comment-end-skip'.")
+(defun font-lock-fontify-syntactically-region (beg end &optional loudly)
+ "Syntactically fontify the text between BEG and END.
+If LOUDLY is non-nil, print status messages while fontifying.
+This works by calling `font-lock-fontify-syntactically-function'."
+ (funcall font-lock-fontify-syntactically-function beg end loudly))
+
(defun font-lock-default-fontify-syntactically (start end &optional loudly)
"Put proper face on each string and comment between START and END.
START should be at the beginning of a line."
@@ -2369,7 +2375,6 @@ in which C preprocessor directives are used, e.g. `asm-mode' and
(define-obsolete-function-alias 'font-lock-after-fontify-buffer #'ignore "29.1")
(define-obsolete-function-alias 'font-lock-after-unfontify-buffer #'ignore "29.1")
-(define-obsolete-function-alias 'font-lock-fontify-syntactically-region #'font-lock-default-fontify-syntactically "29.1")
(provide 'font-lock)
diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el
index 9bb77f7920b..93cdf6ae868 100644
--- a/lisp/org/ob-core.el
+++ b/lisp/org/ob-core.el
@@ -1690,6 +1690,7 @@ shown below.
(append
(split-string (if (stringp raw-result)
raw-result
+ ;; FIXME: Arbitrary code evaluation.
(eval raw-result t)))
(cdr (assq :result-params params))))))
(append
@@ -2860,6 +2861,7 @@ parameters when merging lists."
(split-string
(cond ((stringp value) value)
((functionp value) (funcall value))
+ ;; FIXME: Arbitrary code evaluation.
(t (eval value t)))))))
(`(:exports . ,value)
(setq exports (funcall merge
@@ -3188,16 +3190,8 @@ situations in which is it not appropriate."
((and (not inhibit-lisp-eval)
(or (memq (string-to-char cell) '(?\( ?' ?` ?\[))
(string= cell "*this*")))
- ;; Prevent arbitrary function calls.
- (if (and (memq (string-to-char cell) '(?\( ?`))
- (not (org-babel-confirm-evaluate
- ;; See `org-babel-get-src-block-info'.
- (list "emacs-lisp" cell
- '((:eval . yes)) nil (format "%s" cell)
- nil nil))))
- ;; Not allowed.
- (user-error "Evaluation of elisp code %S aborted." cell)
- (eval (read cell) t)))
+ ;; FIXME: Arbitrary code evaluation.
+ (eval (read cell) t))
((save-match-data
(and (string-match "^[[:space:]]*\"\\(.*\\)\"[[:space:]]*$" cell)
(not (string-match "[^\\]\"" (match-string 1 cell)))))
diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el
index 4a60186cd5d..2c30a26056b 100644
--- a/lisp/org/ob-shell.el
+++ b/lisp/org/ob-shell.el
@@ -79,7 +79,7 @@ is modified outside the Customize interface."
,(format "Execute a block of %s commands with Babel." name)
(let ((shell-file-name ,name)
(org-babel-prompt-command
- (or (alist-get ,name org-babel-shell-set-prompt-commands)
+ (or (cdr (assoc ,name org-babel-shell-set-prompt-commands))
(alist-get t org-babel-shell-set-prompt-commands))))
(org-babel-execute:shell body params))))
(eval `(defalias ',(intern (concat "org-babel-variable-assignments:" name))
diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el
index 72929cdd26c..07c668a807d 100644
--- a/lisp/org/org-macs.el
+++ b/lisp/org/org-macs.el
@@ -372,18 +372,23 @@ be set to a buffer or a buffer name. `shell-command' then uses
it for output."
(let* ((base-name (file-name-base source))
(full-name (file-truename source))
- (out-dir (or (file-name-directory source) "./"))
+ (relative-name (file-relative-name source))
+ (out-dir (if (file-name-directory source)
+ ;; Expand "~". Shell expansion will be disabled
+ ;; in the shell command call.
+ (file-name-directory full-name)
+ "./"))
(output (expand-file-name (concat base-name "." ext) out-dir))
(time (file-attribute-modification-time (file-attributes output)))
(err-msg (if (stringp err-msg) (concat ". " err-msg) "")))
(save-window-excursion
(pcase process
- ((pred functionp) (funcall process (shell-quote-argument source)))
+ ((pred functionp) (funcall process (shell-quote-argument relative-name)))
((pred consp)
(let ((log-buf (and log-buf (get-buffer-create log-buf)))
(spec (append spec
`((?b . ,(shell-quote-argument base-name))
- (?f . ,(shell-quote-argument source))
+ (?f . ,(shell-quote-argument relative-name))
(?F . ,(shell-quote-argument full-name))
(?o . ,(shell-quote-argument out-dir))
(?O . ,(shell-quote-argument output))))))
diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el
index c3650c167e2..336496efbfb 100644
--- a/lisp/org/org-persist.el
+++ b/lisp/org/org-persist.el
@@ -753,12 +753,12 @@ with `org-persist-write'."
When ASSOCIATED is `all', unregister CONTAINER everywhere."
(unless org-persist--index (org-persist--load-index))
(setq container (org-persist--normalize-container container))
- (setq associated (org-persist--normalize-associated associated))
(if (eq associated 'all)
(mapc (lambda (collection)
(when (member container (plist-get collection :container))
(org-persist-unregister container (plist-get collection :associated))))
org-persist--index)
+ (setq associated (org-persist--normalize-associated associated))
(let ((collection (org-persist--find-index `(:container ,container :associated ,associated))))
(when collection
(if (= (length (plist-get collection :container)) 1)
diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el
index 06cf919db76..fac9e68c124 100644
--- a/lisp/org/org-table.el
+++ b/lisp/org/org-table.el
@@ -2614,6 +2614,7 @@ location of point."
(if lispp
(setq ev (condition-case nil
+ ;; FIXME: Arbitrary code evaluation.
(eval (eval (read form)))
(error "#ERROR"))
ev (if (numberp ev) (number-to-string ev) ev)
diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el
index dd6d92d8e58..942cc4eae8b 100644
--- a/lisp/org/org-version.el
+++ b/lisp/org/org-version.el
@@ -11,7 +11,7 @@ Inserted by installing Org mode or when a release is made."
(defun org-git-version ()
"The Git version of Org mode.
Inserted by installing Org or when a release is made."
- (let ((org-git-version "release_9.6-81-g563a43"))
+ (let ((org-git-version "release_9.6-90-ga6523f"))
org-git-version))
(provide 'org-version)
diff --git a/lisp/org/org.el b/lisp/org/org.el
index 21764f3d434..8d226c2c5ab 100644
--- a/lisp/org/org.el
+++ b/lisp/org/org.el
@@ -4898,16 +4898,20 @@ The following commands are available:
(= (point-min) (point-max)))
(insert "# -*- mode: org -*-\n\n"))
(unless org-inhibit-startup
+ (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
+ (org-table-map-tables
+ (cond ((and org-startup-align-all-tables
+ org-startup-shrink-all-tables)
+ (lambda () (org-table-align) (org-table-shrink)))
+ (org-startup-align-all-tables #'org-table-align)
+ (t #'org-table-shrink))
+ t))
+ ;; Suppress modification hooks to speed up the startup.
+ ;; However, do it only when text properties/overlays, but not
+ ;; buffer text are actually modified. We still need to track text
+ ;; modifications to make cache updates work reliably.
(org-unmodified
(when org-startup-with-beamer-mode (org-beamer-mode))
- (when (or org-startup-align-all-tables org-startup-shrink-all-tables)
- (org-table-map-tables
- (cond ((and org-startup-align-all-tables
- org-startup-shrink-all-tables)
- (lambda () (org-table-align) (org-table-shrink)))
- (org-startup-align-all-tables #'org-table-align)
- (t #'org-table-shrink))
- t))
(when org-startup-with-inline-images (org-display-inline-images))
(when org-startup-with-latex-preview (org-latex-preview '(16)))
(unless org-inhibit-startup-visibility-stuff (org-cycle-set-startup-visibility))
@@ -8855,7 +8859,7 @@ keywords relative to each registered export back-end."
"EXCLUDE_TAGS:" "FILETAGS:" "INCLUDE:" "INDEX:" "KEYWORDS:" "LANGUAGE:"
"MACRO:" "OPTIONS:" "PROPERTY:" "PRINT_BIBLIOGRAPHY" "PRIORITIES:"
"SELECT_TAGS:" "SEQ_TODO:" "SETUPFILE:" "STARTUP:" "TAGS:" "TITLE:" "TODO:"
- "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:"))
+ "TYP_TODO:" "SELECT_TAGS:" "EXCLUDE_TAGS:" "EXPORT_FILE_NAME:"))
(defcustom org-structure-template-alist
'(("a" . "export ascii")
diff --git a/lisp/org/ox.el b/lisp/org/ox.el
index 62fc8d583e4..12767267a71 100644
--- a/lisp/org/ox.el
+++ b/lisp/org/ox.el
@@ -6757,7 +6757,6 @@ Return file name as a string."
(cond
(pub-dir (concat (file-name-as-directory pub-dir)
(file-name-nondirectory base-name)))
- ((file-name-absolute-p base-name) base-name)
(t base-name))))
;; If writing to OUTPUT-FILE would overwrite original file, append
;; EXTENSION another time to final name.
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index e76966e7660..e929fe1dd81 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -122,9 +122,13 @@ MODE is either `c' or `cpp'."
((node-is "else") parent-bol 0)
((node-is "case") parent-bol 0)
((node-is "preproc_arg") no-indent)
+ (c-ts-mode--comment-2nd-line-matcher
+ c-ts-mode--comment-2nd-line-anchor
+ 1)
((and (parent-is "comment") c-ts-mode--looking-at-star)
c-ts-mode--comment-start-after-first-star -1)
((parent-is "comment") prev-adaptive-prefix 0)
+ (c-ts-mode--top-level-label-matcher point-min 1)
((node-is "labeled_statement") parent-bol 0)
((parent-is "labeled_statement") parent-bol c-ts-mode-indent-offset)
((match "preproc_ifdef" "compound_statement") point-min 0)
@@ -138,6 +142,7 @@ MODE is either `c' or `cpp'."
((parent-is "function_definition") parent-bol 0)
((parent-is "conditional_expression") first-sibling 0)
((parent-is "assignment_expression") parent-bol c-ts-mode-indent-offset)
+ ((parent-is "concatenated_string") parent-bol c-ts-mode-indent-offset)
((parent-is "comma_expression") first-sibling 0)
((parent-is "init_declarator") parent-bol c-ts-mode-indent-offset)
((parent-is "parenthesized_expression") first-sibling 1)
@@ -151,7 +156,9 @@ MODE is either `c' or `cpp'."
((parent-is "call_expression") parent 0)
((parent-is "enumerator_list") parent-bol c-ts-mode-indent-offset)
,@(when (eq mode 'cpp)
- '(((node-is "access_specifier") parent-bol 0)))
+ '(((node-is "access_specifier") parent-bol 0)
+ ;; Indent the body of namespace definitions.
+ ((parent-is "declaration_list") parent-bol c-ts-mode-indent-offset)))
((parent-is "field_declaration_list") parent-bol c-ts-mode-indent-offset)
((parent-is "initializer_list") parent-bol c-ts-mode-indent-offset)
((parent-is "if_statement") parent-bol c-ts-mode-indent-offset)
@@ -167,7 +174,12 @@ MODE is either `c' or `cpp'."
((match "while" "do_statement") parent 0)
,@common)
(k&r ,@common)
- (linux ,@common)
+ (linux
+ ;; Reference:
+ ;; https://www.kernel.org/doc/html/latest/process/coding-style.html,
+ ;; and script/Lindent in Linux kernel repository.
+ ((node-is "labeled_statement") point-min 0)
+ ,@common)
(bsd
((parent-is "if_statement") parent-bol 0)
((parent-is "for_statement") parent-bol 0)
@@ -190,6 +202,17 @@ MODE is either `c' or `cpp'."
('linux (alist-get 'linux (c-ts-mode--indent-styles mode)))))))
`((,mode ,@style))))
+(defun c-ts-mode--top-level-label-matcher (node &rest _)
+ "A matcher that matches a top-level label.
+NODE should be a labeled_statement."
+ (let ((func (treesit-parent-until
+ node (lambda (n)
+ (equal (treesit-node-type n)
+ "function_definition")))))
+ (and (equal (treesit-node-type node)
+ "labeled_statement")
+ (not (treesit-node-top-level func "function_definition")))))
+
(defun c-ts-mode--bracket-children-anchor (_n parent &rest _)
"This anchor is used for children of a compound_statement.
So anything inside a {} block. PARENT should be the
@@ -205,11 +228,10 @@ beginning of grandparent."
(treesit-node-parent parent)
parent)))))
-(defun c-ts-mode--looking-at-star (&rest _)
+(defun c-ts-mode--looking-at-star (_n _p bol &rest _)
"A tree-sitter simple indent matcher.
-Matches if there is a \"*\" after point (ignoring whitespace in
-between)."
- (looking-at (rx (* (syntax whitespace)) "*")))
+Matches if there is a \"*\" after BOL."
+ (eq (char-after bol) ?*))
(defun c-ts-mode--comment-start-after-first-star (_n parent &rest _)
"A tree-sitter simple indent anchor.
@@ -221,6 +243,35 @@ Assumes PARENT is a comment node."
(match-end 0)
(point))))
+(defun c-ts-mode--comment-2nd-line-matcher (_n parent &rest _)
+ "Matches if point is at the second line of a block comment.
+PARENT should be a comment node."
+ (and (equal (treesit-node-type parent) "comment")
+ (save-excursion
+ (forward-line -1)
+ (back-to-indentation)
+ (eq (point) (treesit-node-start parent)))))
+
+(defun c-ts-mode--comment-2nd-line-anchor (&rest _)
+ "Return appropriate anchor for the second line of a comment.
+
+If the first line is /* alone, return the position right after
+the star; if the first line is /* followed by some text, return
+the position right before the text minus 1.
+
+Use an offset of 1 with this anchor."
+ (save-excursion
+ (forward-line -1)
+ (back-to-indentation)
+ (when (looking-at comment-start-skip)
+ (goto-char (match-end 0))
+ (if (looking-at (rx (* (or " " "\t")) eol))
+ ;; Only /* at the first line.
+ (progn (skip-chars-backward " \t")
+ (point))
+ ;; There is something after /* at the first line.
+ (1- (point))))))
+
;;; Font-lock
(defvar c-ts-mode--preproc-keywords
@@ -419,20 +470,29 @@ MODE is either `c' or `cpp'."
;;; Font-lock helpers
-(defun c-ts-mode--declarator-identifier (node)
- "Return the identifier of the declarator node NODE."
+(defun c-ts-mode--declarator-identifier (node &optional qualified)
+ "Return the identifier of the declarator node NODE.
+
+If QUALIFIED is non-nil, include the names space part of the
+identifier and return a qualified_identifier."
(pcase (treesit-node-type node)
;; Recurse.
((or "attributed_declarator" "parenthesized_declarator")
- (c-ts-mode--declarator-identifier (treesit-node-child node 0 t)))
+ (c-ts-mode--declarator-identifier (treesit-node-child node 0 t)
+ qualified))
((or "pointer_declarator" "reference_declarator")
- (c-ts-mode--declarator-identifier (treesit-node-child node -1)))
+ (c-ts-mode--declarator-identifier (treesit-node-child node -1)
+ qualified))
((or "function_declarator" "array_declarator" "init_declarator")
(c-ts-mode--declarator-identifier
- (treesit-node-child-by-field-name node "declarator")))
+ (treesit-node-child-by-field-name node "declarator")
+ qualified))
("qualified_identifier"
- (c-ts-mode--declarator-identifier
- (treesit-node-child-by-field-name node "name")))
+ (if qualified
+ node
+ (c-ts-mode--declarator-identifier
+ (treesit-node-child-by-field-name node "name")
+ qualified)))
;; Terminal case.
((or "identifier" "field_identifier")
node)))
@@ -534,9 +594,11 @@ Return nil if NODE is not a defun node or doesn't have a name."
(pcase (treesit-node-type node)
((or "function_definition" "declaration")
(c-ts-mode--declarator-identifier
- (treesit-node-child-by-field-name node "declarator")))
+ (treesit-node-child-by-field-name node "declarator")
+ t))
((or "struct_specifier" "enum_specifier"
- "union_specifier" "class_specifier")
+ "union_specifier" "class_specifier"
+ "namespace_definition")
(treesit-node-child-by-field-name node "name")))
t))
@@ -568,6 +630,23 @@ Ie, NODE is not nested."
node "declarator"))
"function_declarator")))))
+(defun c-ts-mode--defun-for-class-in-imenu-p (node)
+ "Check if NODE is a valid entry for the Class subindex.
+
+Basically, if NODE is a class, return non-nil; if NODE is a
+function but is under a class, return non-nil; if NODE is a
+top-level function, return nil.
+
+This is for the Class subindex in
+`treesit-simple-imenu-settings'."
+ (pcase (treesit-node-type node)
+ ;; The Class subindex only has class_specifier and
+ ;; function_definition.
+ ("class_specifier" t)
+ ("function_definition"
+ ;; Return t if this function is nested in a class.
+ (treesit-node-top-level node "class_specifier"))))
+
(defun c-ts-mode--defun-skipper ()
"Custom defun skipper for `c-ts-mode' and friends.
Structs in C ends with a semicolon, but the semicolon is not
@@ -741,7 +820,8 @@ Set up:
"struct_specifier"
"enum_specifier"
"union_specifier"
- "class_specifier"))
+ "class_specifier"
+ "namespace_definition"))
#'c-ts-mode--defun-valid-p))
(setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
(setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
@@ -772,7 +852,7 @@ Set up:
("Class" ,(rx bos (or "class_specifier"
"function_definition")
eos)
- ,pred nil))))
+ c-ts-mode--defun-for-class-in-imenu-p nil))))
(setq-local treesit-font-lock-feature-list
'(( comment definition)
@@ -782,49 +862,49 @@ Set up:
;;;###autoload
(define-derived-mode c-ts-mode c-ts-base-mode "C"
- "Major mode for editing C, powered by tree-sitter."
- :group 'c
-
- (unless (treesit-ready-p 'c)
- (error "Tree-sitter for C isn't available"))
-
- (treesit-parser-create 'c)
-
- ;; Comments.
- (setq-local comment-start "/* ")
- (setq-local comment-end " */")
-
- (setq-local treesit-simple-indent-rules
- (c-ts-mode--set-indent-style 'c))
+ "Major mode for editing C, powered by tree-sitter.
- ;; Font-lock.
- (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
+This mode is independent from the classic cc-mode.el based
+`c-mode', so configuration variables of that mode, like
+`c-basic-offset', don't affect this mode."
+ :group 'c
- (treesit-major-mode-setup))
+ (when (treesit-ready-p 'c)
+ (treesit-parser-create 'c)
+ ;; Comments.
+ (setq-local comment-start "/* ")
+ (setq-local comment-end " */")
+ ;; Indent.
+ (setq-local treesit-simple-indent-rules
+ (c-ts-mode--set-indent-style 'c))
+ ;; Font-lock.
+ (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'c))
+ (treesit-major-mode-setup)))
;;;###autoload
(define-derived-mode c++-ts-mode c-ts-base-mode "C++"
"Major mode for editing C++, powered by tree-sitter."
:group 'c++
- (unless (treesit-ready-p 'cpp)
- (error "Tree-sitter for C++ isn't available"))
+ (when (treesit-ready-p 'cpp)
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "raw_string_literal")))
- (setq-local treesit-text-type-regexp
- (regexp-opt '("comment"
- "raw_string_literal")))
+ (treesit-parser-create 'cpp)
- (treesit-parser-create 'cpp)
- (setq-local syntax-propertize-function
- #'c-ts-mode--syntax-propertize)
+ ;; Syntax.
+ (setq-local syntax-propertize-function
+ #'c-ts-mode--syntax-propertize)
- (setq-local treesit-simple-indent-rules
- (c-ts-mode--set-indent-style 'cpp))
+ ;; Indent.
+ (setq-local treesit-simple-indent-rules
+ (c-ts-mode--set-indent-style 'cpp))
- ;; Font-lock.
- (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp))
+ ;; Font-lock.
+ (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings 'cpp))
- (treesit-major-mode-setup))
+ (treesit-major-mode-setup)))
(provide 'c-ts-mode)
diff --git a/lisp/progmodes/go-ts-mode.el b/lisp/progmodes/go-ts-mode.el
index 1d6a8a30db5..64e761d2f72 100644
--- a/lisp/progmodes/go-ts-mode.el
+++ b/lisp/progmodes/go-ts-mode.el
@@ -36,6 +36,7 @@
(declare-function treesit-node-child-by-field-name "treesit.c")
(declare-function treesit-node-start "treesit.c")
(declare-function treesit-node-type "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
(defcustom go-ts-mode-indent-offset 4
"Number of spaces for each indentation step in `go-ts-mode'."
@@ -173,44 +174,6 @@
'((ERROR) @font-lock-warning-face))
"Tree-sitter font-lock settings for `go-ts-mode'.")
-(defun go-ts-mode--imenu ()
- "Return Imenu alist for the current buffer."
- (let* ((node (treesit-buffer-root-node))
- (func-tree (treesit-induce-sparse-tree
- node "function_declaration" nil 1000))
- (type-tree (treesit-induce-sparse-tree
- node "type_spec" nil 1000))
- (func-index (go-ts-mode--imenu-1 func-tree))
- (type-index (go-ts-mode--imenu-1 type-tree)))
- (append
- (when func-index `(("Function" . ,func-index)))
- (when type-index `(("Type" . ,type-index))))))
-
-(defun go-ts-mode--imenu-1 (node)
- "Helper for `go-ts-mode--imenu'.
-Find string representation for NODE and set marker, then recurse
-the subtrees."
- (let* ((ts-node (car node))
- (children (cdr node))
- (subtrees (mapcan #'go-ts-mode--imenu-1
- children))
- (name (when ts-node
- (treesit-node-text
- (pcase (treesit-node-type ts-node)
- ("function_declaration"
- (treesit-node-child-by-field-name ts-node "name"))
- ("type_spec"
- (treesit-node-child-by-field-name ts-node "name"))))))
- (marker (when ts-node
- (set-marker (make-marker)
- (treesit-node-start ts-node)))))
- (cond
- ((or (null ts-node) (null name)) subtrees)
- (subtrees
- `((,name ,(cons name marker) ,@subtrees)))
- (t
- `((,name . ,marker))))))
-
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.go\\'" . go-ts-mode))
@@ -228,14 +191,30 @@ the subtrees."
(setq-local comment-end "")
(setq-local comment-start-skip (rx "//" (* (syntax whitespace))))
+ ;; Navigation.
+ (setq-local treesit-defun-type-regexp
+ (regexp-opt '("method_declaration"
+ "function_declaration"
+ "type_declaration")))
+ (setq-local treesit-defun-name-function #'go-ts-mode--defun-name)
+
;; Imenu.
- (setq-local imenu-create-index-function #'go-ts-mode--imenu)
- (setq-local which-func-functions nil)
+ (setq-local treesit-simple-imenu-settings
+ `(("Function" "\\`function_declaration\\'" nil nil)
+ ("Method" "\\`method_declaration\\'" nil nil)
+ ("Struct" "\\`type_declaration\\'" go-ts-mode--struct-node-p nil)
+ ("Interface" "\\`type_declaration\\'" go-ts-mode--interface-node-p nil)
+ ("Type" "\\`type_declaration\\'" go-ts-mode--other-type-node-p nil)
+ ("Alias" "\\`type_declaration\\'" go-ts-mode--alias-node-p nil)))
;; Indent.
(setq-local indent-tabs-mode t
treesit-simple-indent-rules go-ts-mode--indent-rules)
+ ;; Electric
+ (setq-local electric-indent-chars
+ (append "{}()" electric-indent-chars))
+
;; Font-lock.
(setq-local treesit-font-lock-settings go-ts-mode--font-lock-settings)
(setq-local treesit-font-lock-feature-list
@@ -247,6 +226,54 @@ the subtrees."
(treesit-major-mode-setup)))
+(defun go-ts-mode--defun-name (node)
+ "Return the defun name of NODE.
+Return nil if there is no name or if NODE is not a defun node."
+ (pcase (treesit-node-type node)
+ ("function_declaration"
+ (treesit-node-text
+ (treesit-node-child-by-field-name
+ node "name")
+ t))
+ ("method_declaration"
+ (let* ((receiver-node (treesit-node-child-by-field-name node "receiver"))
+ (type-node (treesit-search-subtree receiver-node "type_identifier"))
+ (name-node (treesit-node-child-by-field-name node "name")))
+ (concat
+ "(" (treesit-node-text type-node) ")."
+ (treesit-node-text name-node))))
+ ("type_declaration"
+ (treesit-node-text
+ (treesit-node-child-by-field-name
+ (treesit-node-child node 0 t) "name")
+ t))))
+
+(defun go-ts-mode--interface-node-p (node)
+ "Return t if NODE is an interface."
+ (and
+ (string-equal "type_declaration" (treesit-node-type node))
+ (treesit-search-subtree node "interface_type" nil nil 2)))
+
+(defun go-ts-mode--struct-node-p (node)
+ "Return t if NODE is a struct."
+ (and
+ (string-equal "type_declaration" (treesit-node-type node))
+ (treesit-search-subtree node "struct_type" nil nil 2)))
+
+(defun go-ts-mode--alias-node-p (node)
+ "Return t if NODE is a type alias."
+ (and
+ (string-equal "type_declaration" (treesit-node-type node))
+ (treesit-search-subtree node "type_alias" nil nil 1)))
+
+(defun go-ts-mode--other-type-node-p (node)
+ "Return t if NODE is a type, other than interface, struct or alias."
+ (and
+ (string-equal "type_declaration" (treesit-node-type node))
+ (not (go-ts-mode--interface-node-p node))
+ (not (go-ts-mode--struct-node-p node))
+ (not (go-ts-mode--alias-node-p node))))
+
;; go.mod support.
(defvar go-mod-ts-mode--syntax-table
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 20692d6c8df..92e018aaec1 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -3561,8 +3561,9 @@ Treats actions as defuns."
(kill-local-variable 'gdb-define-alist)
(remove-hook 'after-save-hook #'gdb-create-define-alist t))))
-(defcustom gud-tooltip-modes '(gud-mode c-mode c++-mode fortran-mode
- python-mode)
+(defcustom gud-tooltip-modes '( gud-mode c-mode c++-mode fortran-mode
+ python-mode c-ts-mode c++-ts-mode
+ python-ts-mode)
"List of modes for which to enable GUD tooltips."
:type '(repeat (symbol :tag "Major mode"))
:group 'tooltip)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 881f4a83b17..902d4fa7ab3 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3542,7 +3542,10 @@ This function is intended for use in `after-change-functions'."
(identifier)
(identifier)
@font-lock-function-name-face)
- value: (array (number) (function))))
+ value: (array (number) (function)))
+ (import_clause (identifier) @font-lock-variable-name-face)
+ (import_clause (named_imports (import_specifier (identifier))
+ @font-lock-variable-name-face)))
:language 'javascript
:feature 'property
diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el
index 730998727ce..dc87cb8e15d 100644
--- a/lisp/progmodes/project.el
+++ b/lisp/progmodes/project.el
@@ -1,7 +1,7 @@
;;; project.el --- Operations on the current project -*- lexical-binding: t; -*-
;; Copyright (C) 2015-2023 Free Software Foundation, Inc.
-;; Version: 0.9.3
+;; Version: 0.9.4
;; Package-Requires: ((emacs "26.1") (xref "1.4.0"))
;; This is a GNU ELPA :core package. Avoid using functionality that
diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el
index 59164d7d50c..21d16db287c 100644
--- a/lisp/progmodes/python.el
+++ b/lisp/progmodes/python.el
@@ -1067,11 +1067,28 @@ fontified."
"expression_statement"))
'font-lock-doc-face
'font-lock-string-face)))
- (when (eq (char-after string-beg) ?f)
- (cl-incf string-beg))
+ ;; Don't highlight string prefixes like f/r/b.
+ (save-excursion
+ (goto-char string-beg)
+ (when (search-forward "\"" string-end t)
+ (setq string-beg (match-beginning 0))))
(treesit-fontify-with-override
string-beg string-end face override start end)))
+(defun python--treesit-fontify-string-interpolation
+ (node _ start end &rest _)
+ "Fontify string interpolation.
+NODE is the string node. Do not fontify the initial f for
+f-strings. START and END mark the region to be
+fontified."
+ ;; This is kind of a hack, it basically removes the face applied by
+ ;; the string feature, so that following features can apply their
+ ;; face.
+ (let ((n-start (treesit-node-start node))
+ (n-end (treesit-node-end node)))
+ (remove-text-properties
+ (max start n-start) (min end n-end) '(face))))
+
(defvar python--treesit-settings
(treesit-font-lock-rules
:feature 'comment
@@ -1082,10 +1099,12 @@ fontified."
:language 'python
'((string) @python--treesit-fontify-string)
+ ;; HACK: This feature must come after the string feature and before
+ ;; other features. Maybe we should make string-interpolation an
+ ;; option rather than a feature.
:feature 'string-interpolation
:language 'python
- :override t
- '((interpolation (identifier) @font-lock-variable-name-face))
+ '((interpolation) @python--treesit-fontify-string-interpolation)
:feature 'definition
:language 'python
@@ -3766,15 +3785,16 @@ the python shell:
(line-beginning-position)
start))))
(substring (buffer-substring-no-properties start end))
- (starts-at-point-min-p (save-restriction
- (widen)
- (= (point-min) start)))
+ (starts-at-first-line-p (save-restriction
+ (widen)
+ (goto-char start)
+ (= (line-number-at-pos) 1)))
(encoding (python-info-encoding))
(toplevel-p (zerop (save-excursion
(goto-char start)
(python-util-forward-comment 1)
(current-indentation))))
- (fillstr (cond (starts-at-point-min-p
+ (fillstr (cond (starts-at-first-line-p
nil)
((not no-cookie)
(concat
diff --git a/lisp/progmodes/ruby-ts-mode.el b/lisp/progmodes/ruby-ts-mode.el
index 5f5de500435..d68b57966ba 100644
--- a/lisp/progmodes/ruby-ts-mode.el
+++ b/lisp/progmodes/ruby-ts-mode.el
@@ -82,6 +82,16 @@
(require 'ruby-mode)
(declare-function treesit-parser-create "treesit.c")
+(declare-function treesit-induce-sparse-tree "treesit.c")
+(declare-function treesit-node-child-by-field-name "treesit.c")
+(declare-function treesit-search-subtree "treesit.c")
+(declare-function treesit-node-parent "treesit.c")
+(declare-function treesit-node-next-sibling "treesit.c")
+(declare-function treesit-node-type "treesit.c")
+(declare-function treesit-node-child "treesit.c")
+(declare-function treesit-node-end "treesit.c")
+(declare-function treesit-node-start "treesit.c")
+(declare-function treesit-node-string "treesit.c")
(defgroup ruby-ts nil
"Major mode for editing Ruby code."
@@ -304,7 +314,12 @@ values of OVERRIDE"
(array_pattern
(identifier) @font-lock-variable-name-face)
(keyword_pattern
- key: (hash_key_symbol) @font-lock-variable-name-face)
+ value: (identifier) @font-lock-variable-name-face)
+ (keyword_pattern
+ key: (hash_key_symbol) @font-lock-variable-name-face
+ !value)
+ (as_pattern
+ name: (identifier) @font-lock-variable-name-face)
(in_clause
pattern: (identifier) @font-lock-variable-name-face))
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index 0a79ae01248..0786150d906 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -194,7 +194,13 @@ Argument LANGUAGE is either `typescript' or `tsx'."
name: (array_pattern
(identifier)
(identifier) @font-lock-function-name-face)
- value: (array (number) (function))))
+ value: (array (number) (function)))
+
+ (catch_clause
+ parameter: (identifier) @font-lock-variable-name-face)
+
+ (import_clause (identifier) @font-lock-variable-name-face)
+ (import_clause (named_imports (import_specifier (identifier)) @font-lock-variable-name-face)))
:language language
:override t
@@ -223,17 +229,7 @@ Argument LANGUAGE is either `typescript' or `tsx'."
parameters:
[(_ (identifier) @font-lock-variable-name-face)
(_ (_ (identifier) @font-lock-variable-name-face))
- (_ (_ (_ (identifier) @font-lock-variable-name-face)))])
-
- (return_statement (identifier) @font-lock-variable-name-face)
-
- (binary_expression left: (identifier) @font-lock-variable-name-face)
- (binary_expression right: (identifier) @font-lock-variable-name-face)
-
- (arguments (identifier) @font-lock-variable-name-face)
-
- (parenthesized_expression (identifier) @font-lock-variable-name-face)
- (parenthesized_expression (_ (identifier) @font-lock-variable-name-face)))
+ (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
:language language
:override t
@@ -245,8 +241,6 @@ Argument LANGUAGE is either `typescript' or `tsx'."
(pair key: (property_identifier) @font-lock-variable-name-face)
- (pair value: (identifier) @font-lock-variable-name-face)
-
((shorthand_property_identifier) @font-lock-property-face)
((shorthand_property_identifier_pattern)
diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el
index d5cee9fa84f..916d83d407b 100644
--- a/lisp/progmodes/xref.el
+++ b/lisp/progmodes/xref.el
@@ -1,7 +1,7 @@
;;; xref.el --- Cross-referencing commands -*-lexical-binding:t-*-
;; Copyright (C) 2014-2023 Free Software Foundation, Inc.
-;; Version: 1.6.0
+;; Version: 1.6.1
;; Package-Requires: ((emacs "26.1"))
;; This is a GNU ELPA :core package. Avoid functionality that is not
diff --git a/lisp/simple.el b/lisp/simple.el
index c8c5542caee..f5712177234 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2207,15 +2207,39 @@ to get different commands to edit and resubmit."
"Predicate to use to determine which commands to include when completing.
If it's nil, include all the commands.
If it's a function, it will be called with two parameters: the
-symbol of the command and a buffer. The predicate should return
-non-nil if the command should be present when doing \\`M-x TAB'
-in that buffer."
+symbol of the command and the current buffer. The predicate should
+return non-nil if the command should be considered as a completion
+candidate for \\`M-x' in that buffer.
+
+Several predicate functions suitable for various optional behaviors
+are available:
+
+ `command-completion-default-include-p'
+ This excludes from completion candidates those commands
+ which have been marked specific to modes other than the
+ current buffer's mode. Commands that are not specific
+ to any mode are included.
+
+ `command-completion-using-modes-p'
+ This includes in completion candidates only commands
+ marked as specific to the current buffer's mode.
+
+ `command-completion-using-modes-and-keymaps-p'
+ This includes commands marked as specific to the current
+ buffer's modes and commands that have keybindings in the
+ current buffer's active local keymaps. It also includes
+ several commands, like Cuztomize commands, which should
+ always be avaliable."
:version "28.1"
:group 'completion
:type '(choice (const :tag "Don't exclude any commands" nil)
(const :tag "Exclude commands irrelevant to current buffer's mode"
command-completion-default-include-p)
- (function :tag "Other function")))
+ (const :tag "Include only commands relevant to current buffer's mode"
+ command-completion-using-modes-p)
+ (const :tag "Commands relevant to current buffer's mode or bound in its keymaps"
+ command-completion-using-modes-and-keymaps-p)
+ (function :tag "Other predicate function")))
(defun execute-extended-command-cycle ()
"Choose the next version of the extended command predicates.
@@ -2401,6 +2425,35 @@ or (if one of MODES is a minor mode), if it is switched on in BUFFER."
#'eq)
(seq-intersection modes global-minor-modes #'eq)))
+(defun command-completion-using-modes-and-keymaps-p (symbol buffer)
+ "Return non-nil if SYMBOL is marked for BUFFER's mode or bound in its keymaps."
+ (with-current-buffer buffer
+ (let ((keymaps
+ ;; The major mode's keymap and any active minor modes.
+ (nconc
+ (and (current-local-map) (list (current-local-map)))
+ (mapcar
+ #'cdr
+ (seq-filter
+ (lambda (elem)
+ (symbol-value (car elem)))
+ minor-mode-map-alist)))))
+ (or (command-completion-using-modes-p symbol buffer)
+ ;; Include commands that are bound in a keymap in the
+ ;; current buffer.
+ (and (where-is-internal symbol keymaps)
+ ;; But not if they have a command predicate that
+ ;; says that they shouldn't. (This is the case
+ ;; for `ignore' and `undefined' and similar
+ ;; commands commonly found in keymaps.)
+ (or (null (get symbol 'completion-predicate))
+ (funcall (get symbol 'completion-predicate)
+ symbol buffer)))
+ ;; Include customize-* commands (do we need a list of such
+ ;; "always available" commands? customizable?)
+ (string-match-p "customize-" (symbol-name symbol))))))
+
+
(defun command-completion-button-p (category buffer)
"Return non-nil if there's a button of CATEGORY at point in BUFFER."
(with-current-buffer buffer
@@ -2502,7 +2555,11 @@ Also see `suggest-key-bindings'."
(defun execute-extended-command (prefixarg &optional command-name typed)
"Read a command name, then read the arguments and call the command.
To pass a prefix argument to the command you are
-invoking, give a prefix argument to `execute-extended-command'."
+invoking, give a prefix argument to `execute-extended-command'.
+
+This command provides completion when reading the command name.
+Which completion candidates are shown can be controlled by
+customizing `read-extended-command-predicate'."
(declare (interactive-only command-execute))
;; FIXME: Remember the actual text typed by the user before completion,
;; so that we don't later on suggest the same shortening.
diff --git a/lisp/treesit.el b/lisp/treesit.el
index a7f453a8899..25b2c70ce0a 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1143,20 +1143,17 @@ See `treesit-simple-indent-presets'.")
(point))))
(cons 'prev-adaptive-prefix
(lambda (_n parent &rest _)
- (save-excursion
- (re-search-backward
- (rx (not (or " " "\t" "\n"))) nil t)
- (beginning-of-line)
- (and (>= (point) (treesit-node-start parent))
- ;; `adaptive-fill-regexp' will not match "/*",
- ;; so we need to also try `comment-start-skip'.
- (or (and adaptive-fill-regexp
- (looking-at adaptive-fill-regexp)
- (> (- (match-end 0) (match-beginning 0)) 0)
- (match-end 0))
- (and comment-start-skip
- (looking-at comment-start-skip)
- (match-end 0)))))))
+ (let ((comment-start-bol
+ (save-excursion
+ (goto-char (treesit-node-start parent))
+ (line-beginning-position))))
+ (save-excursion
+ (forward-line -1)
+ (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
(lambda (_n parent &rest _)
@@ -1187,9 +1184,12 @@ See `treesit-simple-indent-presets'.")
res))))
(cons 'or (lambda (&rest fns)
(lambda (node parent bol &rest _)
- (seq-find
- (lambda (fn) (funcall fn node parent bol))
- fns))))
+ (let (res)
+ (catch 'break
+ (dolist (fn fns)
+ (setq res (funcall fn node parent bol))
+ (and res (throw 'break t))))
+ res))))
(cons 'not (lambda (fn)
(lambda (node parent bol &rest _)
(not (funcall fn node parent bol)))))
@@ -1338,10 +1338,10 @@ and returns
(ANCHOR . OFFSET).
BOL is the position of the beginning of the line; NODE is the
-\"largest\" node that starts at BOL; PARENT is its parent; ANCHOR
-is a point (not a node), and OFFSET is a number. Emacs finds the
-column of ANCHOR and adds OFFSET to it as the final indentation
-of the current line.")
+\"largest\" node that starts at BOL (and isn't a root node);
+PARENT is its parent; ANCHOR is a point (not a node), and OFFSET
+is a number. Emacs finds the column of ANCHOR and adds OFFSET to
+it as the final indentation of the current line.")
(defun treesit--indent-1 ()
"Indent the current line.
@@ -1359,10 +1359,13 @@ Return (ANCHOR . OFFSET). This function is used by
((treesit-language-at (point))
(treesit-node-at bol (treesit-language-at (point))))
(t (treesit-node-at bol))))
+ (root (treesit-parser-root-node
+ (treesit-node-parser smallest-node)))
(node (treesit-parent-while
smallest-node
(lambda (node)
- (eq bol (treesit-node-start node))))))
+ (and (eq bol (treesit-node-start node))
+ (not (treesit-node-eq node root)))))))
(let*
((parser (if smallest-node
(treesit-node-parser smallest-node)
@@ -2447,11 +2450,15 @@ in the region."
(window-start) (window-end) treesit--explorer-language))
;; Only highlight the current top-level construct.
;; Highlighting the whole buffer is slow and unnecessary.
- (top-level (treesit-node-first-child-for-pos
- root (if (eolp)
- (max (point-min) (1- (point)))
- (point))
- t))
+ ;; But if the buffer is small (ie, used in playground
+ ;; style), just highlight the whole buffer.
+ (top-level (if (< (buffer-size) 4000)
+ root
+ (treesit-node-first-child-for-pos
+ root (if (eolp)
+ (max (point-min) (1- (point)))
+ (point))
+ t)))
;; Only highlight node when region is active, if we
;; highlight node at point the syntax tree is too jumpy.
(nodes-hl
diff --git a/lisp/vc/diff-mode.el b/lisp/vc/diff-mode.el
index acfd2c30f0c..eb01dede56e 100644
--- a/lisp/vc/diff-mode.el
+++ b/lisp/vc/diff-mode.el
@@ -485,17 +485,19 @@ use the face `diff-removed' for removed lines, and the face
;; if below, use `diff-added'.
(save-match-data
(let ((limit (save-excursion (diff-beginning-of-hunk))))
- (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
- diff-indicator-added-face
- diff-indicator-removed-face)))))
+ (when (< limit (point))
+ (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
+ diff-indicator-added-face
+ diff-indicator-removed-face))))))
(2 (if diff-use-changed-face
'diff-changed-unspecified
;; Otherwise, use the same method as above.
(save-match-data
(let ((limit (save-excursion (diff-beginning-of-hunk))))
- (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
- 'diff-added
- 'diff-removed))))))
+ (when (< limit (point))
+ (if (save-excursion (re-search-backward diff-context-mid-hunk-header-re limit t))
+ 'diff-added
+ 'diff-removed)))))))
("^\\(?:Index\\|revno\\): \\(.+\\).*\n"
(0 'diff-header) (1 'diff-index prepend))
("^\\(?:index .*\\.\\.\\|diff \\).*\n" . 'diff-header)
diff --git a/src/callint.c b/src/callint.c
index c60a376b958..d8d2b278458 100644
--- a/src/callint.c
+++ b/src/callint.c
@@ -105,11 +105,13 @@ If the string begins with `^' and `shift-select-mode' is non-nil,
You may use `@', `*', and `^' together. They are processed in the
order that they appear, before reading any arguments.
-If MODES is present, it should be a list of mode names (symbols) that
-this command is applicable for. The main effect of this is that
-`M-x TAB' (by default) won't list this command if the current buffer's
-mode doesn't match the list. That is, if either the major mode isn't
-derived from them, or (when it's a minor mode) the mode isn't in effect.
+If MODES is present, it should be one or more mode names (symbols)
+for which this command is applicable. This is so that `M-x TAB'
+will be able to exclude this command from the list of completion
+candidates if the current buffer's mode doesn't match the list.
+Which commands are excluded from the list of completion
+candidates based on this information is controlled by the value
+of `read-extended-command-predicate', which see.
usage: (interactive &optional ARG-DESCRIPTOR &rest MODES) */
attributes: const)
diff --git a/src/pgtkfns.c b/src/pgtkfns.c
index 6b3a0459d36..6e5bb22375a 100644
--- a/src/pgtkfns.c
+++ b/src/pgtkfns.c
@@ -1902,7 +1902,7 @@ parse_resource_key (const char *res_key, char *setting_key)
/* check existence of setting_key */
GSettingsSchemaSource *ssrc = g_settings_schema_source_get_default ();
- GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, FALSE);
+ GSettingsSchema *scm = g_settings_schema_source_lookup (ssrc, SCHEMA_ID, TRUE);
if (!scm)
return NULL; /* *.schema.xml is not installed. */
if (!g_settings_schema_has_key (scm, setting_key))
diff --git a/src/print.c b/src/print.c
index d4a9ff89246..e65b4c40b0e 100644
--- a/src/print.c
+++ b/src/print.c
@@ -2034,8 +2034,13 @@ print_vectorlike (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag,
/* Now the node must be up-to-date, and calling functions like
Ftreesit_node_start will not signal. */
bool named = treesit_named_node_p (XTS_NODE (obj)->node);
- const char *delim1 = named ? "(" : "\"";
- const char *delim2 = named ? ")" : "\"";
+ /* We used to use () as delimiters for named nodes, but that
+ confuses pretty-printing a tad bit. There might be more
+ little breakages here and there if we print parenthesizes
+ inside an object, so I guess better not do it.
+ (bug#60696) */
+ const char *delim1 = named ? "" : "\"";
+ const char *delim2 = named ? "" : "\"";
print_c_string (delim1, printcharfun);
print_string (Ftreesit_node_type (obj), printcharfun);
print_c_string (delim2, printcharfun);
diff --git a/test/lisp/progmodes/python-tests.el b/test/lisp/progmodes/python-tests.el
index eac558db10f..df71990278e 100644
--- a/test/lisp/progmodes/python-tests.el
+++ b/test/lisp/progmodes/python-tests.el
@@ -4520,6 +4520,16 @@ def foo():
(python-tests-look-at "\"\"\""))
"# -*- coding: utf-8 -*-\n\nif True:\n a = 1\n b = 2\n\n"))))
+(ert-deftest python-shell-buffer-substring-18 ()
+ "Check substring from the part of the first line."
+ (python-tests-with-temp-buffer
+ "s = 'test'
+"
+ (should (string= (python-shell-buffer-substring
+ (python-tests-look-at "'test'")
+ (pos-eol))
+ "'test'"))))
+
;;; Shell completion
diff --git a/test/lisp/progmodes/ruby-mode-resources/ruby.rb b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
index bfae948b259..3f0dfdf68ba 100644
--- a/test/lisp/progmodes/ruby-mode-resources/ruby.rb
+++ b/test/lisp/progmodes/ruby-mode-resources/ruby.rb
@@ -513,7 +513,7 @@ foo bar, {
case translation
in ['th', orig_text, 'en', trans_text]
puts "English translation: #{orig_text} => #{trans_text}"
-in {'th' => orig_text, 'ja' => trans_text}
+in {th: orig_text, ja: trans_text} => whole
puts "Japanese translation: #{orig_text} => #{trans_text}"
end