diff --git a/admin/MAINTAINERS b/admin/MAINTAINERS index 41bc780d1cc..3ffa21c0d45 100644 --- a/admin/MAINTAINERS +++ b/admin/MAINTAINERS @@ -235,6 +235,7 @@ Philip Kaludercic lisp/emacs-lisp/package.el lisp/emacs-lisp/package-vc.el lisp/emacs-lisp/compat.el + lisp/textmodes/sgml-mode.el Yuan Fu src/treesit.c diff --git a/configure.ac b/configure.ac index a3ba5e69a2f..eeaaaa53a3d 100644 --- a/configure.ac +++ b/configure.ac @@ -1790,7 +1790,9 @@ AS_IF([test $gl_gcc_warnings = no], ;; esac AS_IF([test $gl_gcc_warnings = yes], - [WERROR_CFLAGS=-Werror], + [WERROR_CFLAGS=-Werror + # Work around GCC bug 125116. + gl_WARN_ADD([-Wno-analyzer-allocation-size])], [# Use -fanalyzer and related options only if --enable-gcc-warnings, # as they slow GCC considerably. nw="$nw -fanalyzer -Wno-analyzer-double-free -Wno-analyzer-malloc-leak" diff --git a/doc/lispintro/emacs-lisp-intro.texi b/doc/lispintro/emacs-lisp-intro.texi index 85aa8107232..fc1da41af8b 100644 --- a/doc/lispintro/emacs-lisp-intro.texi +++ b/doc/lispintro/emacs-lisp-intro.texi @@ -1366,8 +1366,11 @@ following in it: ---------- Buffer: *Backtrace* ---------- Debugger entered--Lisp error: (void-function this) (this is an unquoted list) - eval((this is an unquoted list) nil) + (progn (this is an unquoted list)) + eval((progn (this is an unquoted list)) t) elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) eval-last-sexp(nil) funcall-interactively(eval-last-sexp nil) call-interactively(eval-last-sexp nil nil) @@ -1807,6 +1810,8 @@ Debugger entered--Lisp error: (void-function fill-column) (fill-column) eval((fill-column) nil) elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) eval-last-sexp(nil) funcall-interactively(eval-last-sexp nil) call-interactively(eval-last-sexp nil nil) @@ -1843,8 +1848,10 @@ says: @group ---------- Buffer: *Backtrace* ---------- Debugger entered--Lisp error: (void-variable +) - eval(+) + eval(+ nil) elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) eval-last-sexp(nil) funcall-interactively(eval-last-sexp nil) call-interactively(eval-last-sexp nil nil) @@ -2099,15 +2106,16 @@ You will create and enter a @file{*Backtrace*} buffer that says: @smallexample @group ---------- Buffer: *Backtrace* ---------- -Debugger entered--Lisp error: - (wrong-type-argument number-or-marker-p hello) +Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p hello) +(2 hello) eval((+ 2 'hello) nil) - elisp--eval-last-sexp(t) + elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) eval-last-sexp(nil) - funcall-interactively(eval-print-last-sexp nil) - call-interactively(eval-print-last-sexp nil nil) - command-execute(eval-print-last-sexp) + funcall-interactively(eval-last-sexp nil) + call-interactively(eval-last-sexp nil nil) + command-execute(eval-last-sexp) ---------- Buffer: *Backtrace* ---------- @end group @end smallexample @@ -17938,13 +17946,16 @@ Debugger entered--Lisp error: (void-function 1=) (let ((total 0)) (while (> number 0) (setq total ...) (setq number ...)) total) triangle-bugged(4) + eval((triangle-bugged 4) nil) @end group @group - eval((triangle-bugged 4) nil) - eval-expression((triangle-bugged 4) nil nil 127) - funcall-interactively(eval-expression (triangle-bugged 4) nil nil 127) - call-interactively(eval-expression nil nil) - command-execute(eval-expression) + elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) + eval-last-sexp(nil) + funcall-interactively(eval-last-sexp nil) + call-interactively(eval-last-sexp nil nil) + command-execute(eval-last-sexp) ---------- Buffer: *Backtrace* ---------- @end group @end smallexample @@ -18042,10 +18053,13 @@ Debugger entered--entering a function: eval((triangle-bugged 5) nil) @end group @group - eval-expression((triangle-bugged 5) nil nil 127) - funcall-interactively(eval-expression (triangle-bugged 5) nil nil 127) - call-interactively(eval-expression nil nil) - command-execute(eval-expression) + elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) + eval-last-sexp(nil) + funcall-interactively(eval-last-sexp nil) + call-interactively(eval-last-sexp nil nil) + command-execute(eval-last-sexp) ---------- Buffer: *Backtrace* ---------- @end group @end smallexample @@ -18094,12 +18108,15 @@ Debugger entered--beginning evaluation of function call form: (setq number ...)) total) * triangle-bugged(5) eval((triangle-bugged 5) nil) -@group @end group - eval-expression((triangle-bugged 5) nil nil 127) - funcall-interactively(eval-expression (triangle-bugged 5) nil nil 127) - call-interactively(eval-expression nil nil) - command-execute(eval-expression) +@group + elisp--eval-last-sexp(nil) + #f(compiled-function () #)() + handler-bind-1(#f(compiled-function () #) (error) eval-expression--debug) + eval-last-sexp(nil) + funcall-interactively(eval-last-sexp nil) + call-interactively(eval-last-sexp nil nil) + command-execute(eval-last-sexp) ---------- Buffer: *Backtrace* ---------- @end group @end smallexample diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index b0eebec3071..f454d81c63e 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -31,7 +31,7 @@ General Public License for more details. @finalout @titlepage @title Transient User and Developer Manual -@subtitle for version 0.13.0 +@subtitle for version 0.13.2 @author Jonas Bernoulli @page @vskip 0pt plus 1filll @@ -53,7 +53,7 @@ resource to get over that hurdle is Psionic K's interactive tutorial, available at @uref{https://github.com/positron-solutions/transient-showcase}. @noindent -This manual is for Transient version 0.13.0. +This manual is for Transient version 0.13.2. @insertcopying @end ifnottex diff --git a/doc/translations/fr/misc/ses-fr.texi b/doc/translations/fr/misc/ses-fr.texi index ead9ed33609..10bb20420a9 100644 --- a/doc/translations/fr/misc/ses-fr.texi +++ b/doc/translations/fr/misc/ses-fr.texi @@ -58,7 +58,7 @@ modify this GNU manual.'' @top @acronym{SES}: Simple Emacs Spreadsheet @display -@acronym{SES} est mode majeur de GNU Emacs pour éditer des fichiers +@acronym{SES} est un mode majeur de GNU Emacs pour éditer des fichiers tableur, c.-à-d.@: des fichiers contenant une grille rectangulaire de cellules. Les valeurs des cellules sont spécifiées par des formules pouvant se référer aux valeurs d’autres cellules. @@ -70,7 +70,7 @@ Pour les rapports d’anomalie, utiliser @kbd{M-x report-emacs-bug}. @insertcopying @menu -* Boniment: Sales Pitch. Pourquoi utiliser @acronym{SES}? +* Boniment: Sales Pitch. Pourquoi utiliser @acronym{SES} ? * Tuto: Quick Tutorial. Une introduction sommaire * Les bases: The Basics. Les commandes de base du tableur * Fonctions avancées: Advanced Features. Vous voulez en savoir plus ? diff --git a/etc/ERC-NEWS b/etc/ERC-NEWS index 9ede2566e6d..082c10702f3 100644 --- a/etc/ERC-NEWS +++ b/etc/ERC-NEWS @@ -14,8 +14,25 @@ GNU Emacs since Emacs version 22.1. * Changes in ERC 5.6.2 +** Option 'erc-log-insert-log-on-open' can be a function. +Rather than insert redundant logs into all buffers when reconnecting, +which is what happens when this option is set to t, ERC 5.6.2 allows +users to exercise more control by specifying a predicate. The provided +'erc-log-new-target-buffer-p' tells ERC to only insert logs when +creating a new target buffer, such as when issuing a "/JOIN" or a +"/QUERY" or when connecting for the first time with autojoin configured. + ** Changes in the library API. +*** Function 'erc-log-setup-logging' deprecated. +In order to ensure proper buffer-local setup, the 'log' module has +always run this function somewhat indiscriminately and overly often. +This might be fine were it not for the function's interest in the option +'erc-log-insert-log-on-open' and its consequent altering of buffer text +in a manner only conducive to buffer creation. The module now conducts +such business in a tidier and more internal fashion that no longer has +any use for the function nor its presence in 'erc-connect-pre-hook'. + *** Accessors like 'erc-channel-user-voice' may ignore assignments. ERC now silently ignores attempts to enable certain status flags on 'erc-channel-user' objects if the connection's "PREFIX" parameter omits diff --git a/etc/NEWS b/etc/NEWS index c54941382c3..dd9db73285c 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -976,11 +976,10 @@ It is equivalent to running 'project-any-command' with The prompt now displays the chosen project on which to invoke a command. --- -*** 'project-prompter' values may be called with up to four arguments. +*** 'project-prompter' values may be called with up to three arguments. These allow callers of the value of 'project-prompter' to specify a prompt string; prompt the user to choose between a subset of all the -known projects; disallow returning arbitrary directories; and allow -returning an empty string. +known projects; and disallow returning arbitrary directories. See the docstring of 'project-prompter' for a full specification of these new optional arguments. diff --git a/etc/themes/newcomers-presets-theme.el b/etc/themes/newcomers-presets-theme.el index 2c69f26da4c..2163631324e 100644 --- a/etc/themes/newcomers-presets-theme.el +++ b/etc/themes/newcomers-presets-theme.el @@ -19,7 +19,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . -;;; Commentary +;;; Commentary: ;; This theme configures user options that we can reasonably expect the ;; average, new user to want to enable, but would otherwise be unlikely diff --git a/lib-src/emacsclient.c b/lib-src/emacsclient.c index 134c2217650..0769c94a89d 100644 --- a/lib-src/emacsclient.c +++ b/lib-src/emacsclient.c @@ -2257,6 +2257,11 @@ main (int argc, char **argv) char *p = recv_buf; for (char *end_p = p; end_p < recv_buf + nrecv; p = end_p) { + /* An unquoted newline ends a server command. Keep reading, + possibly growing the buffer, until a buffer with a newline + is received. This handles commands with arbitrary-long + arguments (actually needed in 'print' and 'error' commands, + which are followed by strings). */ end_p = memchr (p, '\n', recv_buf + nrecv - p); if (!end_p) break; @@ -2288,7 +2293,8 @@ main (int argc, char **argv) } else if (strprefix ("-print ", p)) { - /* -print STRING: Print STRING on the terminal. */ + /* -print STRING: Print STRING, preceeded by a newline, on + the terminal. */ if (!suppress_output) { char *str = unquote_argument (p + strlen ("-print ")); @@ -2299,8 +2305,10 @@ main (int argc, char **argv) } else if (strprefix ("-print-nonl ", p)) { - /* -print-nonl STRING: Print STRING on the terminal. - Used to continue a preceding -print command. */ + /* -print-nonl STRING: Print STRING on the terminal + without a preceding newlin. Used to continue a + preceding -print command. Nowadays used only for + servers in Emacs versions before 31. */ if (!suppress_output) { char *str = unquote_argument (p + strlen ("-print-nonl ")); diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index e1486418876..068b94360d4 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -468,7 +468,7 @@ BI-DESC should be a `package--bi-desc' object." :summary (package--bi-desc-summary bi-desc) :dir 'builtin)) -(defconst package--builtin-alist nil) +(defvar package--builtin-alist nil) (defun package--builtin-alist () "Return a alist of built-in packages in the form of `package-alist'. The alist doesn't include the pseudo-package for Emacs." @@ -2566,7 +2566,7 @@ intended for testing Emacs and/or the packages in a clean environment." (interactive (cl-loop for p in (append (cl-loop for p in (package--alist) append (cdr p)) - (cl-loop for p in package-archive-contents append (cdr p))) + (cl-loop for p in (package--archive-contents) append (cdr p))) unless (package-built-in-p p) collect (cons (package-desc-full-name p) p) into table finally return diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index 6126679e870..166b346fbbe 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -228,10 +228,9 @@ Emacs Lisp manual for more information and examples." ;;;###autoload (defmacro pcase-exhaustive (exp &rest cases) "The exhaustive version of `pcase' (which see). -If EXP fails to match any of the patterns in CASES, an error is -signaled. +If EXP fails to match any of the patterns in CASES, signal an error. -In contrast, `pcase' will return nil if there is no match, but +In contrast, `pcase' will return nil if there is no match, but will not signal an error." (declare (indent 1) (debug pcase)) (let* ((x (gensym "x")) diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index be86051ff2f..d5a39b77c2e 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -322,6 +322,7 @@ automatically killed, which means that in a such case buffer (generate-new-buffer " *work*" t)))) +;;;###autoload (defun work-buffer--release (buffer) "Release work BUFFER." (if (buffer-live-p buffer) diff --git a/lisp/erc/erc-log.el b/lisp/erc/erc-log.el index 01ea1a3d3c8..e7160aa482f 100644 --- a/lisp/erc/erc-log.el +++ b/lisp/erc/erc-log.el @@ -157,8 +157,16 @@ arguments." (const :tag "Disable logging" nil))) (defcustom erc-log-insert-log-on-open nil - "Insert log file contents into the buffer if a log file exists." - :type 'boolean) + "Insert an existing log file's contents into its associated buffer. +A legacy value of t does so upon connecting and reconnecting in all +buffers, often in an overlapping and redundant fashion. A value of +`erc-log-new-target-buffer-p' does so in new target buffers only. If +set to an arbitrary predicate, ERC calls it with no args in the +associated buffer." + :type '(choice boolean + (function-item :tag "Only new target buffers" + erc-log-new-target-buffer-p) + (function "User-defined predicate taking no args"))) (defcustom erc-save-buffer-on-part t "Save the channel buffer content using `erc-save-buffer-in-logs' on PART. @@ -231,10 +239,9 @@ also be a predicate function. To only log when you are not set away, use: (add-hook 'erc-quit-hook #'erc-conditional-save-queries) (add-hook 'erc-part-hook #'erc-conditional-save-buffer) ;; append, so that 'erc-initialize-log-marker runs first - (add-hook 'erc-connect-pre-hook #'erc-log-setup-logging 'append) - ;; FIXME use proper local "setup" function and major-mode hook. - (dolist (buffer (erc-buffer-list)) - (erc-log-setup-logging buffer)) + (add-hook 'erc-connect-pre-hook #'erc-log--insert-log-on-open 80) + (add-hook 'erc-mode-hook #'erc-log--setup) + (unless erc--updating-modules-p (erc-buffer-do #'erc-log--setup)) (erc--modify-local-map t "C-c C-l" #'erc-save-buffer-in-logs)) ;; disable ((remove-hook 'erc-insert-post-hook #'erc-save-buffer-in-logs) @@ -244,36 +251,74 @@ also be a predicate function. To only log when you are not set away, use: (remove-hook 'kill-emacs-hook #'erc-log-save-all-buffers) (remove-hook 'erc-quit-hook #'erc-conditional-save-queries) (remove-hook 'erc-part-hook #'erc-conditional-save-buffer) - (remove-hook 'erc-connect-pre-hook #'erc-log-setup-logging) - (dolist (buffer (erc-buffer-list)) - (erc-log-disable-logging buffer)) + (remove-hook 'erc-connect-pre-hook #'erc-log--insert-log-on-open) + (remove-hook 'erc-mode-hook #'erc-log--setup) + (erc-buffer-do #'erc-log--setup) (erc--modify-local-map nil "C-c C-l" #'erc-save-buffer-in-logs))) -;;; functionality referenced from erc.el +(defun erc-log-new-target-buffer-p () + "Return non-nil during `erc-open' if the current buffer is a new target. +That is, return nil if it's a server buffer or a target being +reassociated from a previous session." + (and (erc-target) (null erc--target-priors))) + +;; This function served double duty as the local setup function for both +;; idempotent tasks and destructive ones typically confined to +;; `erc-open'. The caller was implicitly tasked with selectively +;; inhibiting the destructive portion by binding +;; `erc-log-insert-log-on-open' to nil when calling it, which led to +;; bugs. (defun erc-log-setup-logging (buffer) "Setup the buffer-local logging variables in the current buffer. This function is destined to be run from `erc-connect-pre-hook'. The current buffer is given by BUFFER." - (when (erc-logging-enabled buffer) - (with-current-buffer buffer + (declare (obsolete "use `erc-log-mode' or mimic `erc-log--setup'" "31.1")) + (with-current-buffer buffer + (let ((erc-log-mode t)) + (erc-log--setup) + (erc-log--insert-log-on-open)))) + +;; This module's differs from other global modules in that it allows for +;; effectively disabling itself in a subset of buffers by setting the +;; option `erc-enable-logging' locally to nil. Though not +;; permanent-local, this option's variable is never explicitly killed +;; when the module is disabled, such as via its mode command. +(defun erc-log--setup () + "Perform buffer-local setup for ERC's log module." + (if erc-log-mode + (when (erc-logging-enabled) + ;; If reconnecting, preserve `erc-last-saved-position' from prev + ;; session and preempt `erc-initialize-log-marker' in `erc-open'. + (unless erc-last-saved-position + (when-let* ((priors (or erc--server-reconnecting erc--target-priors)) + (val (alist-get 'erc-last-saved-position priors)) + (_ (eq (current-buffer) (marker-buffer val)))) + (setq erc-last-saved-position val))) (auto-save-mode -1) (setq buffer-file-name nil) (add-hook 'write-file-functions #'erc-save-buffer-in-logs nil t) (add-function :before (local 'erc--clear-function) - #'erc-log--save-on-clear '((depth . 50))) - (when erc-log-insert-log-on-open + #'erc-log--save-on-clear '((depth . 50)))) + (erc-log-disable-logging (current-buffer)))) + +(defun erc-log--insert-log-on-open (&rest _) + "Conditionally perform insertion for `erc-log-insert-log-on-open'." + (when (if (functionp erc-log-insert-log-on-open) + (funcall erc-log-insert-log-on-open) + erc-log-insert-log-on-open) + (with-silent-modifications + (progn (ignore-errors (save-excursion (goto-char (point-min)) - (insert-file-contents (erc-current-logfile))) - (move-marker erc-last-saved-position - (1- (point-max)))))))) + (insert-file-contents (erc-current-logfile)))))))) (defun erc-log-disable-logging (buffer) "Disable logging in BUFFER." (when (erc-logging-enabled buffer) (with-current-buffer buffer (remove-function (local 'erc--clear-function) #'erc-log--save-on-clear) + (remove-hook 'write-file-functions #'erc-save-buffer-in-logs t) (setq buffer-offer-save nil erc-enable-logging nil)))) diff --git a/lisp/erc/erc-pcomplete.el b/lisp/erc/erc-pcomplete.el index e5c72cda796..df94097a00f 100644 --- a/lisp/erc/erc-pcomplete.el +++ b/lisp/erc/erc-pcomplete.el @@ -61,6 +61,11 @@ add this string to nicks completed." ;;;###autoload(put 'completion 'erc--feature 'erc-pcomplete) ;;;###autoload(autoload 'erc-completion-mode "erc-pcomplete" nil t) (put 'completion 'erc-group 'erc-pcomplete) +;; For historical reasons, (the downcased version of) this module's +;; alias is the canonical name used by `erc-modules'. But user code +;; still needs to detect whether the module is enabled based on that +;; name alone, hence this variable alias. +(defvaralias 'erc-completion-mode 'erc-pcomplete-mode) (define-erc-module pcomplete Completion "In ERC Completion mode, the TAB key does completion whenever possible." ((add-hook 'erc-mode-hook #'pcomplete-erc-setup) diff --git a/lisp/external-completion.el b/lisp/external-completion.el index aa23c949241..a361710b686 100644 --- a/lisp/external-completion.el +++ b/lisp/external-completion.el @@ -67,8 +67,8 @@ may be a shell utility, an inferior process, an http server, etc. Given a pattern string, the external tool matches it to an arbitrarily large set of candidates. Since the full set doesn't need to be transferred to Emacs's address space, this often -results in much faster overall experience, at the expense of the -convenience of offered by other completion styles. +results in a much faster overall experience, at the expense of the +convenience offered by other completion styles. CATEGORY is a symbol uniquely naming the external tool. This function links CATEGORY to the style `external', by modifying @@ -95,7 +95,7 @@ non-list. METADATA is an alist of additional properties such as `cycle-sort-function' to associate with CATEGORY. This means -that the caller may still retain control the sorting of the +that the caller may still retain control of the sorting of the candidates while the tool controls the matching. Optional TRY-COMPLETION-FUNCTION helps some frontends partially @@ -105,7 +105,7 @@ ALL-COMPLETIONS), where PATTERN and POINT are as described above and ALL-COMPLETIONS are gathered by LOOKUP for these arguments (this function ensures LOOKUP isn't called more than needed). If you know the matching method that the external tool -using, TRY-COMPLETION-FUNCTION may return a cons +is using, TRY-COMPLETION-FUNCTION may return a cons cell (EXPANDED-PATTERN . NEW-POINT). For example, if the tool is completing by prefix, one could call `try-completion' to find the largest common prefix in ALL-COMPLETIONS and then return that as diff --git a/lisp/gnus/gnus-srvr.el b/lisp/gnus/gnus-srvr.el index 312862df165..b4802cb72d4 100644 --- a/lisp/gnus/gnus-srvr.el +++ b/lisp/gnus/gnus-srvr.el @@ -31,6 +31,7 @@ (require 'gnus-int) (require 'gnus-range) (require 'gnus-cloud) +(require 'gnus-sum) (autoload 'gnus-group-read-ephemeral-search-group "nnselect") @@ -250,6 +251,8 @@ The following commands are available: \\{gnus-server-mode-map}" (when (gnus-visual-p 'server-menu 'menu) (gnus-server-make-menu-bar)) + (gnus-update-format-specifications nil 'server 'server-mode) + (gnus-set-mode-line 'server) (gnus-simplify-mode-line) (gnus-set-default-directory) (setq mode-line-process nil) diff --git a/lisp/gnus/gnus-sum.el b/lisp/gnus/gnus-sum.el index 0fdb97d496c..cf635db0f02 100644 --- a/lisp/gnus/gnus-sum.el +++ b/lisp/gnus/gnus-sum.el @@ -6161,16 +6161,19 @@ If WHERE is `summary', the summary mode line format will be used." (symbol-value (intern (format "gnus-%s-mode-line-format-spec" where)))) (let (mode-string) - ;; We evaluate this in the summary buffer since these - ;; variables are buffer-local to that buffer. - (with-current-buffer gnus-summary-buffer + ;; We evaluate this in the summary or server buffer (depending on + ;; WHERE) since these variables are buffer-local to these buffers. + (with-current-buffer (if (eq where 'server) + gnus-server-buffer + gnus-summary-buffer) ;; We bind all these variables that are used in the `eval' form ;; below. (let* ((mformat (symbol-value (intern (format "gnus-%s-mode-line-format-spec" where)))) - (gnus-tmp-group-name (gnus-mode-string-quote - gnus-newsgroup-name)) + (gnus-tmp-group-name (and gnus-newsgroup-name + (gnus-mode-string-quote + gnus-newsgroup-name))) (gnus-tmp-article-number (or gnus-current-article 0)) (gnus-tmp-unread gnus-newsgroup-unreads) (gnus-tmp-unread-and-unticked (length gnus-newsgroup-unreads)) diff --git a/lisp/gnus/gnus.el b/lisp/gnus/gnus.el index b6c307f9037..bcc8b8744f8 100644 --- a/lisp/gnus/gnus.el +++ b/lisp/gnus/gnus.el @@ -1420,7 +1420,7 @@ this variable. I think." (gnus-redefine-select-method-widget) -(defcustom gnus-updated-mode-lines '(group article summary tree) +(defcustom gnus-updated-mode-lines '(group article summary tree server) "List of buffers that should update their mode lines. The list may contain the symbols `group', `article', `tree' and `summary'. If the corresponding symbol is present, Gnus will keep @@ -1430,7 +1430,8 @@ If this variable is nil, screen refresh may be quicker." :type '(set (const group) (const article) (const summary) - (const tree))) + (const tree) + (const server))) (defcustom gnus-mode-non-string-length 30 "Max length of mode-line non-string contents. diff --git a/lisp/jsonrpc.el b/lisp/jsonrpc.el index 77010b76ab5..174c99afc86 100644 --- a/lisp/jsonrpc.el +++ b/lisp/jsonrpc.el @@ -86,12 +86,14 @@ :documentation "Map (DEFERRED BUF) to (FN TIMER ID). FN is\ a saved DEFERRED `async-request' from BUF, to be sent not later\ than TIMER as ID.") - (-sync-request-alist ; bug#67945 + (-scontrol ; bug#67945 :initform nil - :accessor jsonrpc--sync-request-alist - :documentation "List of ((ID [ANXIOUS...])) where ID refers \ -to a sync `jsonrpc-request' and each ANXIOUS to another completed\ -request that is higher up in the stack but couldn't run.") + :accessor jsonrpc--scontrol + :documentation "List of ((KEY [ANXIOUS...])) where KEY is \ +(:local ID) for an outstanding sync `jsonrpc-request', or \ +(:remote ID) while a remote request with that ID is being \ +dispatched. Each ANXIOUS is a completed response deferred \ +until KEY's entry is popped.") (-next-request-id :initform 0 :accessor jsonrpc--next-request-id @@ -291,7 +293,7 @@ dispatcher in CONN." (with-slots (last-error (rdispatcher -request-dispatcher) (ndispatcher -notification-dispatcher) - (sr-alist -sync-request-alist)) + (scontrol -scontrol)) conn (setf last-error error) (cond @@ -311,23 +313,31 @@ dispatcher in CONN." ) (;; A remote response that can't run yet (bug#67945) (and response-p - (and sr-alist (not (eq id (caar sr-alist))))) + (and scontrol (not (equal `(:local ,id) (caar scontrol))))) (jsonrpc--event conn 'internal :log-text (format "anxious continuation to %s can't run, held up by %s" id - (mapcar #'car sr-alist))) + (mapcar #'car scontrol))) (push (cons cont (list result error)) - (cdr (car sr-alist)))) + (cdr (car scontrol)))) (;; A remote response that can continue now response-p - (jsonrpc--continue conn id cont result error)) + (jsonrpc--continue conn `(:local ,id) cont result error)) (;; A remote request (and method id) (let* ((debug-on-error (and debug-on-error (not jsonrpc-inhibit-debug-on-error))) reply) + ;; While the rdispatcher runs, any arriving response to + ;; a previous sync request must not fire its + ;; continuation immediately: the resulting `throw' would + ;; unwind through the dispatcher and trigger a spurious + ;; -32603 instead of a reply. Use `jsonrpc--scontrol' + ;; mechanism to defer such continuations until the end + ;; of the cleanup below. + (push `((:remote ,id)) (jsonrpc--scontrol conn)) (unwind-protect (setq reply @@ -349,7 +359,8 @@ dispatcher in CONN." (unless reply (setq reply `(:error (:code -32603 :message "Internal error")))) - (apply #'jsonrpc--reply conn id method reply)))) + (apply #'jsonrpc--reply conn id method reply) + (jsonrpc--continue conn `(:remote ,id))))) (;; A remote notification method (funcall ndispatcher conn (intern method) params)) @@ -513,7 +524,7 @@ to the original request (normal or error) are ignored." ;; request, it might have been holding up any outer ;; "anxious" continuations. The following ensures we ;; call them. - (jsonrpc--continue connection id))) + (jsonrpc--continue connection `(:local ,id)))) (cond ((eq 'error (car retval)) (signal 'jsonrpc-error (cons @@ -902,11 +913,11 @@ Return the full continuation (ID SUCCESS-FN ERROR-FN TIMER)" (defun jsonrpc--continue (conn id &optional cont result error) (pcase-let* ((`(,cont-id ,_method ,success-fn ,error-fn ,_timer) cont) - (head (pop (jsonrpc--sync-request-alist conn))) + (head (pop (jsonrpc--scontrol conn))) (anxious (cdr head))) (cond (anxious - (when (not (= (car head) id)) ; sanity check + (when (not (equal (car head) id)) ; sanity check (error "Internal error: please report this bug")) ;; If there are "anxious" `jsonrpc-request' continuations ;; that should already have been run, they should run now. @@ -998,7 +1009,7 @@ TIMEOUT is nil)." ;; Setup some control structures ;; (when sync-request - (push (list id) (jsonrpc--sync-request-alist connection))) + (push `((:local ,id)) (jsonrpc--scontrol connection))) (jsonrpc--schedule connection id method @@ -1108,7 +1119,7 @@ of the API instead.") (cl-destructuring-bind (&key method id error &allow-other-keys) message (let* ((inhibit-read-only t) (depth (length - (jsonrpc--sync-request-alist connection))) + (jsonrpc--scontrol connection))) (preamble (format "[jsonrpc] %s[%s]%s " (pcase type ('error "E") ('debug "D") (_ (pcase origin diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 591000cb440..c8120d5752c 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -1274,7 +1274,8 @@ if `c-ts-mode-emacs-sources-support' is non-nil." "goto_statement" "case_statement"))) (text ,(regexp-opt '("comment" - "raw_string_literal")))) + "raw_string_literal"))) + (comment "comment")) "`treesit-thing-settings' for both C and C++.") ;;; Support for FOR_EACH_* macros diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 13d578d550a..b41fd3d2212 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -625,12 +625,12 @@ Note additionally: :package-version '(Eglot . "1.19")) (defcustom eglot-code-action-indicator - (cl-loop for c in '(?💡 ?⚡?✓ ?α ??) + (cl-loop for c in '(?↯ ?⭍ ?✓ ?α ??) when (char-displayable-p c) return (make-string 1 c)) "Indicator string for code action suggestions." :type (let ((basic-choices - (cl-loop for c in '(?💡 ?⚡?✓ ?α ??) + (cl-loop for c in '(?↯ ?⭍ ?✓ ?α ??) when (char-displayable-p c) collect `(const :tag ,(format "Use `%c'" c) ,(make-string 1 c))))) diff --git a/lisp/progmodes/project.el b/lisp/progmodes/project.el index e7078d8e972..7e794330b1f 100644 --- a/lisp/progmodes/project.el +++ b/lisp/progmodes/project.el @@ -212,8 +212,8 @@ When it is non-nil, `project-current' will always skip prompting too.") (defcustom project-prompter #'project-prompt-project-dir "Function to call to prompt for a project. -The function is called either with no arguments or with up to four -optional arguments: (&optional PROMPT PREDICATE REQUIRE-KNOWN ALLOW-EMPTY). +The function is called either with no arguments or with up to three +optional arguments: (&optional PROMPT PREDICATE REQUIRE-KNOWN). PROMPT is the prompt string to use. @@ -231,12 +231,14 @@ may allow the user to input arbitrary directories. If PREDICATE and REQUIRE-KNOWN are both non-nil, the value of `project-prompter' should not return any project root directory for which PREDICATE returns nil. -If ALLOW-EMPTY is non-nil, then irrespective of REQUIRE-KNOWN, the user -may enter nothing (i.e., just type RET). -In this case the function should return \"\". Conventionally this is -used to allow the user to select the current project. -Callers should append something like \" (empty for current project)\" to -PROMPT when passing ALLOW-EMPTY non-nil." +The function must always return a valid project. + +If there is a current project, it satisfies PREDICATE (or PREDICATE is +nil), and the method of prompting involves a default selection, then +this default selection should be the current project root. For example +if the function uses `completing-read' then the current project, if any, +should be passed as the DEF argument to `completing-read', and returned +in the case that the user replies with empty input." :type '(choice (const :tag "Prompt for a project directory" project-prompt-project-dir) (const :tag "Prompt for a project name" @@ -1416,7 +1418,7 @@ directories listed in `vc-directory-exclusion-list'." project "Find file" all-files nil 'file-name-history suggested-filename))) - (if (string= file "") + (if (string-empty-p file) (user-error "You didn't specify the file") (find-file file)))) @@ -1845,7 +1847,7 @@ Return non-nil if PROJECT is not a remote project." '(metadata . ((category . project-buffer) (cycle-sort-function . identity)))) ((and (eq action t) - (equal string "")) ;Pcm completion or empty prefix. + (string-empty-p string)) ;Pcm completion or empty prefix. (let* ((all (complete-with-action action buffers string pred)) (non-internal (cl-remove-if (lambda (b) (= (aref b 0) ?\s)) all))) (if (null non-internal) @@ -2222,10 +2224,10 @@ With some possible metadata (to be decided).") "Initialize `project--list' if it isn't already initialized." (when (eq project--list 'unset) (project--read-project-list) - (if-let* ((pred (alist-get 'list-first-read project-prune-zombie-projects)) - ((consp project--list)) - (inhibit-message t)) - (project--delete-zombie-projects pred)))) + (when-let* ((pred (alist-get 'list-first-read project-prune-zombie-projects)) + ((consp project--list)) + (inhibit-message t)) + (project--delete-zombie-projects pred)))) (defun project--write-project-list () "Save `project--list' in `project-list-file'." @@ -2234,10 +2236,10 @@ With some possible metadata (to be decided).") (insert ";;; -*- lisp-data -*-\n") (let ((print-length nil) (print-level nil)) - (if-let* ((pred (alist-get 'list-write project-prune-zombie-projects)) - ((consp project--list)) - (inhibit-message t)) - (project--delete-zombie-projects pred)) + (when-let* ((pred (alist-get 'list-write project-prune-zombie-projects)) + ((consp project--list)) + (inhibit-message t)) + (project--delete-zombie-projects pred)) (pp (mapcar (lambda (elem) (let ((name (car elem))) (list (if (file-remote-p name) name @@ -2311,8 +2313,7 @@ the project list." (defvar project--dir-history) -(defun project-prompt-project-dir - (&optional prompt predicate require-known allow-empty) +(defun project-prompt-project-dir (&optional prompt predicate require-known) "Prompt the user for a directory that is one of the known project roots. The project is chosen among projects known from the project list, see `project-list-file'. @@ -2320,13 +2321,17 @@ If PROMPT is non-nil, use it as the prompt string. If PREDICATE is non-nil, filter possible project choices using this function; see `project-prompter' for more details. Unless REQUIRE-KNOWN is non-nil, it's also possible to enter an -arbitrary directory not in the list of known projects. -If ALLOW-EMPTY is non-nil, it is possible to exit with no input." +arbitrary directory not in the list of known projects." (project--ensure-read-project-list) - (if-let* ((pred (alist-get 'prompt project-prune-zombie-projects)) - (inhibit-message t)) - (project--delete-zombie-projects pred)) + (when-let* ((pred (alist-get 'prompt project-prune-zombie-projects)) + (inhibit-message t)) + (project--delete-zombie-projects pred)) (let* ((dir-choice "... (choose a dir)") + (current (and-let* ((p (project-current)) + (_ (or (null predicate) + (funcall predicate + (project-root p))))) + (project-root p))) (choices ;; XXX: Just using this for the category (for the substring ;; completion style). @@ -2334,30 +2339,29 @@ If ALLOW-EMPTY is non-nil, it is possible to exit with no input." (if require-known project--list (append project--list `(,dir-choice))))) (project--dir-history (project-known-project-roots)) - pr-dir) - (cl-loop - do (setq pr-dir - (let (history-add-new-input) - (completing-read (if prompt - ;; TODO: Use `format-prompt' (Emacs 28.1+) - (format "%s: " (substitute-command-keys prompt)) - "Select project: ") - choices - (and predicate - (lambda (choice) - (or (equal choice dir-choice) - (funcall predicate choice)))) - t nil 'project--dir-history))) - ;; If the user simply pressed RET, do this again until they don't. - while (and (not allow-empty) (equal pr-dir ""))) + (pr-dir "")) + (while (string-empty-p pr-dir) + ;; If the user simply pressed RET (and CURRENT is nil), do this + ;; again until they don't. + (setq pr-dir + (let (history-add-new-input) + (completing-read + ;; Emacs 28.1+: Use `format-prompt'. + (cond (prompt (format "%s: " prompt)) + (current "Select project (default current project): ") + (t "Select project: ")) + choices (and predicate + (lambda (choice) + (or (equal choice dir-choice) + (funcall predicate choice)))) + t nil 'project--dir-history current)))) (if (equal pr-dir dir-choice) (read-directory-name "Select directory: " default-directory nil t) pr-dir))) (defvar project--name-history) -(defun project-prompt-project-name - (&optional prompt predicate require-known allow-empty) +(defun project-prompt-project-name (&optional prompt predicate require-known) "Prompt the user for a project, by name, that is one of the known project roots. The project is chosen among projects known from the project list, see `project-list-file'. @@ -2365,13 +2369,17 @@ If PROMPT is non-nil, use it as the prompt string. If PREDICATE is non-nil, filter possible project choices using this function; see `project-prompter' for more details. Unless REQUIRE-KNOWN is non-nil, it's also possible to enter an -arbitrary directory not in the list of known projects. -If ALLOW-EMPTY is non-nil, it is possible to exit with no input." - (if-let* ((pred (alist-get 'prompt project-prune-zombie-projects)) - (inhibit-message t)) - (project--delete-zombie-projects pred)) +arbitrary directory not in the list of known projects." + (when-let* ((pred (alist-get 'prompt project-prune-zombie-projects)) + (inhibit-message t)) + (project--delete-zombie-projects pred)) (let* ((dir-choice "... (choose a dir)") project--name-history + (current (and-let* ((p (project-current)) + (_ (or (null predicate) + (funcall predicate + (project-root p))))) + (project-name p))) (choices (let (ret) ;; Iterate in reverse order so project--name-history is in @@ -2390,22 +2398,22 @@ If ALLOW-EMPTY is non-nil, it is possible to exit with no input." (table (project--file-completion-table (reverse (if require-known choices (cons dir-choice choices))))) - pr-name) - (cl-loop - do (setq pr-name - (let (history-add-new-input) - (completing-read (if prompt - (format "%s: " prompt) - "Select project: ") - table nil t nil 'project--name-history))) - ;; If the user simply pressed RET, do this again until they don't. - while (and (not allow-empty) (equal pr-name ""))) - (pcase pr-name - ("" "") - ((pred (equal dir-choice)) (read-directory-name "Select directory: " - default-directory nil t)) - (_ (let ((proj (assoc pr-name choices))) - (if (stringp proj) proj (project-root (cdr proj)))))))) + (pr-name "")) + (while (string-empty-p pr-name) + ;; If the user simply pressed RET (and CURRENT is nil), do this + ;; again until they don't. + (setq pr-name + (let (history-add-new-input) + (completing-read + ;; Emacs 28.1+: Use `format-prompt'. + (cond (prompt (format "%s: " prompt)) + (current "Select project (default current project): ") + (t "Select project: ")) + table nil t nil 'project--name-history current)))) + (if (equal pr-name dir-choice) + (read-directory-name "Select directory: " default-directory nil t) + (let ((proj (assoc pr-name choices))) + (if (stringp proj) proj (project-root (cdr proj))))))) ;;;###autoload (defun project-known-project-roots () diff --git a/lisp/server.el b/lisp/server.el index c2aa854a4bb..b912b185275 100644 --- a/lisp/server.el +++ b/lisp/server.el @@ -1143,7 +1143,9 @@ The following commands are accepted by the client: `-print-nonl STRING' Print STRING on stdout. Used to continue a preceding -print command that would be too big to send - in a single message. + in a single message. Unused in the server since Emacs 31; + mentioned here only for completeness, because the client + needs to support it when it connects to older Emacsen. `-error DESCRIPTION' Signal an error and delete process PROC. diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index 2170fcea6e9..be14462d1a0 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -4,7 +4,7 @@ ;; Foundation, Inc. ;; Author: James Clark -;; Maintainer: emacs-devel@gnu.org +;; Maintainer: Philip Kaludercic ;; Adapted-By: ESR, Daniel Pfeiffer , ;; F.Potorti@cnuce.cnr.it ;; Keywords: text, hypermedia, comm, languages @@ -47,8 +47,8 @@ (defcustom sgml-basic-offset 2 "Specifies the basic indentation level for `sgml-indent-line'." - :type 'integer - :safe #'integerp) + :type 'natnum + :safe #'natnump) (defcustom sgml-attribute-offset 0 "Specifies a delta for attribute indentation in `sgml-indent-line'. @@ -65,14 +65,15 @@ When 2, attribute indentation looks like this: attribute=\"value\"> " :version "25.1" - :type 'integer - :safe #'integerp) + :type 'natnum + :safe #'natnump) (defcustom sgml-xml-mode nil "When non-nil, tag insertion functions will be XML-compliant. It is set to be buffer-local when the file has a DOCTYPE or an XML declaration." :type 'boolean + :safe #'booleanp :version "22.1") (define-obsolete-variable-alias 'sgml-transformation @@ -114,49 +115,57 @@ Including ?- makes double dashes into comment delimiters, but they are really only supposed to delimit comments within DTD definitions. So we normally turn it off.") -(defvar sgml-quick-keys nil - "Use <, >, &, /, SPC and `sgml-specials' keys \"electrically\" when non-nil. -This takes effect when first loading the `sgml-mode' library.") - (defvar sgml-mode-map (let ((map (make-keymap))) ;`sparse' doesn't allow binding to charsets. - (define-key map "\C-c\C-i" #'sgml-tags-invisible) + (define-key map (kbd "C-c C-i") #'sgml-tags-invisible) (define-key map "/" #'sgml-slash) - (define-key map "\C-c\C-n" #'sgml-name-char) - (define-key map "\C-c\C-t" #'sgml-tag) - (define-key map "\C-c\C-a" #'sgml-attributes) - (define-key map "\C-c\C-b" #'sgml-skip-tag-backward) - (define-key map [?\C-c left] #'sgml-skip-tag-backward) - (define-key map "\C-c\C-f" #'sgml-skip-tag-forward) - (define-key map [?\C-c right] #'sgml-skip-tag-forward) - (define-key map "\C-c\C-d" #'sgml-delete-tag) - (define-key map "\C-c\^?" #'sgml-delete-tag) - (define-key map "\C-c?" #'sgml-tag-help) - (define-key map "\C-c]" #'sgml-close-tag) - (define-key map "\C-c/" #'sgml-close-tag) + (define-key map (kbd "C-c C-n") #'sgml-name-char) + (define-key map (kbd "C-c C-t") #'sgml-tag) + (define-key map (kbd "C-c C-a") #'sgml-attributes) + (define-key map (kbd "C-c C-b") #'sgml-skip-tag-backward) + (define-key map (kbd "C-c ") #'sgml-skip-tag-backward) + (define-key map (kbd "C-c C-f") #'sgml-skip-tag-forward) + (define-key map (kbd "C-c ") #'sgml-skip-tag-forward) + (define-key map (kbd "C-c C-d") #'sgml-delete-tag) + (define-key map (kbd "C-c ^ ?") #'sgml-delete-tag) + (define-key map (kbd "C-c ?") #'sgml-tag-help) + (define-key map (kbd "C-c ]") #'sgml-close-tag) + (define-key map (kbd "C-c /") #'sgml-close-tag) ;; Redundant keybindings, for consistency with TeX mode. - (define-key map "\C-c\C-o" #'sgml-tag) - (define-key map "\C-c\C-e" #'sgml-close-tag) + (define-key map (kbd "C-c C-o") #'sgml-tag) + (define-key map (kbd "C-c C-e") #'sgml-close-tag) - (define-key map "\C-c8" #'sgml-name-8bit-mode) - (define-key map "\C-c\C-v" #'sgml-validate) - (when sgml-quick-keys - (define-key map "&" #'sgml-name-char) - (define-key map "<" #'sgml-tag) - (define-key map " " #'sgml-auto-attributes) - (define-key map ">" #'sgml-maybe-end-tag) - (when (memq ?\" sgml-specials) - (define-key map "\"" #'sgml-name-self)) - (when (memq ?' sgml-specials) - (define-key map "'" #'sgml-name-self))) - (let ((c 127) - (map (nth 1 map))) - (while (< (setq c (1+ c)) 256) - (aset map c #'sgml-maybe-name-self))) + (define-key map (kbd "C-c 8") #'sgml-name-8bit-mode) + (define-key map (kbd "C-c C-v") #'sgml-validate) + + (cl-loop for c from 128 upto 255 + do (define-key map (string c) #'sgml-maybe-name-self)) map) "Keymap for SGML mode. See also `sgml-specials'.") +(defcustom sgml-quick-keys nil + "Use <, >, &, /, SPC and `sgml-specials' keys \"electrically\" when non-nil. +By setting the option to `indent', Emacs will eagerly reindent the +current line when you manually close a tag." + :set (lambda (sym val) + (set-default sym val) + (dolist (bind `(("&" . ,#'sgml-name-char) + ("<" . ,#'sgml-tag) + ("\s" . ,#'sgml-auto-attributes) + (">" . ,#'sgml-maybe-end-tag) + ("\"" . ,(and (memq ?\" sgml-specials) #'sgml-name-self)) + ("'" . ,(and (memq ?' sgml-specials) #'sgml-name-self)))) + (if (and val (cdr bind)) + (define-key sgml-mode-map (car bind) (cdr bind)) + (define-key sgml-mode-map (car bind) nil t))) + (custom-reevaluate-setting 'html-quick-keys)) + :type '(choice (const :tag "Enabled" t) + (const :tag "Enabled, and indent when closing tags" indent) + ;; Omit `close' because `electric-pair-mode' already + ;; takes care of paring "<" and ">". + (const :tag "Disabled" nil))) + (easy-menu-define sgml-mode-menu sgml-mode-map "Menu for SGML mode." '("SGML" @@ -211,7 +220,7 @@ This takes effect when first loading the `sgml-mode' library.") table) "Syntax table used to parse SGML tags.") -(defcustom sgml-name-8bit-mode nil +(define-minor-mode sgml-name-8bit-mode "When non-nil, insert non-ASCII characters as named entities." :type 'boolean) @@ -277,12 +286,11 @@ Currently, only Latin-1 characters are supported.") ((executable-find "onsgmls") ;; onsgmls is the community version of `nsgmls' ;; hosted on https://openjade.sourceforge.net/ - "onsgmls -s") - (t "Install (o)nsgmls, tidy, or some other SGML validator, and set `sgml-validate-command'")) + "onsgmls -s")) "The command to validate an SGML document. The file name of current buffer file name will be appended to this, separated by a space." - :type 'string + :type '(choice (const :tag "Unset" nil) string) :version "21.1") (defvar sgml-saved-validate-command nil @@ -774,14 +782,6 @@ Uses `sgml-char-names'." (sgml-name-char last-command-event) (self-insert-command 1))) -(defun sgml-name-8bit-mode () - "Toggle whether to insert named entities instead of non-ASCII characters. -This only works for Latin-1 input." - (interactive) - (setq sgml-name-8bit-mode (not sgml-name-8bit-mode)) - (message "sgml name entity mode is now %s" - (if sgml-name-8bit-mode "ON" "OFF"))) - ;; When an element of a skeleton is a string "str", it is passed ;; through `skeleton-transformation-function' and inserted. ;; If "str" is to be inserted literally, one should obtain it as @@ -1199,13 +1199,14 @@ with output going to the buffer `*compilation*'. You can then use the command \\[next-error] to find the next error message and move to the line in the SGML document that caused it." (interactive - (list (read-string "Validate command: " - (or sgml-saved-validate-command - (concat sgml-validate-command - " " - (when-let* ((name (buffer-file-name))) - (shell-quote-argument - (file-name-nondirectory name)))))))) + (list (read-shell-command "Validate command: " + (or sgml-saved-validate-command + sgml-validate-command + (concat sgml-validate-command + " " + (when-let* ((name (buffer-file-name))) + (shell-quote-argument + (file-name-nondirectory name)))))))) (setq sgml-saved-validate-command command) (save-some-buffers (not compilation-ask-about-save) nil) (compilation-start command)) @@ -1616,6 +1617,8 @@ the current start-tag or the current comment or the current cdata, ..." (and (not sgml-xml-mode) (assoc-string tag-name sgml-unclosed-tags 'ignore-case))) +(defvar sgml-whitespace-sensitive-tags nil + "List of tags where the contents shouldn't be reindented.") (defun sgml-calculate-indent (&optional lcon) "Calculate the column to which this line should be indented. @@ -1628,7 +1631,16 @@ LCON is the lexical context, if any." (save-excursion (goto-char (cdr lcon)) (looking-at "