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.) +@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. -@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. - -@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,25 +2719,98 @@ sessions, or add this line in your init file (@pxref{Init File}): (desktop-save-mode 1) @end example +@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 @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. + +@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. + @findex desktop-change-dir @findex desktop-revert -@vindex desktop-path - 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. + 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. - 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-load-locked-desktop + The file in which Emacs saves the desktop is locked while the +session runs, to avoid inadvertently overwriting it from another Emacs +session. That lock is normally removed when Emacs exits, but if Emacs +or your system crashes, the lock stays, and when you restart Emacs, it +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. 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, +so if it finds the desktop file locked, it will not load it, unless +@code{desktop-load-locked-desktop} is @code{t}. Note that restoring +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} (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. @@ -2773,50 +2822,18 @@ 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 + 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. -@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. - -@vindex desktop-load-locked-desktop - The file in which Emacs saves the desktop is locked while the -session runs, to avoid inadvertently overwriting it from another Emacs -session. That lock is normally removed when Emacs exits, but if Emacs -or your system crashes, the lock stays, and when you restart Emacs, it -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. - -@cindex desktop restore in daemon mode - When Emacs starts in daemon mode, it cannot ask you any questions, -so if it finds the desktop file locked, it will not load it, unless -@code{desktop-load-locked-desktop} is @code{t}. Note that restoring -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} -(@pxref{Creating Frames,,, elisp, The Emacs Lisp Reference Manual}). - @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." + "Major mode for editing C, powered by tree-sitter. + +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 - (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)) - - ;; Font-lock. - (setq-local treesit-font-lock-settings (c-ts-mode--font-lock-settings '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 @@ def qux 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