summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README2
-rw-r--r--admin/admin.el5
-rw-r--r--admin/find-gc.el2
-rw-r--r--admin/gitmerge.el2
-rwxr-xr-xadmin/merge-gnulib5
-rw-r--r--admin/notes/git-workflow10
-rw-r--r--configure.ac61
-rw-r--r--doc/emacs/misc.texi41
-rw-r--r--doc/emacs/programs.texi18
-rw-r--r--doc/misc/calc.texi13
-rw-r--r--doc/misc/eshell.texi104
-rw-r--r--doc/misc/mh-e.texi2
-rw-r--r--doc/misc/rcirc.texi8
-rw-r--r--doc/misc/sc.texi4
-rw-r--r--doc/misc/texinfo.tex177
-rw-r--r--doc/misc/trampver.texi2
-rw-r--r--doc/misc/transient.texi129
-rw-r--r--etc/DEBUG22
-rw-r--r--etc/NEWS4736
-rw-r--r--etc/NEWS.294745
-rw-r--r--etc/PROBLEMS24
-rw-r--r--etc/publicsuffix.txt5
-rw-r--r--etc/refcards/ru-refcard.tex2
-rw-r--r--lib-src/etags.c2
-rw-r--r--lib/explicit_bzero.c74
-rw-r--r--lib/file-has-acl.c120
-rw-r--r--lib/gnulib.mk.in28
-rw-r--r--lib/memset_explicit.c55
-rw-r--r--lib/string.in.h17
-rw-r--r--lib/time.in.h1
-rw-r--r--lib/verify.h2
-rw-r--r--lisp/abbrev.el2
-rw-r--r--lisp/bindings.el2
-rw-r--r--lisp/bs.el95
-rw-r--r--lisp/calc/calc-units.el42
-rw-r--r--lisp/calendar/cal-dst.el12
-rw-r--r--lisp/calendar/diary-lib.el2
-rw-r--r--lisp/calendar/solar.el10
-rw-r--r--lisp/cedet/semantic/complete.el2
-rw-r--r--lisp/cedet/semantic/decorate/include.el8
-rw-r--r--lisp/cedet/semantic/lex-spp.el2
-rw-r--r--lisp/cedet/semantic/lex.el2
-rw-r--r--lisp/comint.el10
-rw-r--r--lisp/cus-edit.el6
-rw-r--r--lisp/descr-text.el2
-rw-r--r--lisp/desktop.el2
-rw-r--r--lisp/elide-head.el55
-rw-r--r--lisp/emacs-lisp/byte-opt.el15
-rw-r--r--lisp/emacs-lisp/byte-run.el6
-rw-r--r--lisp/emacs-lisp/bytecomp.el108
-rw-r--r--lisp/emacs-lisp/cl-macs.el3
-rw-r--r--lisp/emacs-lisp/easy-mmode.el7
-rw-r--r--lisp/emacs-lisp/gv.el6
-rw-r--r--lisp/emacs-lisp/macroexp.el6
-rw-r--r--lisp/emacs-lisp/package.el1
-rw-r--r--lisp/emulation/viper-cmd.el6
-rw-r--r--lisp/eshell/em-alias.el4
-rw-r--r--lisp/eshell/em-cmpl.el26
-rw-r--r--lisp/eshell/em-unix.el12
-rw-r--r--lisp/eshell/esh-arg.el115
-rw-r--r--lisp/eshell/esh-cmd.el54
-rw-r--r--lisp/eshell/esh-io.el174
-rw-r--r--lisp/eshell/esh-opt.el4
-rw-r--r--lisp/eshell/esh-proc.el2
-rw-r--r--lisp/eshell/esh-util.el6
-rw-r--r--lisp/eshell/esh-var.el35
-rw-r--r--lisp/files.el53
-rw-r--r--lisp/frame.el9
-rw-r--r--lisp/gnus/gnus-registry.el2
-rw-r--r--lisp/gnus/mml.el13
-rw-r--r--lisp/gnus/nndiary.el7
-rw-r--r--lisp/help-fns.el4
-rw-r--r--lisp/image-mode.el2
-rw-r--r--lisp/ldefs-boot.el106
-rw-r--r--lisp/mail/rmailout.el5
-rw-r--r--lisp/mh-e/mh-identity.el2
-rw-r--r--lisp/mouse.el20
-rw-r--r--lisp/net/ange-ftp.el24
-rw-r--r--lisp/net/eww.el8
-rw-r--r--lisp/net/gnutls.el10
-rw-r--r--lisp/net/newst-backend.el20
-rw-r--r--lisp/net/rcirc.el21
-rw-r--r--lisp/net/soap-client.el2
-rw-r--r--lisp/net/tramp-adb.el19
-rw-r--r--lisp/net/tramp-crypt.el11
-rw-r--r--lisp/net/tramp-fuse.el10
-rw-r--r--lisp/net/tramp-gvfs.el26
-rw-r--r--lisp/net/tramp-sh.el13
-rw-r--r--lisp/net/tramp-smb.el32
-rw-r--r--lisp/net/tramp-sudoedit.el13
-rw-r--r--lisp/net/tramp.el23
-rw-r--r--lisp/net/trampver.el9
-rw-r--r--lisp/proced.el52
-rw-r--r--lisp/progmodes/c-ts-mode.el4
-rw-r--r--lisp/progmodes/csharp-mode.el5
-rw-r--r--lisp/progmodes/flymake.el2
-rw-r--r--lisp/progmodes/gdb-mi.el69
-rw-r--r--lisp/progmodes/gud.el223
-rw-r--r--lisp/progmodes/java-ts-mode.el5
-rw-r--r--lisp/progmodes/js.el5
-rw-r--r--lisp/progmodes/prog-mode.el35
-rw-r--r--lisp/progmodes/sh-script.el4
-rw-r--r--lisp/progmodes/typescript-ts-mode.el5
-rw-r--r--lisp/progmodes/verilog-mode.el1588
-rw-r--r--lisp/server.el134
-rw-r--r--lisp/simple.el88
-rw-r--r--lisp/startup.el2
-rw-r--r--lisp/subr.el43
-rw-r--r--lisp/tab-bar.el177
-rw-r--r--lisp/transient.el34
-rw-r--r--lisp/treesit.el38
-rw-r--r--lisp/url/url-future.el5
-rw-r--r--lisp/use-package/bind-key.el19
-rw-r--r--lisp/vc/vc-git.el228
-rw-r--r--lisp/vc/vc.el33
-rw-r--r--lisp/whitespace.el35
-rw-r--r--m4/explicit_bzero.m423
-rw-r--r--m4/gnulib-common.m457
-rw-r--r--m4/gnulib-comp.m418
-rw-r--r--m4/memset_explicit.m420
-rw-r--r--m4/string_h.m47
-rw-r--r--msdos/sed2v2.inp2
-rw-r--r--nt/README.W322
-rw-r--r--src/alloc.c274
-rw-r--r--src/buffer.h3
-rw-r--r--src/data.c1
-rw-r--r--src/dispnew.c2
-rw-r--r--src/emacs-module.h.in15
-rw-r--r--src/eval.c6
-rw-r--r--src/fileio.c37
-rw-r--r--src/fns.c9
-rw-r--r--src/frame.c49
-rw-r--r--src/frame.h15
-rw-r--r--src/gnutls.c144
-rw-r--r--src/gtkutil.c6
-rw-r--r--src/itree.c2
-rw-r--r--src/itree.h9
-rw-r--r--src/lisp.h21
-rw-r--r--src/module-env-29.h3
-rw-r--r--src/module-env-30.h3
-rw-r--r--src/nsterm.m12
-rw-r--r--src/pdumper.c2
-rw-r--r--src/sysdep.c7
-rw-r--r--src/xdisp.c79
-rw-r--r--src/xfns.c46
-rw-r--r--src/xftfont.c6
-rw-r--r--src/xselect.c932
-rw-r--r--src/xterm.c654
-rw-r--r--src/xterm.h67
-rw-r--r--test/lisp/elide-head-tests.el106
-rw-r--r--test/lisp/emacs-lisp/bytecomp-tests.el172
-rw-r--r--test/lisp/emacs-lisp/cl-lib-tests.el5
-rw-r--r--test/lisp/emacs-lisp/multisession-tests.el2
-rw-r--r--test/lisp/eshell/em-alias-tests.el9
-rw-r--r--test/lisp/eshell/em-extpipe-tests.el2
-rw-r--r--test/lisp/eshell/em-script-tests.el32
-rw-r--r--test/lisp/eshell/em-tramp-tests.el92
-rw-r--r--test/lisp/eshell/esh-cmd-tests.el46
-rw-r--r--test/lisp/eshell/esh-io-tests.el85
-rw-r--r--test/lisp/eshell/esh-var-tests.el74
-rw-r--r--test/lisp/eshell/eshell-tests-helpers.el29
-rw-r--r--test/lisp/eshell/eshell-tests.el19
-rw-r--r--test/lisp/net/tramp-tests.el15
-rw-r--r--test/lisp/proced-tests.el105
-rw-r--r--test/lisp/url/url-future-tests.el2
-rw-r--r--test/lisp/whitespace-tests.el18
-rw-r--r--test/manual/noverlay/itree-tests.c182
-rw-r--r--test/src/process-tests.el2
-rw-r--r--test/src/regex-emacs-tests.el4
169 files changed, 10838 insertions, 7255 deletions
diff --git a/README b/README
index 2f11148411b..f982c55b4cd 100644
--- a/README
+++ b/README
@@ -2,7 +2,7 @@ Copyright (C) 2001-2022 Free Software Foundation, Inc.
See the end of the file for license conditions.
-This directory tree holds version 29.0.60 of GNU Emacs, the extensible,
+This directory tree holds version 30.0.50 of GNU Emacs, the extensible,
customizable, self-documenting real-time display editor.
The file INSTALL in this directory says how to build and install GNU
diff --git a/admin/admin.el b/admin/admin.el
index 4743d776918..12c9c10b1a5 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -110,7 +110,7 @@ Root must be the root of an Emacs source tree."
(submatch (1+ (in "0-9."))))))
(set-version-in-file root "configure.ac" version
(rx (and "AC_INIT" (1+ (not (in ?,)))
- ?, (0+ space) ?\[
+ ?, (0+ space)
(submatch (1+ (in "0-9."))))))
(set-version-in-file root "nt/README.W32" version
(rx (and "version" (1+ space)
@@ -843,8 +843,11 @@ $Date: %s $
(package-install pkg)
(require pkg nil t))))
+(declare-function org-html-export-as-html "ox-html.el")
(defvar org-html-postamble)
(defvar org-html-mathjax-template)
+(defvar htmlize-output-type)
+
(defun make-news-html-file (root version)
"Convert the NEWS file into an HTML file."
(interactive (let ((root
diff --git a/admin/find-gc.el b/admin/find-gc.el
index 1c3c419c563..6b0e2a3d803 100644
--- a/admin/find-gc.el
+++ b/admin/find-gc.el
@@ -100,7 +100,7 @@ Also store it in `find-gc-unsafe-list'."
-(defun trace-call-tree (&optional ignored)
+(defun trace-call-tree (&optional _ignored)
(message "Setting up directories...")
(setq find-gc-subrs-called nil)
(let ((case-fold-search nil)
diff --git a/admin/gitmerge.el b/admin/gitmerge.el
index ddd3e184424..1ff8137e154 100644
--- a/admin/gitmerge.el
+++ b/admin/gitmerge.el
@@ -293,7 +293,7 @@ should not be skipped."
"Try to resolve conflicts in FILE with smerge.
Returns non-nil if conflicts remain."
(unless (file-exists-p file) (error "Gitmerge-resolve: Can't find %s" file))
- (with-demoted-errors
+ (with-demoted-errors "Error: %S"
(let ((exists (find-buffer-visiting file)))
(with-current-buffer (let ((enable-local-variables :safe)
(enable-local-eval nil))
diff --git a/admin/merge-gnulib b/admin/merge-gnulib
index d3c5520ad0f..99f834b0ae3 100755
--- a/admin/merge-gnulib
+++ b/admin/merge-gnulib
@@ -33,13 +33,14 @@ GNULIB_MODULES='
crypto/md5 crypto/md5-buffer
crypto/sha1-buffer crypto/sha256-buffer crypto/sha512-buffer
d-type diffseq double-slash-root dtoastr dtotimespec dup2
- environ execinfo explicit_bzero faccessat
+ environ execinfo faccessat
fchmodat fcntl fcntl-h fdopendir file-has-acl
filemode filename filevercmp flexmember fpieee
free-posix fstatat fsusage fsync futimens
getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
ieee754-h ignore-value intprops largefile libgmp lstat
- manywarnings memmem-simple mempcpy memrchr minmax mkostemp mktime
+ manywarnings memmem-simple mempcpy memrchr memset_explicit
+ minmax mkostemp mktime
nanosleep nproc nstrftime
pathmax pipe2 pselect pthread_sigmask
qcopy-acl readlink readlinkat regex
diff --git a/admin/notes/git-workflow b/admin/notes/git-workflow
index 717fc550776..d33f49a1aca 100644
--- a/admin/notes/git-workflow
+++ b/admin/notes/git-workflow
@@ -16,14 +16,14 @@ Initial setup
Then we want to clone the repository. We normally want to have both
the current master and (if there is one) the active release branch
-(eg emacs-28).
+(eg emacs-29).
mkdir ~/emacs
cd ~/emacs
git clone <membername>@git.sv.gnu.org:/srv/git/emacs.git master
cd master
git config push.default current
-git worktree add ../emacs-28 emacs-28
+git worktree add ../emacs-29 emacs-29
You now have both branches conveniently accessible, and you can do
"git pull" in them once in a while to keep updated.
@@ -67,10 +67,10 @@ which will look like
commit 958b768a6534ae6e77a8547a56fc31b46b63710b
-cd ~/emacs/emacs-28
+cd ~/emacs/emacs-29
git cherry-pick -xe 958b768a6534ae6e77a8547a56fc31b46b63710b
-and optionally add "Backport:" to the commit string. Then
+and add "Backport:" to the commit string. Then
git push
@@ -109,7 +109,7 @@ up-to-date by doing a pull. Then start Emacs with
emacs -l admin/gitmerge.el -f gitmerge
You'll be asked for the branch to merge, which will default to
-(eg) 'origin/emacs-28', which you should accept. Merging a local tracking
+(eg) 'origin/emacs-29', which you should accept. Merging a local tracking
branch is discouraged, since it might not be up-to-date, or worse,
contain commits from you which are not yet pushed upstream.
diff --git a/configure.ac b/configure.ac
index df19508d3d3..d0217bdcf4c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@ dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
AC_PREREQ([2.65])
dnl Note this is parsed by (at least) make-dist and lisp/cedet/ede/emacs.el.
-AC_INIT([GNU Emacs], [29.0.60], [bug-gnu-emacs@gnu.org], [],
+AC_INIT([GNU Emacs], [30.0.50], [bug-gnu-emacs@gnu.org], [],
[https://www.gnu.org/software/emacs/])
dnl Set emacs_config_options to the options of 'configure', quoted for the shell,
@@ -1841,7 +1841,9 @@ AC_CHECK_HEADERS_ONCE(
coff.h pty.h
sys/resource.h
sys/utsname.h pwd.h utmp.h util.h
- sanitizer/lsan_interface.h])
+ sanitizer/lsan_interface.h
+ sanitizer/asan_interface.h
+ sanitizer/common_interface_defs.h])
AC_CACHE_CHECK([for ADDR_NO_RANDOMIZE],
[emacs_cv_personality_addr_no_randomize],
@@ -2693,39 +2695,6 @@ if test "${HAVE_X11}" = "yes"; then
export LD_RUN_PATH
fi
- if test "${opsys}" = "gnu-linux"; then
- AC_CACHE_CHECK([whether X on GNU/Linux needs -b to link], [emacs_cv_b_link],
- [AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
- [[XOpenDisplay ("foo");]])],
- [xgnu_linux_first_failure=no],
- [xgnu_linux_first_failure=yes])
- if test "${xgnu_linux_first_failure}" = "yes"; then
- OLD_CPPFLAGS="$CPPFLAGS"
- OLD_LIBS="$LIBS"
- CPPFLAGS="$CPPFLAGS -b i486-linuxaout"
- LIBS="$LIBS -b i486-linuxaout"
- AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],
- [[XOpenDisplay ("foo");]])],
- [xgnu_linux_second_failure=no],
- [xgnu_linux_second_failure=yes])
- if test "${xgnu_linux_second_failure}" = "yes"; then
- # If we get the same failure with -b, there is no use adding -b.
- # So leave it out. This plays safe.
- emacs_cv_b_link=no
- else
- emacs_cv_b_link=yes
- fi
- CPPFLAGS=$OLD_CPPFLAGS
- LIBS=$OLD_LIBS
- else
- emacs_cv_b_link=no
- fi])
- if test "x$emacs_cv_b_link" = xyes ; then
- LD_SWITCH_X_SITE="$LD_SWITCH_X_SITE -b i486-linuxaout"
- C_SWITCH_X_SITE="$C_SWITCH_X_SITE -b i486-linuxaout"
- fi
- fi
-
# Reportedly, some broken Solaris systems have XKBlib.h but are missing
# header files included from there.
AC_CACHE_CHECK([for Xkb], [emacs_cv_xkb],
@@ -3935,21 +3904,10 @@ if test "${HAVE_X11}" = "yes"; then
if test "${HAVE_XCB}" = "yes"; then
AC_CHECK_LIB([X11-xcb], [XGetXCBConnection], [HAVE_X11_XCB=yes])
if test "${HAVE_X11_XCB}" = "yes"; then
- AC_CHECK_LIB([xcb-util], [xcb_aux_sync], [HAVE_XCB_UTIL=yes])
- if test "${HAVE_XCB_UTIL}" = "yes"; then
- AC_DEFINE([USE_XCB], [1],
-[Define to 1 if you have the XCB library and X11-XCB library for mixed
- X11/XCB programming.])
- XCB_LIBS="-lX11-xcb -lxcb -lxcb-util"
- else
- AC_CHECK_LIB([xcb-aux], [xcb_aux_sync], [HAVE_XCB_AUX=yes])
- if test "${HAVE_XCB_AUX}" = "yes"; then
- AC_DEFINE([USE_XCB], [1],
+ AC_DEFINE([USE_XCB], [1],
[Define to 1 if you have the XCB library and X11-XCB library for mixed
- X11/XCB programming.])
- XCB_LIBS="-lX11-xcb -lxcb -lxcb-aux"
- fi
- fi
+X11/XCB programming.])
+ XCB_LIBS="-lX11-xcb -lxcb"
fi
fi
fi
@@ -4217,11 +4175,13 @@ AC_SUBST_FILE([module_env_snippet_26])
AC_SUBST_FILE([module_env_snippet_27])
AC_SUBST_FILE([module_env_snippet_28])
AC_SUBST_FILE([module_env_snippet_29])
+AC_SUBST_FILE([module_env_snippet_30])
module_env_snippet_25="$srcdir/src/module-env-25.h"
module_env_snippet_26="$srcdir/src/module-env-26.h"
module_env_snippet_27="$srcdir/src/module-env-27.h"
module_env_snippet_28="$srcdir/src/module-env-28.h"
module_env_snippet_29="$srcdir/src/module-env-29.h"
+module_env_snippet_30="$srcdir/src/module-env-30.h"
emacs_major_version="${PACKAGE_VERSION%%.*}"
AC_SUBST([emacs_major_version])
@@ -4703,7 +4663,7 @@ AC_SUBST([XINERAMA_LIBS])
### Use Xfixes (-lXfixes) if available
HAVE_XFIXES=no
if test "${HAVE_X11}" = "yes"; then
- XFIXES_REQUIRED=4.0.0
+ XFIXES_REQUIRED=1.0.0
XFIXES_MODULES="xfixes >= $XFIXES_REQUIRED"
EMACS_CHECK_MODULES([XFIXES], [$XFIXES_MODULES])
if test $HAVE_XFIXES = no; then
@@ -5007,6 +4967,7 @@ pthread_sigmask strsignal setitimer \
sendto recvfrom getsockname getifaddrs freeifaddrs \
gai_strerror sync \
getpwent endpwent getgrent endgrent \
+renameat2 \
cfmakeraw cfsetspeed __executable_start log2 pthread_setname_np \
pthread_set_name_np])
LIBS=$OLD_LIBS
diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi
index 29c0bed19c0..702c72bac25 100644
--- a/doc/emacs/misc.texi
+++ b/doc/emacs/misc.texi
@@ -1808,31 +1808,28 @@ you can give each daemon its own server name like this:
emacs --daemon=foo
@end example
-@findex server-stop-automatically
+@vindex server-stop-automatically
The Emacs server can optionally be stopped automatically when
-certain conditions are met. To do this, call the function
-@code{server-stop-automatically} in your init file (@pxref{Init
-File}), with one of the following arguments:
+certain conditions are met. To do this, set the option
+@code{server-stop-automatically} to one of the following values:
-@itemize
-@item
-With the argument @code{empty}, the server is stopped when it has no
-clients, no unsaved file-visiting buffers and no running processes
-anymore.
-
-@item
-With the argument @code{delete-frame}, when the last client frame is
-being closed, you are asked whether each unsaved file-visiting buffer
-must be saved and each unfinished process can be stopped, and if so,
-the server is stopped.
-
-@item
-With the argument @code{kill-terminal}, when the last client frame is
-being closed with @kbd{C-x C-c} (@code{save-buffers-kill-terminal}),
-you are asked whether each unsaved file-visiting buffer must be saved
-and each unfinished process can be stopped, and if so, the server is
+@table @code
+@item empty
+This value causes the server to be stopped when it has no clients, no
+unsaved file-visiting buffers and no running processes anymore.
+
+@item delete-frame
+This value means that when the last client frame is being closed, you
+are asked whether each unsaved file-visiting buffer must be saved and
+each unfinished process can be stopped, and if so, the server is
stopped.
-@end itemize
+
+@item kill-terminal
+This value means that when the last client frame is being closed with
+@kbd{C-x C-c} (@code{save-buffers-kill-terminal}), you are asked
+whether each unsaved file-visiting buffer must be saved and each
+unfinished process can be stopped, and if so, the server is stopped.
+@end table
@findex server-eval-at
If you have defined a server by a unique server name, it is possible
diff --git a/doc/emacs/programs.texi b/doc/emacs/programs.texi
index 954f4c892e2..3812c2aa281 100644
--- a/doc/emacs/programs.texi
+++ b/doc/emacs/programs.texi
@@ -420,6 +420,9 @@ large chunks of code:
@table @kbd
@item C-M-q
Reindent all the lines within one parenthetical grouping.
+@item M-q
+Fill a single paragraph in a defun, or reindent all the lines within
+that defun.
@item C-u @key{TAB}
Shift an entire parenthetical grouping rigidly sideways so that its
first line is properly indented.
@@ -440,6 +443,21 @@ indentation of the line where the grouping starts). The function that
etc. To correct the overall indentation as well, type @kbd{@key{TAB}}
first.
+@kindex M-q
+@findex prog-fill-reindent-defun
+@vindex beginning-of-defun-function
+@vindex end-of-defun-function
+@vindex fill-paragraph-function
+ To reindent the entire defun around point, type @kbd{M-q}
+(@code{prog-fill-reindent-defun}). If point is in a comment or a
+string, this command fills and indents the comment or string instead.
+What exactly constitutes a comment, a string, or a defun depends on
+the major mode: the bounds of a defun are decided by the variables
+@code{beginning-of-defun-function} and @code{end-of-defun-function}
+(@pxref{List Motion,,, elisp, The Emacs Lisp Reference Manual}),
+and the filling mechanism is decided by @code{fill-paragraph-function}
+(@pxref{Filling,,, elisp, The Emacs Lisp Reference Manual}).
+
@kindex C-u TAB
If you like the relative indentation within a grouping but not the
indentation of its first line, move point to that first line and type
diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi
index 89a340e7343..e5bac25cac8 100644
--- a/doc/misc/calc.texi
+++ b/doc/misc/calc.texi
@@ -11040,7 +11040,8 @@ the year even for older dates. The customizable variable
have Calc's date forms switch from the Julian to Gregorian calendar at
any specified date.
-Today's timekeepers introduce an occasional ``leap second''.
+A few platforms support leap seconds, such as the time stamp
+1972-06-30 23:59:60 UTC, an extra second appended to June 1972.
These do not occur regularly and Calc does not take these minor
effects into account. (If it did, it would have to report a
non-integer number of days between, say,
@@ -17340,8 +17341,12 @@ it can be a variable which is a time zone name in upper- or lower-case.
For example @samp{tzone(PST) = tzone(8)} and @samp{tzone(pdt) = tzone(7)}
(for Pacific standard and daylight saving times, respectively).
-North American and European time zone names are defined as follows;
-note that for each time zone there is one name for standard time,
+North American and European time zone names are defined as follows.
+These names are obsolescent and new code should not rely on them:
+the @samp{YST}-related names have disagreed with time in Yukon since 1973,
+and other names could well become confusing or wrong in the future
+as countries change their time zone rules.
+For each time zone there is one name for standard time,
another for daylight saving time, and a third for ``generalized'' time
in which the daylight saving adjustment is computed from context.
@@ -17363,7 +17368,7 @@ To define time zone names that do not appear in the above table,
you must modify the Lisp variable @code{math-tzone-names}. This
is a list of lists describing the different time zone names; its
structure is best explained by an example. The three entries for
-Pacific Time look like this:
+circa-2022 US Pacific Time look like this:
@smallexample
@group
diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index 8aa160d84eb..118ee80acb9 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -349,9 +349,9 @@ alias (@pxref{Aliases}). Example:
@example
~ $ which sudo
eshell/sudo is a compiled Lisp function in `em-tramp.el'.
-~ $ alias sudo '*sudo $*'
+~ $ alias sudo '*sudo $@@*'
~ $ which sudo
-sudo is an alias, defined as "*sudo $*"
+sudo is an alias, defined as "*sudo $@@*"
@end example
@vindex eshell-prefer-lisp-functions
@@ -475,7 +475,7 @@ Manual}.
If @code{eshell-plain-diff-behavior} is non-@code{nil}, then this
command does not use Emacs's internal @code{diff}. This is the same
-as using @samp{alias diff '*diff $*'}.
+as using @samp{alias diff '*diff $@@*'}.
@item dirname
@cmindex dirname
@@ -545,9 +545,9 @@ but use Emacs's internal @code{grep} instead.
If @code{eshell-plain-grep-behavior} is non-@code{nil}, then these
commands do not use Emacs's internal @code{grep}. This is the same as
-using @samp{alias grep '*grep $*'}, though this setting applies to all
-of the built-in commands for which you would need to create a separate
-alias.
+using @samp{alias grep '*grep $@@*'}, though this setting applies to
+all of the built-in commands for which you would need to create a
+separate alias.
@item history
@cmindex history
@@ -603,7 +603,7 @@ Alias to Emacs's @code{locate} function, which simply runs the external
If @code{eshell-plain-locate-behavior} is non-@code{nil}, then Emacs's
internal @code{locate} is not used. This is the same as using
-@samp{alias locate '*locate $*'}.
+@samp{alias locate '*locate $@@*'}.
@item ls
@cmindex ls
@@ -1027,24 +1027,47 @@ necessary. Its value is @code{@var{emacs-version},eshell}.
@node Aliases
@section Aliases
-@vindex $*
+@findex eshell-read-aliases-list
Aliases are commands that expand to a longer input line. For example,
-@command{ll} is a common alias for @code{ls -l}, and would be defined
-with the command invocation @kbd{alias ll 'ls -l $*'}; with this defined,
-running @samp{ll foo} in Eshell will actually run @samp{ls -l foo}.
-Aliases defined (or deleted) by the @command{alias} command are
-automatically written to the file named by @code{eshell-aliases-file},
-which you can also edit directly (although you will have to manually
-reload it).
-
-@vindex $1, $2, @dots{}
+@command{ll} is a common alias for @code{ls -l}. To define this alias
+in Eshell, you can use the command invocation @kbd{alias ll 'ls -l
+$@@*'}; with this defined, running @samp{ll foo} in Eshell will
+actually run @samp{ls -l foo}. Aliases defined (or deleted) by the
+@command{alias} command are automatically written to the file named by
+@code{eshell-aliases-file}, which you can also edit directly. After
+doing so, use @w{@kbd{M-x eshell-read-aliases-list}} to load the
+edited aliases.
+
Note that unlike aliases in Bash, arguments must be handled
-explicitly. Typically the alias definition would end in @samp{$*} to
-pass all arguments along. More selective use of arguments via
-@samp{$1}, @samp{$2}, etc., is also possible. For example,
+explicitly. Within aliases, you can use the special variables
+@samp{$*}, @samp{$0}, @samp{$1}, @samp{$2}, etc. to refer to the
+arguments passed to the alias.
+
+@table @code
+
+@vindex $*
+@item $*
+This expands to the list of arguments passed to the alias. For
+example, if you run @code{my-alias 1 2 3}, then @samp{$*} would be the
+list @code{(1 2 3)}. Note that since this variable is a list, using
+@samp{$*} in an alias will pass this list as a single argument to the
+aliased command. Therefore, when defining an alias, you should
+usually use @samp{$@@*} to pass all arguments along, splicing them
+into your argument list (@pxref{Dollars Expansion}).
+
+@vindex $0
+@item $0
+This expands to the name of the alias currently being executed.
+
+@vindex $1, $2, @dots{}, $9
+@item $1, $2, @dots{}, $9
+These variables expand to the nth argument (starting at 1) passed to
+the alias. This lets you selectively use an alias's arguments, so
@kbd{alias mcd 'mkdir $1 && cd $1'} would cause @kbd{mcd foo} to
create and switch to a directory called @samp{foo}.
+@end table
+
@node History
@section History
@cmindex history
@@ -1306,12 +1329,36 @@ to split the string. @var{regexp} can be any form other than a
number. For example, @samp{$@var{var}[: 0]} will return the first
element of a colon-delimited string.
+@cindex length operator, in variable expansion
@item $#@var{expr}
-Expands to the length of the result of @var{expr}, an expression in
-one of the above forms. For example, @samp{$#@var{var}} returns the
-length of the variable @var{var} and @samp{$#@var{var}[0]} returns the
-length of the first element of @var{var}. Again, signals an error if
-the result of @var{expr} is not a string or a sequence.
+This is the @dfn{length operator}. It expands to the length of the
+result of @var{expr}, an expression in one of the above forms. For
+example, @samp{$#@var{var}} returns the length of the variable
+@var{var} and @samp{$#@var{var}[0]} returns the length of the first
+element of @var{var}. Again, signals an error if the result of
+@var{expr} is not a string or a sequence.
+
+@cindex splice operator, in variable expansion
+@item $@@@var{expr}
+This is the @dfn{splice operator}. It ``splices'' the elements of
+@var{expr} (an expression of one of the above forms) into the
+resulting list of arguments, much like the @samp{,@@} marker in Emacs
+Lisp (@pxref{Backquote, , , elisp, The Emacs Lisp Reference Manual}).
+The elements of @var{expr} become arguments at the same level as the
+other arguments around it. For example, if @var{numbers} is the list
+@code{(1 2 3)}, then:
+
+@example
+@group
+~ $ echo 0 $numbers
+(0
+ (1 2 3))
+@end group
+@group
+~ $ echo 0 $@@numbers
+(0 1 2 3)
+@end group
+@end example
@end table
@@ -2030,7 +2077,7 @@ Allow for a Bash-compatible syntax, such as:
@example
alias arg=blah
-function arg () @{ blah $* @}
+function arg () @{ blah $@@* @}
@end example
@item Pcomplete sometimes gets stuck
@@ -2115,11 +2162,6 @@ So that @kbd{M-@key{DEL}} acts in a predictable manner, etc.
@item Allow all Eshell buffers to share the same history and list-dir
-@item There is a problem with script commands that output to @file{/dev/null}
-
-If a script file, somewhere in the middle, uses @samp{> /dev/null},
-output from all subsequent commands is swallowed.
-
@item Split up parsing of text after @samp{$} in @file{esh-var.el}
Make it similar to the way that @file{esh-arg.el} is structured.
diff --git a/doc/misc/mh-e.texi b/doc/misc/mh-e.texi
index 1a80c62edba..0650ad69a8d 100644
--- a/doc/misc/mh-e.texi
+++ b/doc/misc/mh-e.texi
@@ -793,7 +793,7 @@ You should see the scan line for your message, and perhaps others. Use
@cartouche
@smallexample
- 3 t08/24 root received fax files on Wed Aug 24 11:00:13 PDT 1
+ 3 t08/24 root received fax files on Wed Aug 24 11:00:13 -0700 1
# 4+t08/24 To:wohler Test<<This is a test message to get the wheels
-:%% @{+inbox/select@} 4 msgs (1-4) Bot L4 (MH-Folder Show)---------
diff --git a/doc/misc/rcirc.texi b/doc/misc/rcirc.texi
index 84933a9ca72..37d62c7c41a 100644
--- a/doc/misc/rcirc.texi
+++ b/doc/misc/rcirc.texi
@@ -691,11 +691,11 @@ window is showing them), the mode line will now show you the abbreviated
channel or nick name. Use @kbd{C-c C-@key{SPC}} to switch to these
buffers.
-@cindex rcirc-track-abbrevate-flag
+@cindex rcirc-track-abbreviate-flag
By default the channel names are abbreviated, set
-@code{rcirc-track-abbrevate-flag} to a non-@code{nil} value. This might be
-interesting if the IRC activities are not tracked in the mode line,
-but somewhere else.
+@code{rcirc-track-abbreviate-flag} to a non-@code{nil} value. This
+might be interesting if the IRC activities are not tracked in the mode
+line, but somewhere else.
@vindex rcirc-mode-hook
If you prefer not to load @code{rcirc} immediately, you can delay the
diff --git a/doc/misc/sc.texi b/doc/misc/sc.texi
index 3f6dcd022a5..49c86f68127 100644
--- a/doc/misc/sc.texi
+++ b/doc/misc/sc.texi
@@ -404,7 +404,7 @@ from the alist with the @code{sc-mail-field} function. Thus, if the
following fields were present in the original article:
@example
-Date:@: 08 April 1991, 17:32:09 EST
+Date:@: 08 Apr 1991 17:32:09 -0500
Subject:@: Better get out your asbestos suit
@end example
@@ -415,7 +415,7 @@ then, the following lisp constructs return:
@example
(sc-mail-field "date")
-==> "08 April 1991, 17:32:09 EST"
+==> "08 Apr 1991 17:32:09 -0500"
(sc-mail-field "subject")
==> "Better get out your asbestos suit"
diff --git a/doc/misc/texinfo.tex b/doc/misc/texinfo.tex
index cfc77a84ea8..cfe83359f65 100644
--- a/doc/misc/texinfo.tex
+++ b/doc/misc/texinfo.tex
@@ -3,7 +3,7 @@
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
-\def\texinfoversion{2022-11-12.22}
+\def\texinfoversion{2022-12-19.22}
%
% Copyright 1985, 1986, 1988, 1990-2022 Free Software Foundation, Inc.
%
@@ -591,6 +591,9 @@
% @/ allows a line break.
\let\/=\allowbreak
+% @- allows explicit insertion of hyphenation points
+\def\-{\discretionary{\normaldash}{}{}}%
+
% @. is an end-of-sentence period.
\def\.{.\spacefactor=\endofsentencespacefactor\space}
@@ -1537,9 +1540,10 @@ output) for that.)}
\next}
\def\makelink{\addtokens{\toksB}%
{\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
- \def\pdflink#1{%
+ \def\pdflink#1{\pdflinkpage{#1}{#1}}%
+ \def\pdflinkpage#1#2{%
\startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
- \setcolor{\linkcolor}#1\endlink}
+ \setcolor{\linkcolor}#2\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
\else
% non-pdf mode
@@ -1786,10 +1790,11 @@ output) for that.)}
\next}
\def\makelink{\addtokens{\toksB}%
{\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
- \def\pdflink#1{%
+ \def\pdflink#1{\pdflinkpage{#1}{#1}}%
+ \def\pdflinkpage#1#2{%
\special{pdf:bann << /Border [0 0 0]
/Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}%
- \setcolor{\linkcolor}#1\endlink}
+ \setcolor{\linkcolor}#2\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
%
%
@@ -2134,6 +2139,11 @@ end
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
\fi\fi
+%
+% This is what gets called when #5 of \setfont is empty.
+\let\cmap\gobble
+%
+% (end of cmaps)
% Set the font macro #1 to the font named \fontprefix#2.
@@ -2149,11 +2159,10 @@ end
\def\setfont#1#2#3#4#5{%
\font#1=\fontprefix#2#3 scaled #4
\csname cmap#5\endcsname#1%
+ \ifx#2\ttshape\hyphenchar#1=-1 \fi
+ \ifx#2\ttbshape\hyphenchar#1=-1 \fi
+ \ifx#2\ttslshape\hyphenchar#1=-1 \fi
}
-% This is what gets called when #5 of \setfont is empty.
-\let\cmap\gobble
-%
-% (end of cmaps)
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
@@ -2815,13 +2824,6 @@ end
% @sansserif, explicit sans.
\def\sansserif#1{{\sf #1}}
-% We can't just use \exhyphenpenalty, because that only has effect at
-% the end of a paragraph. Restore normal hyphenation at the end of the
-% group within which \nohyphenation is presumably called.
-%
-\def\nohyphenation{\hyphenchar\font = -1 \aftergroup\restorehyphenation}
-\def\restorehyphenation{\hyphenchar\font = `- }
-
\newif\iffrenchspacing
\frenchspacingfalse
@@ -2890,27 +2892,29 @@ end
% Switch to typewriter.
\tt
%
- % But `\ ' produces the large typewriter interword space.
+ % `\ ' produces the large typewriter interword space.
\def\ {{\spaceskip = 0pt{} }}%
%
- % Turn off hyphenation.
- \nohyphenation
- %
\plainfrenchspacing
#1%
}%
\null % reset spacefactor to 1000
}
-% We *must* turn on hyphenation at `-' and `_' in @code.
-% (But see \codedashfinish below.)
+% This is for LuaTeX: It is not sufficient to disable hyphenation at
+% explicit dashes by setting `\hyphenchar` to -1.
+\def\dashnobreak{%
+ \normaldash
+ \penalty 10000 }
+
+% We must turn on hyphenation at `-' and `_' in @code.
% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
+% We explicitly allow hyphenation at these characters
+% using \discretionary.
%
-% Unfortunately, TeX uses one parameter (\hyphenchar) to control
-% both hyphenation at - and hyphenation within words.
-% We must therefore turn them both off (\tclose does that)
-% and arrange explicitly to hyphenate at a dash. -- rms.
+% Hyphenation at - and hyphenation within words was turned off
+% by default for the tt fonts using the \hyphenchar parameter of TeX.
{
\catcode`\-=\active \catcode`\_=\active
\catcode`\'=\active \catcode`\`=\active
@@ -2923,7 +2927,7 @@ end
\let-\codedash
\let_\codeunder
\else
- \let-\normaldash
+ \let-\dashnobreak
\let_\realunder
\fi
% Given -foo (with a single dash), we do not want to allow a break
@@ -3200,7 +3204,7 @@ end
% definition of @key with no lozenge.
%
-\def\key#1{{\setregularquotes \nohyphenation \tt #1}\null}
+\def\key#1{{\setregularquotes \tt #1}\null}
% @clicksequence{File @click{} Open ...}
\def\clicksequence#1{\begingroup #1\endgroup}
@@ -3747,6 +3751,7 @@ $$%
% Open one extra group, as we want to close it in the middle of \Etitlepage.
\begingroup
\parindent=0pt \textfonts
+ \headingsoff
% Leave some space at the very top of the page.
\vglue\titlepagetopglue
% No rule at page bottom unless we print one at the top with @title.
@@ -3774,11 +3779,9 @@ $$%
% If we use the new definition of \page, we always get a blank page
% after the title page, which we certainly don't want.
\oldpage
+ \pageone
\endgroup
%
- % Need this before the \...aftertitlepage checks so that if they are
- % in effect the toc pages will come out with page numbers.
- \HEADINGSon
}
\def\finishtitlepage{%
@@ -3947,7 +3950,6 @@ $$%
}
\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting
-\HEADINGSoff % it's the default
% When we turn headings on, set the page number to 1.
\def\pageone{
@@ -3971,7 +3973,7 @@ $$%
\pageone
\HEADINGSsinglex
}
-\def\HEADINGSon{\HEADINGSdouble}
+% \def\HEADINGSon{\HEADINGSdouble} % defined by \CHAPPAGon
\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdoublex}
\let\HEADINGSdoubleafter=\HEADINGSafter
@@ -5616,6 +5618,11 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\newdimen\entryrightmargin
\entryrightmargin=0pt
+% for PDF output, whether to make the text of the entry a link to the page
+% number. set for @contents and @shortcontents where there is only one
+% page number.
+\newif\iflinkentrytext
+
% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
% then page number (#2) flushed to the right margin. It is used for index
% and table of contents entries. The paragraph is indented by \leftskip.
@@ -5642,7 +5649,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
}
\def\entrybreak{\unskip\space\ignorespaces}%
\def\doentry{%
- % Save the text of the entry
+ % Save the text of the entry in \boxA
\global\setbox\boxA=\hbox\bgroup
\bgroup % Instead of the swallowed brace.
\noindent
@@ -5652,12 +5659,21 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% with catcodes occurring.
}
{\catcode`\@=11
+% #1 is the page number
\gdef\finishentry#1{%
- \egroup % end box A
+ \egroup % end \boxA
\dimen@ = \wd\boxA % Length of text of entry
+ % add any leaders and page number to \boxA.
\global\setbox\boxA=\hbox\bgroup
- \unhbox\boxA
- % #1 is the page number.
+ \ifpdforxetex
+ \iflinkentrytext
+ \pdflinkpage{#1}{\unhbox\boxA}%
+ \else
+ \unhbox\boxA
+ \fi
+ \else
+ \unhbox\boxA
+ \fi
%
% Get the width of the page numbers, and only use
% leaders if they are present.
@@ -5676,6 +5692,8 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi
\fi
\egroup % end \boxA
+ %
+ % now output
\ifdim\wd\boxB = 0pt
\noindent\unhbox\boxA\par
\nobreak
@@ -6375,7 +6393,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi
}
-\parseargdef\setchapternewpage{\csname CHAPPAG#1\endcsname}
+\parseargdef\setchapternewpage{\csname CHAPPAG#1\endcsname\HEADINGSon}
\def\CHAPPAGoff{%
\global\let\contentsalignmacro = \chappager
@@ -6392,7 +6410,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\global\let\pchapsepmacro=\chapoddpage
\global\def\HEADINGSon{\HEADINGSdouble}}
-\CHAPPAGon
+\setchapternewpage on
% \chapmacro - Chapter opening.
%
@@ -6772,6 +6790,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\def\thistitle{}% no title in double-sided headings
% Record where the Roman numerals started.
\ifnum\romancount=0 \global\romancount=\pagecount \fi
+ \linkentrytexttrue
}
% \raggedbottom in plain.tex hardcodes \topskip so override it
@@ -6899,7 +6918,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Chapters, in the short toc.
% See comments in \dochapentry re vbox and related settings.
\def\shortchapentry#1#2#3#4{%
- \tocentry{\shortchaplabel{#2}\labelspace #1}{\doshortpageno\bgroup#4\egroup}%
+ \tocentry{\shortchaplabel{#2}\labelspace #1}{#4}%
}
% Appendices, in the main contents.
@@ -6914,7 +6933,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Unnumbered chapters.
\def\unnchapentry#1#2#3#4{\dochapentry{#1}{#4}}
-\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{\doshortpageno\bgroup#4\egroup}}
+\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{#4}}
% Sections.
\def\numsecentry#1#2#3#4{\dosecentry{#2\labelspace#1}{#4}}
@@ -6946,24 +6965,24 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Move the page numbers slightly to the right
\advance\entryrightmargin by -0.05em
\chapentryfonts
- \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+ \tocentry{#1}{#2}%
\endgroup
\nobreak\vskip .25\baselineskip plus.1\baselineskip
}
\def\dosecentry#1#2{\begingroup
\secentryfonts \leftskip=\tocindent
- \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+ \tocentry{#1}{#2}%
\endgroup}
\def\dosubsecentry#1#2{\begingroup
\subsecentryfonts \leftskip=2\tocindent
- \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+ \tocentry{#1}{#2}%
\endgroup}
\def\dosubsubsecentry#1#2{\begingroup
\subsubsecentryfonts \leftskip=3\tocindent
- \tocentry{#1}{\dopageno\bgroup#2\egroup}%
+ \tocentry{#1}{#2}%
\endgroup}
% We use the same \entry macro as for the index entries.
@@ -6972,9 +6991,6 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% Space between chapter (or whatever) number and the title.
\def\labelspace{\hskip1em \relax}
-\def\dopageno#1{{\rm #1}}
-\def\doshortpageno#1{{\rm #1}}
-
\def\chapentryfonts{\secfonts \rm}
\def\secentryfonts{\textfonts}
\def\subsecentryfonts{\textfonts}
@@ -7410,7 +7426,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\endgroup
%
\def\setupverb{%
- \tt % easiest (and conventionally used) font for verbatim
+ \tt
\def\par{\leavevmode\endgraf}%
\setcodequotes
\tabeightspaces
@@ -7587,32 +7603,28 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\exdentamount=\defbodyindent
}
-\def\dodefunx#1{%
- % First, check whether we are in the right environment:
- \checkenv#1%
- %
- % As above, allow line break if we have multiple x headers in a row.
- % It's not a great place, though.
- \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
- %
- % And now, it's time to reuse the body of the original defun:
- \expandafter\gobbledefun#1%
-}
-\def\gobbledefun#1\startdefun{}
+\newtoks\defidx
+\newtoks\deftext
-% \printdefunline \deffnheader{text}
+\def\useindex#1{\defidx={#1}\ignorespaces}
+
+% Called as \printdefunline \deffooheader{text}
%
\def\printdefunline#1#2{%
\begingroup
\plainfrenchspacing
- % call \deffnheader:
+ % call \deffooheader:
#1#2 \endheader
+ % create the index entry
+ \defcharsdefault
+ \edef\temp{\noexpand\doind{\the\defidx}{\the\deftext}}%
+ \temp
% common ending:
\interlinepenalty = 10000
\advance\rightskip by 0pt plus 1fil\relax
\endgraf
\nobreak\vskip -\parskip
- \penalty\defunpenalty % signal to \startdefun and \dodefunx
+ \penalty\defunpenalty % signal to \startdefun and \deffoox
% Some of the @defun-type tags do not enable magic parentheses,
% rendering the following check redundant. But we don't optimize.
\checkparencounts
@@ -7621,7 +7633,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\def\Edefun{\endgraf\medbreak}
-% \makedefun{deffoo}{ (definition of \deffooheader) }
+% \makedefun{deffoo} (\deffooheader parameters) { (\deffooheader expansion) }
%
% Define \deffoo, \deffoox \Edeffoo and \deffooheader.
\def\makedefun#1{%
@@ -7636,8 +7648,18 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\doingtypefnfalse % distinguish typed functions from all else
\parseargusing\activeparens{\printdefunline#3}%
}%
- \def#2{\dodefunx#1}%
- \def#3%
+ \def#2{%
+ % First, check whether we are in the right environment:
+ \checkenv#1%
+ %
+ % As in \startdefun, allow line break if we have multiple x headers
+ % in a row. It's not a great place, though.
+ \ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
+ %
+ \doingtypefnfalse % distinguish typed functions from all else
+ \parseargusing\activeparens{\printdefunline#3}%
+ }%
+ \def#3% definition of \deffooheader follows
}
\newif\ifdoingtypefn % doing typed function?
@@ -7662,18 +7684,23 @@ might help (with 'rm \jobname.?? \jobname.??s')%
\fi\fi
}
+\def\defind#1#2{
+ \defidx={#1}%
+ \deftext={#2}%
+}
+
% Untyped functions:
% @deffn category name args
\makedefun{deffn}#1 #2 #3\endheader{%
- \doind{fn}{\code{#2}}%
+ \defind{fn}{\code{#2}}%
\defname{#1}{}{#2}\magicamp\defunargs{#3\unskip}%
}
% @defop category class name args
\makedefun{defop}#1 {\defopheaderx{#1\ \putwordon}}
\def\defopheaderx#1#2 #3 #4\endheader{%
- \doind{fn}{\code{#3}\space\putwordon\ \code{#2}}%
+ \defind{fn}{\code{#3}\space\putwordon\ \code{#2}}%
\defname{#1\ \code{#2}}{}{#3}\magicamp\defunargs{#4\unskip}%
}
@@ -7681,7 +7708,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% @deftypefn category type name args
\makedefun{deftypefn}#1 #2 #3 #4\endheader{%
- \doind{fn}{\code{#3}}%
+ \defind{fn}{\code{#3}}%
\doingtypefntrue
\defname{#1}{#2}{#3}\defunargs{#4\unskip}%
}
@@ -7689,7 +7716,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% @deftypeop category class type name args
\makedefun{deftypeop}#1 {\deftypeopheaderx{#1\ \putwordon}}
\def\deftypeopheaderx#1#2 #3 #4 #5\endheader{%
- \doind{fn}{\code{#4}\space\putwordon\ \code{#1\ \code{#2}}}%
+ \defind{fn}{\code{#4}\space\putwordon\ \code{#1\ \code{#2}}}%
\doingtypefntrue
\defname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}%
}
@@ -7698,14 +7725,14 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% @deftypevr category type var args
\makedefun{deftypevr}#1 #2 #3 #4\endheader{%
- \doind{vr}{\code{#3}}%
+ \defind{vr}{\code{#3}}%
\defname{#1}{#2}{#3}\defunargs{#4\unskip}%
}
% @deftypecv category class type var args
\makedefun{deftypecv}#1 {\deftypecvheaderx{#1\ \putwordof}}
\def\deftypecvheaderx#1#2 #3 #4 #5\endheader{%
- \doind{vr}{\code{#4}\space\putwordof\ \code{#2}}%
+ \defind{vr}{\code{#4}\space\putwordof\ \code{#2}}%
\defname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}%
}
@@ -7722,7 +7749,7 @@ might help (with 'rm \jobname.?? \jobname.??s')%
% @deftp category name args
\makedefun{deftp}#1 #2 #3\endheader{%
- \doind{tp}{\code{#2}}%
+ \defind{tp}{\code{#2}}%
\defname{#1}{}{#2}\defunargs{#3\unskip}%
}
@@ -10489,7 +10516,7 @@ directory should work if nowhere else does.}
\DeclareUnicodeCharacter{00AE}{\registeredsymbol{}}%
\DeclareUnicodeCharacter{00AF}{\={ }}%
%
- \DeclareUnicodeCharacter{00B0}{\textdegree}
+ \DeclareUnicodeCharacter{00B0}{\textdegree}%
\DeclareUnicodeCharacter{00B1}{\ensuremath\pm}%
\DeclareUnicodeCharacter{00B2}{$^2$}%
\DeclareUnicodeCharacter{00B3}{$^3$}%
diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi
index c374b6d333b..45cc12b2394 100644
--- a/doc/misc/trampver.texi
+++ b/doc/misc/trampver.texi
@@ -7,7 +7,7 @@
@c In the Tramp GIT, the version number and the bug report address
@c are auto-frobbed from configure.ac.
-@set trampver 2.6.0.29.1
+@set trampver 2.6.0-pre
@set trampurl https://www.gnu.org/software/tramp/
@set tramp-bug-report-address tramp-devel@@gnu.org
@set emacsver 26.1
diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi
index e5e7cccbe8d..2b106bb7141 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.3.7
+@subtitle for version 0.3.7.50
@author Jonas Bernoulli
@page
@vskip 0pt plus 1filll
@@ -65,7 +65,7 @@ Calling a suffix command usually causes the transient to be exited
but suffix commands can also be configured to not exit the transient.
@noindent
-This manual is for Transient version 0.3.7.
+This manual is for Transient version 0.3.7.50.
@insertcopying
@end ifnottex
@@ -447,10 +447,10 @@ session.
Save the value of the active transient persistently across Emacs
sessions.
-@item @kbd{C-x C-k} (@code{transient-save})
+@item @kbd{C-x C-k} (@code{transient-reset})
@kindex C-x C-k
-@findex transient-save
-Clear the set and saved value of the active transient.
+@findex transient-reset
+Clear the set and saved values of the active transient.
@end table
@defopt transient-values-file
@@ -911,7 +911,6 @@ means the former. @xref{Suffix Specifications}.
@var{SUFFIX} may also be a group in the same form as expected by
@code{transient-define-prefix}. @xref{Group Specifications}.
-
@item
@var{LOC} is a command, a key vector, a key description (a string as
returned by @code{key-description}), or a list specifying coordinates (the
@@ -1044,6 +1043,18 @@ For example, the scope of the @code{magit-branch-configure} transient is
the branch whose variables are being configured.
@end defmac
+It is possible to define one or more groups independently of a prefix
+definition, which is useful when those groups are to be used by more
+than just one prefix command.
+
+@defmac transient-define-groups name group...
+This macro defines one or more groups of infix and suffix commands
+and stores them in a property of the symbol @var{NAME}. @var{GROUP} has the
+same form as for @code{transient-define-prefix}. Subsequently @var{NAME} can
+be used in a @var{GROUP} of @code{transient-define-prefix}, as described in the
+next section.
+@end defmac
+
@node Binding Suffix and Infix Commands
@section Binding Suffix and Infix Commands
@@ -1139,11 +1150,17 @@ suffixes, which assumes that a predicate like this is used:
@item
The value of @code{:setup-children}, if non-@code{nil}, is a function that takes
-two arguments the group object itself and a list of children.
-The children are given as a (potentially empty) list consisting
-of either group or suffix specifications. It can make arbitrary
-changes to the children including constructing new children from
-scratch. Also see @code{transient-setup-children}.
+one argument, a potentially list of children, and must return a list
+of children or an empty list. This can either be used to somehow
+transform the group's children that were defined the normal way, or
+to dynamically create the children from scratch.
+
+The returned children must have the same form as stored in the
+prefix's @code{transient--layout} property, but it is often more convenient
+to use the same form as understood by @code{transient-define-prefix},
+described below. If you use the latter approach, you can use the
+@code{transient-parse-child} and @code{transient-parse-children} functions to
+transform them from the convenient to the expected form.
@item
The boolean @code{:pad-keys} argument controls whether keys of all suffixes
@@ -1151,23 +1168,35 @@ contained in a group are right padded, effectively aligning the
descriptions.
@end itemize
-The @var{ELEMENT}s are either all subgroups (vectors), or all suffixes
-(lists) and strings. (At least currently no group type exists that
-would allow mixing subgroups with commands at the same level, though
-in principle there is nothing that prevents that.)
+The @var{ELEMENT}s are either all subgroups, or all suffixes and strings.
+(At least currently no group type exists that would allow mixing
+subgroups with commands at the same level, though in principle there
+is nothing that prevents that.)
If the @var{ELEMENT}s are not subgroups, then they can be a mixture of lists
-that specify commands and strings. Strings are inserted verbatim.
-The empty string can be used to insert gaps between suffixes, which is
-particularly useful if the suffixes are outlined as a table.
-
-Variables are supported inside group specifications. For example in
-place of a direct subgroup specification, a variable can be used whose
-value is a vector that qualifies as a group specification. Likewise,
-a variable can be used where a suffix specification is expected.
-Lists of group or suffix specifications are also supported. Indirect
-specifications are resolved when the transient prefix is being
-defined.
+that specify commands and strings. Strings are inserted verbatim into
+the buffer. The empty string can be used to insert gaps between
+suffixes, which is particularly useful if the suffixes are outlined as
+a table.
+
+Inside group specifications, including inside contained suffix
+specifications, nothing has to be quoted and quoting anyway is
+invalid.
+
+How symbols are treated, depends on context. Inside suffix
+specifications they often name functions. However if they appear in
+a place where a group is expected, then they are treated as indirect
+group specifications. Such a symbol must have an associated group
+specification, created using @code{transient-define-groups}.
+
+Likewise a symbol can appear in a place where a suffix specification
+is expected. The value of the @code{transient--layout} property of that
+symbol must be a single suffix specification or a list of such
+specifications. Currently no macro exist that would create such a
+symbol, and this feature should usually not be used.
+
+The value following a keyword, can be explicitly unquoted using @code{,}.
+This feature is experimental and should be avoided as well.
The form of suffix specifications is documented in the next node.
@@ -1232,7 +1261,7 @@ Any command will do; it does not need to have an object associated
with it (as would be the case if @code{transient-define-suffix} or
@code{transient-define-infix} were used to define it).
-Anonymous, dynamically defined suffix commands are also support.
+Anonymous, dynamically defined suffix commands are also supported.
See information about the @code{:setup-children} function in @ref{Group Specifications}.
As mentioned above, the object that is associated with a command can
@@ -1515,7 +1544,18 @@ Call the command without exporting variables and stay transient.
@anchor{Pre-commands for Suffixes}
@subheading Pre-commands for Suffixes
-The default for suffixes is @code{transient--do-exit}.
+By default, invoking a suffix causes the transient to be exited.
+
+If you want a different default behavior for a certain transient
+prefix command, then set its @code{:transient-suffix} slot. The value can be
+a boolean, answering the question "does the transient stay active,
+when a suffix command is invoked?" @code{t} means that the transient stays
+active, while @code{nil} means that invoking a suffix exits the transient.
+In either case, the exact behavior depends on whether the suffix is
+itself a prefix (i.e., a sub-prefix), an infix or a regular suffix.
+
+The behavior for an individual suffix command can be changed by
+setting its @code{transient} slot to one of the following pre-commands.
@defun transient--do-exit
Call the command after exporting variables and exit the transient.
@@ -1566,21 +1606,32 @@ be added to @code{transient-predicate-map}.
@anchor{Pre-commands for Non-Suffixes}
@subheading Pre-commands for Non-Suffixes
-The default for non-suffixes, i.e., commands that are bound in other
-keymaps beside the transient keymap, is @code{transient--do-warn}. Silently
-ignoring the user-error is also an option, though probably not a good
-one.
+By default, non-suffixes (commands that are bound in other keymaps
+beside the transient keymap) cannot be invoked. Trying to invoke
+such a command results in a warning and the transient stays active.
-If you want to let the user invoke non-suffix commands, then use
-@code{transient--do-stay} as the value of the prefix's @code{transient-non-suffix}
-slot.
+If you want a different behavior, then set the @code{:transient-non-suffix}
+slot of the transient prefix command. The value can be a boolean,
+answering the question, "is it allowed to invoke non-suffix commands?"
+
+If the value is @code{t} or @code{transient--do-stay}, then non-suffixes can be
+invoked, when it is @code{nil} or @code{transient--do-warn} (the default) then they
+cannot be invoked.
+
+The only other recommended value is @code{transient--do-leave}. If that is
+used, then non-suffixes can be invoked, but if one is invoked, then
+that exits the transient.
@defun transient--do-warn
Call @code{transient-undefined} and stay transient.
@end defun
-@defun transient--do-noop
-Call @code{transient-noop} and stay transient.
+@defun transient--do-stay
+Call the command without exporting variables and stay transient.
+@end defun
+
+@defun transient--do-leave
+Call the command without exporting variables and exit the transient.
@end defun
@anchor{Special Pre-Commands}
@@ -1810,7 +1861,7 @@ indicates that all remaining arguments are files.
@item
Classes used for infix commands that represent variables should
-derived from the abstract @code{transient-variables} class.
+derived from the abstract @code{transient-variable} class.
@end itemize
Magit defines additional classes, which can serve as examples for the
@@ -2045,7 +2096,7 @@ called with no argument and returns a string.
@item
@code{show-help} A function used to display help for the suffix. If
-unspecified, the prefix controls how hlep is displayed for its
+unspecified, the prefix controls how help is displayed for its
suffixes.
@end itemize
diff --git a/etc/DEBUG b/etc/DEBUG
index ee134999dac..382e7cb7b6d 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -1007,6 +1007,28 @@ Address sanitization is incompatible with undefined-behavior
sanitization, unfortunately. Address sanitization is also
incompatible with the --with-dumping=unexec option of 'configure'.
+*** Address poisoning/unpoisoning
+
+When compiled with address sanitization, Emacs will also try to mark
+dead/free lisp objects as poisoned, forbidding them from being
+accessed without being unpoisoned first. This adds an extra layer
+of checking with objects in internal free lists, which may otherwise
+evade traditional use-after-free checks. To disable this, add
+'allow_user_poisoning=0' to ASAN_OPTIONS, or build Emacs with
+'-DGC_ASAN_POISON_OBJECTS=0' in CFLAGS.
+
+While using GDB, memory addresses can be inspected by using helper
+functions additionally provided by the ASan library:
+
+ (gdb) call __asan_describe_address(ptr)
+
+To check whether an address range is poisoned or not, use:
+
+ (gdb) call __asan_region_is_poisoned(ptr, 8)
+
+Additional functions can be found in the header
+'sanitizer/asan_interface.h' in your compiler's headers directory.
+
** Running Emacs under Valgrind
Valgrind <https://valgrind.org/> is free software that can be useful
diff --git a/etc/NEWS b/etc/NEWS
index 38b7865626d..50937f5e962 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -6,10 +6,10 @@ See the end of the file for license conditions.
Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
If possible, use 'M-x report-emacs-bug'.
-This file is about changes in Emacs version 29.
+This file is about changes in Emacs version 30.
See file HISTORY for a list of GNU Emacs versions and release dates.
-See files NEWS.28, NEWS.27, ..., NEWS.18, and NEWS.1-17 for changes
+See files NEWS.29, NEWS.28, ..., NEWS.18, and NEWS.1-17 for changes
in older Emacs versions.
You can narrow news to a specific version by calling 'view-emacs-news'
@@ -22,4702 +22,150 @@ When you add a new item, use the appropriate mark if you are sure it
applies, and please also update docstrings as needed.
-* Installation Changes in Emacs 29.1
-
----
-** Ahead-of-time native compilation can now be specified via configure.
-Use '--with-native-compilation=aot' to specify that all the Lisp files
-in the Emacs tree should be natively compiled ahead of time. (This is
-slow on most machines.)
-
-+++
-** Emacs can be built with the tree-sitter parsing library.
-This library, together with grammar libraries, provides incremental
-parsing capabilities for several popular programming languages and
-other formatted files. Emacs built with this library offers major
-modes, described elsewhere in this file, that are based on the
-tree-sitter's parsers. If you have the tree-sitter library
-installed, the configure script will automatically include it in the
-build; use '--without-tree-sitter' at configure time to disable that.
-
-Emacs modes based on the tree-sitter library require an additional
-grammar library for each mode. These grammar libraries provide the
-tree-sitter library with language-specific lexical analysis and
-parsing capabilities, and are developed separately from the
-tree-sitter library itself. If you don't have a grammar library
-required by some Emacs major mode, and your distro doesn't provide it
-as an installable package, you can compile and install such a library
-yourself. Many libraries can be downloaded from the tree-sitter site:
-
- https://github.com/tree-sitter
-
-To compile such a library, compile the files "scanner.c" and "parser.c"
-(sometimes named "scanner.cc" and "parser.cc") in the "src" subdirectory
-of the library's source tree using the C or C++ compiler, then link
-these two files into a shared library named "libtree-sitter-LANG.so",
-where LANG is the name of the language supported by the grammar as it
-is expected by the Emacs major mode (for example, "c" for 'c-ts-mode',
-"cpp" for 'c++-ts-mode', "python" for 'python-ts-mode', etc.). Then place
-the shared library you've built in the same directory where you keep
-the other shared libraries used by Emacs, or in the "tree-sitter"
-subdirectory of your 'user-emacs-directory', or in a directory
-mentioned in the variable 'treesit-extra-load-path'.
-
-You only need to install language grammar libraries required by the
-Emacs modes you will use, as Emacs loads these libraries only when the
-corresponding mode is turned on in some buffer for the first time in
-an Emacs session.
-
-+++
-** Emacs can be built with built-in support for accessing SQLite databases.
-This uses the popular sqlite3 library, and can be disabled by using
-the '--without-sqlite3' option to the 'configure' script.
-
-+++
-** Support for the WebP image format.
-This support is built by default when the libwebp library is
-available, and includes support for animated WebP images. To disable
-WebP support, use the '--without-webp' configure flag. Image
-specifiers can now use ':type webp'.
-
-+++
-** Emacs has been ported to the Haiku operating system.
-The configuration process should automatically detect and build for
-Haiku. There is also an optional window-system port to Haiku, which
-can be enabled by configuring Emacs with the option '--with-be-app',
-which will require the Haiku Application Kit development headers and a
-C++ compiler to be present on your system. If Emacs is not built with
-the option '--with-be-app', the resulting Emacs will only run in
-text-mode terminals.
-
-To enable Cairo support, ensure that the Cairo and FreeType
-development files are present on your system, and configure Emacs with
-'--with-be-cairo'.
-
-Unlike X, there is no compile-time option to enable or disable
-double-buffering; it is always enabled. To disable it, change the
-frame parameter 'inhibit-double-buffering' instead.
-
----
-** Emacs now installs the ".pdmp" file using a unique fingerprint in the name.
-The file is typically installed using a file name akin to
-"...dir/libexec/emacs/29.1/x86_64-pc-linux-gnu/emacs-<fingerprint>.pdmp".
-If a constant file name is required, the file can be renamed to
-"emacs.pdmp", and Emacs will find it during startup anyway.
-
----
-** Emacs on X now uses XInput 2 for input events.
-If your X server has support and you have the XInput 2 development
-headers installed, Emacs will use the X Input Extension for handling
-input. If this causes problems, you can configure Emacs with the
-option '--without-xinput2' to disable this support.
-
-'(featurep 'xinput2)' can be used to test for the presence of XInput 2
-support from Lisp programs.
-
-+++
-** Emacs now supports being built with pure GTK.
-To use this option, make sure the GTK 3 (version 3.22.23 or later) and
-Cairo development files are installed, and configure Emacs with the
-option '--with-pgtk'. Unlike the default X and GTK build, the
-resulting Emacs binary will work on any underlying window system
-supported by GDK, such as Wayland and Broadway. We recommend that you
-use this configuration only if you are running a window system other
-than X that's supported by GDK. Running this configuration on X is
-known to have problems, such as undesirable frame positioning and
-various issues with keyboard input of sequences such as 'C-;' and
-'C-S-u'.
-
----
-** Emacs no longer reduces the size of the Japanese dictionary.
-Building Emacs includes generation of a Japanese dictionary, which is
-used by Japanese input methods. Previously, the build included a step
-of reducing the size of this dictionary's vocabulary. This vocabulary
-reduction is now optional, by default off. If you need the Emacs
-build to include the vocabulary reduction, configure Emacs with the
-option '--with-small-ja-dic'. In an Emacs source tree already
-configured without that option, you can force the vocabulary reduction
-by saying
-
- make -C leim generate-ja-dic JA_DIC_NO_REDUCTION_OPTION=''
-
-after deleting "lisp/leim/ja-dic/ja-dic.el".
-
----
-** The docstrings of preloaded files are not in "etc/DOC" any more.
-Instead, they're fetched as needed from the corresponding ".elc"
-files, as was already the case for all the non-preloaded files.
+* Installation Changes in Emacs 30.1
-* Startup Changes in Emacs 29.1
-
-+++
-** '--batch' and '--script' now adjust the garbage collection levels.
-These switches now set 'gc-cons-percentage' to 1.0 (up from the
-default of 0.1). This means that batch processes will typically use
-more memory than before, but use less time doing garbage collection.
-Batch jobs that are supposed to run for a long time should adjust the
-limit back down again.
-
-+++
-** Emacs can now be used more easily in an executable script.
-If you start an executable script with
-
- #!/usr/bin/emacs -x
-
-Emacs will start without reading any init files (like with '--quick'),
-and then execute the rest of the script file as Emacs Lisp. When it
-reaches the end of the script, Emacs will exit with an exit code from
-the value of the final form.
-
-+++
-** Emacs now supports setting 'user-emacs-directory' via '--init-directory'.
-Use the '--init-directory' command-line option to set
-'user-emacs-directory'.
-
-+++
-** Emacs now has a '--fingerprint' option.
-This will output a string identifying the current Emacs build, and exit.
-
-+++
-** New hook 'after-pdump-load-hook'.
-This is run at the end of the Emacs startup process, and is meant to
-be used to reinitialize data structures that would normally be done at
-load time.
-
-** Native Compilation
-
-+++
-*** New variable 'inhibit-automatic-native-compilation'.
-If set, Emacs will inhibit native compilation (and won't write
-anything to the eln cache automatically). The variable is initialized
-during Emacs startup from the environment variable
-'EMACS_INHIBIT_AUTOMATIC_NATIVE_COMPILATION'.
-
----
-*** New command 'native-compile-prune-cache'.
-This command deletes old subdirectories of the eln cache (but not the
-ones for the current Emacs version). Note that subdirectories of the
-system directory where the "*.eln" files are installed (usually, the
-last entry in 'native-comp-eln-load-path') are not deleted.
-
----
-*** New function 'startup-redirect-eln-cache'.
-This function can be called in your init files to change the
-user-specific directory where Emacs stores the "*.eln" files produced
-by native compilation of Lisp packages Emacs loads. The default
-eln cache directory is unchanged: it is the "eln-cache" subdirectory
-of 'user-emacs-directory'.
+* Startup Changes in Emacs 30.1
-* Incompatible changes in Emacs 29.1
-
-+++
-** The image commands have changed key bindings.
-In previous Emacs versions, images have had the '+', '-' and 'r' keys
-bound when point is over an image. In Emacs 29.1, additional commands
-were added, and this made it more likely that users would trigger the
-image commands by mistake. To avoid this, all image commands have
-moved to the 'i' keymap, so '+' is now 'i +', '-' is now 'i -', and
-'r' is now 'i r'. In addition, these commands are now repeating, so
-you can rotate an image twice by saying 'i r r', for instance.
-
-+++
-** Emacs now picks the correct coding-system for X input methods.
-Previously, Emacs would use 'locale-coding-system' for input
-methods, which could in some circumstances be incorrect, especially
-when the input method chose to fall back to some other coding system.
-
-Emacs now automatically detects the coding-system used by input
-methods, and uses that to decode input in preference to the value of
-'locale-coding-system'. This unfortunately means that users who have
-changed the coding system used to decode X keyboard input must adjust
-their customizations to 'locale-coding-system' to the variable
-'x-input-coding-system' instead.
-
-+++
-** Bookmarks no longer include context for encrypted files.
-If you're visiting an encrypted file, setting a bookmark no longer
-includes excerpts from that buffer in the bookmarks file. This is
-implemented by the new hook 'bookmark-inhibit-context-functions',
-where packages can register a function which returns non-nil for file
-names to be excluded from adding such excerpts.
-
----
-** 'show-paren-mode' is now disabled in 'special-mode' buffers.
-In Emacs versions previous to Emacs 28.1, 'show-paren-mode' defaulted
-off. In Emacs 28.1, the mode was switched on in all buffers. In
-Emacs 29.1, this was changed to be switched on in all editing-related
-buffers, but not in buffers that inherit from 'special-mode'. To go
-back to how things worked in Emacs 28.1, put the following in your
-init file:
-
- (setopt show-paren-predicate t)
-
-+++
-** Explicitly-set read-only state is preserved when reverting a buffer.
-If you use the 'C-x C-q' command to change the read-only state of the
-buffer and then revert it, Emacs would previously use the file
-permission bits to determine whether the buffer should be read-only
-after reverting the buffer. Emacs now remembers the decision made in
-'C-x C-q'.
-
----
-** The Gtk selection face is no longer used for the region.
-The combination of a Gtk-controlled background and a foreground color
-controlled by the internal Emacs machinery led to low-contrast faces
-in common default setups. Emacs now uses the same 'region' face on
-Gtk and non-Gtk setups.
-
----
-** 'C-h f' and 'C-h x' may now require confirmation when you press 'RET'.
-If the text in the minibuffer cannot be completed to a single function
-or command, typing 'RET' will not automatically complete to the shortest
-candidate, but will instead ask for confirmation. Typing 'TAB' will
-complete as much as possible, and another 'TAB' will show all the
-possible completions. This allows you to insist on the functions name
-even if Help doesn't appear to know about it, by confirming with a
-second 'RET'.
-
-** Dired
-
----
-*** 'w' ('dired-copy-filename-as-kill') has changed behavior.
-If there are several files marked, file names containing space and
-quote characters will be quoted "like this".
-
----
-*** The 'd' command now more consistently skips dot files.
-In previous Emacs versions, commands like 'C-u 10 d' would put the "D"
-mark on the next ten files, no matter whether they were dot files
-(i.e., "." and "..") or not, while marking the next ten lines with the
-mouse (in 'transient-mark-mode') and then hitting 'd' would skip dot
-files. These now work equivalently.
-
-+++
-** Warning about "eager macro-expansion failure" is now an error.
-
----
-** Previously, the X "reverseVideo" value at startup was heeded for all frames.
-This meant that if you had a "reverseVideo" resource on the initial
-display, and then opened up a new frame on a display without any
-explicit "reverseVideo" setting, it would get heeded there, too. (This
-included terminal frames.) In Emacs 29, the "reverseVideo" X resource
-is handled like all the other X resources, and set on a per-frame basis.
-
-+++
-** 'E' in 'query-replace' now edits the replacement with exact case.
-Previously, this command did the same as 'e'.
-
----
-** '/ a' in "*Packages*" buffer now limits by archive name(s) instead of regexp.
-
-+++
-** Setting the goal columns now also affects '<prior>' and '<next>'.
-Previously, 'C-x C-n' only affected 'next-line' and 'previous-line',
-but it now also affects 'scroll-up-command' and 'scroll-down-command'.
-
----
-** Isearch in "*Help*" and "*info*" now char-folds quote characters by default.
-This means that you can say 'C-s `foo' (GRAVE ACCENT) if the buffer
-contains "‘foo" (LEFT SINGLE QUOTATION MARK) and the like. These
-quotation characters look somewhat similar in some fonts. To switch
-this off, disable the new 'isearch-fold-quotes-mode' minor mode.
-
----
-** Sorting commands no longer necessarily change modification status.
-In earlier Emacs versions, commands like 'M-x sort-lines' would always
-change buffer modification status to "modified", whether they changed
-something in the buffer or not. This has been changed: the buffer is
-marked as modified only if the sorting ended up actually changing the
-contents of the buffer.
-
----
-** 'string-lines' handles trailing newlines differently.
-It no longer returns an empty final string if the string ends with a
-newline.
-
----
-** 'TAB' and '<backtab>' are now bound in 'button-map'.
-This means that if point is on a button, 'TAB' will take you to the
-next button, even if the mode has bound it to something else. This
-also means that 'TAB' on a button in an 'outline-minor-mode' heading
-will move point instead of collapsing the outline.
-
----
-** 'Info-default-directory-list' is no longer populated at Emacs startup.
-If you have code in your init file that removes directories from
-'Info-default-directory-list', this will no longer work.
-
----
-** 'C-k' no longer deletes files in 'ido-mode'.
-To get the previous action back, put something like the following in
-your Init file:
-
- (require 'ido)
- (keymap-set ido-file-completion-map "C-k" #'ido-delete-file-at-head)
-
----
-** New user option 'term-clear-full-screen-programs'.
-By default, term.el will now work like most terminals when displaying
-full-screen programs: When they exit, the output is cleared, leaving
-what was displayed in the window before the programs started. Set
-this user option to nil to revert back to the old behavior.
-
----
-** Support for old EIEIO functions is not autoloaded any more.
-You need an explicit '(require 'eieio-compat)' to use 'defmethod'
-and 'defgeneric' (which have been made obsolete in Emacs 25.1 with
-'cl-defmethod' and 'cl-defgeneric').
-Similarly you might need to '(require 'eieio-compat)' before loading
-files that were compiled with an old EIEIO (Emacs<25).
-
----
-** 'C-x 8 .' has been moved to 'C-x 8 . .'.
-This is to open up the 'C-x 8 .' map to bind further characters there.
+* Changes in Emacs 30.1
----
-** 'C-x 8 =' moved to 'C-x 8 = ='.
-You can now use 'C-x 8 =' to insert several characters with macron;
-for example, 'C-x 8 = a' will insert U+0101 LATIN SMALL LETTER A WITH
-MACRON. To insert a lone macron, type 'C-x 8 = =' instead of the
-previous 'C-x ='.
-
-** Eshell
-
-*** Eshell's PATH is now derived from 'exec-path'.
-For consistency with remote connections, Eshell now uses 'exec-path'
-to determine the execution path on the local system, instead of using
-the PATH environment variable directly.
-
----
-*** 'source' and '.' no longer accept the '--help' option.
-This is for compatibility with the shell versions of these commands,
-which don't handle options like '--help' in any special way.
-
-+++
-*** String delimiters in argument predicates/modifiers are more restricted.
-Previously, some argument predicates/modifiers allowed arbitrary
-characters as string delimiters. To provide more unified behavior
-across all predicates/modifiers, the list of allowed delimiters has
-been restricted to "...", '...', /.../, |...|, (...), [...], <...>,
-and {...}. See the "(eshell) Argument Predication and Modification"
-node in the Eshell manual for more details.
-
-+++
-*** Eshell pipelines now only pipe stdout by default.
-To pipe both stdout and stderr, use the '|&' operator instead of '|'.
-
----
-** The 'delete-forward-char' command now deletes by grapheme clusters.
-This command is by default bound to the <Delete> function key
-(a.k.a. <deletechar>). When invoked without a prefix argument or with
-a positive prefix numeric argument, the command will now delete
-complete grapheme clusters produced by character composition. For
-example, if point is before an Emoji sequence, pressing <Delete> will
-delete the entire sequence, not just a single character at its
-beginning.
-
-+++
-** 'load-history' does not treat autoloads specially any more.
-An autoload definition appears just as a '(defun . NAME)' and the
-'(t . NAME)' entries are not generated any more.
-
----
-** The Tamil input methods no longer insert Tamil digits.
-The input methods 'tamil-itrans' and 'tamil-inscript' no longer insert
-the Tamil digits, as those digit characters are not used nowadays by
-speakers of the Tamil language. To get back the previous behavior,
-use the new 'tamil-itrans-digits' and 'tamil-inscript-digits' input
-methods instead.
-
-+++
-** New variable 'current-time-list' governing default timestamp form.
-Functions like 'current-time' now yield '(TICKS . HZ)' timestamps if
-this new variable is nil. The variable defaults to t, which means
-these functions default to timestamps of the forms '(HI LO US PS)',
-'(HI LO US)' or '(HI LO)', which are less regular and less efficient.
-This is part of a long-planned change first documented in Emacs 27.
-Developers are encouraged to test timestamp-related code with this
-variable set to nil, as it will default to nil in a future Emacs
-version and will be removed some time after that.
-
-+++
-** Functions that recreate the "*scratch*" buffer now also initialize it.
-When functions like 'other-buffer' and 'server-execute' recreate
-"*scratch*", they now also insert 'initial-scratch-message' and set
-the major mode according to 'initial-major-mode', like at Emacs
-startup. Previously, these functions ignored
-'initial-scratch-message' and left "*scratch*" in 'fundamental-mode'.
-
----
-** Naming of Image-Dired thumbnail files has changed.
-Names of thumbnail files generated when 'image-dired-thumbnail-storage'
-is 'image-dired' now always end in ".jpg". This fixes various issues
-on different platforms, but means that thumbnails generated in Emacs 28
-will not be used in Emacs 29, and vice-versa. If disk space is an
-issue, consider deleting the 'image-dired-dir' directory (usually
-"~/.emacs.d/image-dired/") after upgrading to Emacs 29.
-
----
-** The 'rlogin' method in the URL library is now obsolete.
-Emacs will now display a warning if you request a URL like
-"rlogin://foo@example.org".
-
----
-** Setting 'url-gateway-method' to 'rlogin' is now obsolete.
-Emacs will now display a warning when setting it to that value.
-The user options 'url-gateway-rlogin-host',
-'url-gateway-rlogin-parameters', and 'url-gateway-rlogin-user-name'
-are also obsolete.
-
----
-** The user function 'url-irc-function' now takes a SCHEME argument.
-The user option 'url-irc-function' is now called with a sixth argument
-corresponding to the scheme portion of the target URL. For example,
-this would be "ircs" for a URL like "ircs://irc.libera.chat".
-
----
-** The linum.el library is now obsolete.
-We recommend using either the built-in 'display-line-numbers-mode', or
-the 'nlinum' package from GNU ELPA instead. The former has better
-performance, but the latter is closer to a drop-in replacement.
-
-1. To use 'display-line-numbers-mode', add something like this to your
- Init file:
-
- (global-display-line-numbers-mode 1)
- ;; Alternatively, to use it only in programming modes:
- (add-hook 'prog-mode-hook #'display-line-numbers-mode)
-
-2. To use 'nlinum', add this to your Init file:
-
- (package-install 'nlinum)
- (global-nlinum-mode 1)
- ;; Alternatively, to use it only in programming modes:
- (add-hook 'prog-mode-hook #'nlinum-mode)
-
-3. To continue using the obsolete package 'linum', add this line to
- your Init file, in addition to any existing customizations:
-
- (require 'linum)
-
----
-** The thumbs.el library is now obsolete.
-We recommend using 'M-x image-dired' instead.
-
----
-** The autoarg.el library is now marked obsolete.
-This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor
-modes to emulate the behavior of the historical editor Twenex Emacs.
-We believe it is no longer useful.
-
----
-** The quickurl.el library is now obsolete.
-Use 'abbrev', 'skeleton' or 'tempo' instead.
-
----
-** The rlogin.el library, and the 'rsh' command are now obsolete.
-Use something like 'M-x shell RET ssh <host> RET' instead.
-
----
-** The url-about.el library is now obsolete.
-
----
-** The autoload.el library is now obsolete.
-It is superseded by the new loaddefs-gen.el library.
-
----
-** The netrc.el library is now obsolete.
-Use the 'auth-source-netrc-parse-all' function in auth-source.el
-instead.
-
----
-** The url-dired.el library is now obsolete.
+** X selection requests are now handled much faster and asynchronously.
+This means it should be less necessary to disable the likes of
+`select-active-regions' when Emacs is running over a slow network
+connection.
----
-** The fast-lock.el and lazy-lock.el libraries have been removed.
-They have been obsolete since Emacs 22.1.
-
-The variable 'font-lock-support-mode' is occasionally useful for
-debugging purposes. It is now a regular variable (instead of a user
-option) and can be set to nil to disable Just-in-time Lock mode.
+** Emacs now updates invisible frames that are made visible by a compositor.
+If an invisible or an iconified frame is shown to the user by the
+compositing manager, Emacs will now redisplay such a frame even though
+'frame-visible-' returns nil or 'icon' for it. This can happen, for
+example, as part of preview for iconified frames.
-* Changes in Emacs 29.1
-
-+++
-** New user option 'major-mode-remap-alist' to specify favorite major modes.
-This user option lets you remap the default modes (e.g. 'perl-mode' or
-'latex-mode') to your favorite ones (e.g. 'cperl-mode' or
-'LaTeX-mode') without having to use 'defalias', which can have
-undesirable side effects.
-This applies to all modes specified via 'auto-mode-alist', file-local
-variables, etc.
-
----
-** Emacs now supports Unicode Standard version 15.0.
-
----
-** New user option 'electric-quote-replace-consecutive'.
-
----
-** Emacs is now capable of editing files with very long lines.
-The display of long lines has been optimized, and Emacs should no
-longer choke when a buffer on display contains long lines. The
-variable 'long-line-threshold' controls whether and when these display
-optimizations are in effect.
+* Editing Changes in Emacs 30.1
-A companion variable 'large-hscroll-threshold' controls when another
-set of display optimizations are in effect, which are aimed
-specifically at speeding up display of long lines that are truncated
-on display.
-
-If you still experience slowdowns while editing files with long lines,
-this may be due to line truncation, or to one of the enabled minor
-modes, or to the current major mode. Try turning off line truncation
-with 'C-x x t', or try disabling all known slow minor modes with
-'M-x so-long-minor-mode', or try disabling both known slow minor modes
-and the major mode with 'M-x so-long-mode', or visit the file with
-'M-x find-file-literally' instead of the usual 'C-x C-f'.
-
-Note that the display optimizations in these cases may cause the
-buffer to be occasionally mis-fontified.
-
-The new function 'long-line-optimizations-p' returns non-nil when
-these optimizations are in effect in the current buffer.
-
-+++
-** New command to change the font size globally.
-To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
-decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x
-C-M-0'. The final key in these commands may be repeated without the
-leading 'C-x' and without the modifiers, e.g. 'C-x C-M-+ C-M-+ C-M-+'
-and 'C-x C-M-+ + +' increase the font size by three steps. When
-'mouse-wheel-mode' is enabled, 'C-M-wheel-up' and 'C-M-wheel-down' also
-increase and decrease the font size globally. Additionally, the
-user option 'global-text-scale-adjust-resizes-frames' controls whether
-the frames are resized when the font size is changed.
-
----
-** New config variable 'syntax-wholeline-max' to reduce the cost of long lines.
-This variable is used by some operations (mostly syntax-propertization
-and font-locking) to treat lines longer than this variable as if they
-were made up of various smaller lines. This can help reduce the
-slowdowns seen in buffers made of a single long line, but can also
-cause misbehavior in the presence of such long lines (though most of
-that misbehavior should usually be limited to mis-highlighting). You
-can recover the previous behavior with:
-
- (setq syntax-wholeline-max most-positive-fixnum)
-
----
-** New bindings in 'find-function-setup-keys' for 'find-library'.
-When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to
-'find-library', 'C-x 4 L' is now bound to 'find-library-other-window'
-and 'C-x 5 L' is now bound to 'find-library-other-frame'.
-
-+++
-** New key binding after 'M-x' or 'M-X': 'M-X'.
-Emacs allows different completion predicates to be used with 'M-x'
-(i.e., 'execute-extended-command') via the
-'read-extended-command-predicate' user option. Emacs also has the
-'M-X' (note upper case X) command, which only displays commands
-especially relevant to the current buffer. Emacs now allows toggling
-between these modes while the user is inputting a command by hitting
-'M-X' while in the minibuffer.
-
----
-** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved.
-
----
-** New commands 'duplicate-line' and 'duplicate-dwim'.
-'duplicate-line' duplicates the current line the specified number of times.
-'duplicate-dwim' duplicates the region if it is active. If not, it
-works like 'duplicate-line'. An active rectangular region is
-duplicated on its right-hand side.
-
----
-** Files with the ".eld" extension are now visited in 'lisp-data-mode'.
-
-+++
-** 'network-lookup-address-info' can now check numeric IP address validity.
-Specifying 'numeric' as the new optional 'hints' argument makes it
-check if the passed address is a valid IPv4/IPv6 address (without DNS
-traffic).
-
- (network-lookup-address-info "127.1" 'ipv4 'numeric)
- => ([127 0 0 1 0])
-
-+++
-** New command 'find-sibling-file'.
-This command jumps to a file considered a "sibling file", which is
-determined according to the new user option 'find-sibling-rules'.
-
-+++
-** New user option 'delete-selection-temporary-region'.
-When non-nil, 'delete-selection-mode' will only delete the temporary
-regions (usually set by mouse-dragging or shift-selection).
-
-+++
-** New user option 'switch-to-prev-buffer-skip-regexp'.
-This should be a regexp or a list of regexps; buffers whose names
-match those regexps will be ignored by 'switch-to-prev-buffer' and
-'switch-to-next-buffer'.
-
-+++
-** New command 'rename-visited-file'.
-This command renames the file visited by the current buffer by moving
-it to a new name or location, and also makes the buffer visit this new
-file.
-
-** Menus
-
----
-*** The entries following the buffers in the "Buffers" menu can now be altered.
-Change the 'menu-bar-buffers-menu-command-entries' variable to alter
-the entries that follow the buffer list.
-
----
-** 'delete-process' is now a command.
-When called interactively, it will kill the process running in the
-current buffer (if any). This can be useful if you have runaway
-output in the current buffer (from a process or a network connection),
-and want to stop it.
-
-+++
-** New command 'restart-emacs'.
-This is like 'save-buffers-kill-emacs', but instead of just killing
-the current Emacs process at the end, it starts a new Emacs process
-(using the same command line arguments as the running Emacs process).
-'kill-emacs' and 'save-buffers-kill-emacs' have also gained new
-optional parameters to restart instead of just killing the current
-process.
+** New helper 'transpose-sexps-function'
+Emacs now can set this defvar to customize the behavior of the
+'transpose-sexps' function.
-** Drag and Drop
-
-+++
-*** New user option 'mouse-drag-mode-line-buffer'.
-If non-nil, dragging on the buffer name part of the mode-line will
-drag the buffer's associated file to other programs. This option is
-currently only available on X, Haiku and Nextstep (GNUstep or macOS).
-
-+++
-*** New user option 'mouse-drag-and-drop-region-cross-program'.
-If non-nil, this option allows dragging text in the region from Emacs
-to another program.
-
----
-*** New user option 'mouse-drag-and-drop-region-scroll-margin'.
-If non-nil, this option allows scrolling a window while dragging text
-around without a scroll wheel.
-
-+++
-*** The value of 'mouse-drag-copy-region' can now be the symbol 'non-empty'.
-This prevents mouse drag gestures from putting empty strings onto the
-kill ring.
-
-+++
-*** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'.
-These options allow adjusting point and scrolling a window when
-dragging items from another program.
-
-+++
-*** The X Direct Save (XDS) protocol is now supported.
-This means dropping an image or file link from programs such as
-Firefox will no longer create a temporary file in a random directory,
-instead asking you where to save the file first.
-
-+++
-** New user option 'record-all-keys'.
-If non-nil, this option will force recording of all input keys,
-including those typed in response to passwords prompt (this was the
-previous behavior). The default is nil, which inhibits recording of
-passwords.
-
-+++
-** New function 'command-query'.
-This function makes its argument command prompt the user for
-confirmation before executing.
-
-+++
-** The 'disabled' property of a command's symbol can now be a list.
-The first element of the list should be the symbol 'query', which will
-cause the command disabled this way prompt the user with a y/n or a
-yes/no question before executing. The new function 'command-query' is
-a convenient method of making commands disabled in this way.
-
----
-** 'count-words' will now report buffer totals if given a prefix.
-Without a prefix, it will only report the word count for the narrowed
-part of the buffer.
-
-+++
-** 'count-words' will now report sentence count when used interactively.
-
-+++
-** New user option 'set-message-functions'.
-It allows selecting more functions for 'set-message-function'
-in addition to the default function that handles messages
-in the active minibuffer. The most useful are 'inhibit-message'
-that allows specifying a list of messages to inhibit via
-'inhibit-message-regexps', and 'set-multi-message' that
-accumulates recent messages and displays them stacked
-in the echo area.
-
----
-** New user option 'find-library-include-other-files'.
-If set to nil, commands like 'find-library' will only include library
-files in the completion candidates. The default is t, which preserves
-previous behavior, whereby non-library files could also be included.
-
-+++
-** New command 'sqlite-mode-open-file' for examining an sqlite3 file.
-This uses the new 'sqlite-mode' which allows listing the tables in a
-DB file, and examining and modifying the columns and the contents of
-those tables.
-
----
-** 'write-file' will now copy some file mode bits.
-If the current buffer is visiting a file that is executable, the
-'C-x C-w' command will now make the new file executable, too.
-
-+++
-** New user option 'process-error-pause-time'.
-This determines how long to pause Emacs after a process
-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-misc-punctuation-face', 'font-lock-operator-face',
-'font-lock-property-face', and 'font-lock-punctuation-face'.
-
-+++
-** New face 'variable-pitch-text'.
-This face is like 'variable-pitch' (from which it inherits), but is
-slightly larger, which should help with the visual size differences
-between the default, non-proportional font and proportional fonts when
-mixed.
-
-+++
-** New face 'mode-line-active'.
-This inherits from the 'mode-line' face, but is the face actually used
-on the mode lines (along with 'mode-line-inactive').
-
-+++
-** New face attribute pseudo-value 'reset'.
-This value stands for the value of the corresponding attribute of the
-'default' face. It can be used to reset attribute values produced by
-inheriting from other faces.
-
-+++
-** New X resource: "borderThickness".
-This controls the thickness of the external borders of the menu bars
-and pop-up menus.
-
-+++
-** New X resource: "inputStyle".
-This controls the style of the pre-edit and status areas of X input
-methods.
-
-+++
-** New X resources: "highlightForeground" and "highlightBackground".
-Only in the Lucid build, this controls colors used for highlighted
-menu item widgets.
-
-+++
-** On X, Emacs now tries to synchronize window resize with the window manager.
-This leads to less flicker and empty areas of a frame being displayed
-when a frame is being resized. Unfortunately, it does not work on
-some ancient buggy window managers, so if Emacs appears to freeze, but
-is still responsive to input, you can turn it off by setting the X
-resource "synchronizeResize" to "off".
-
-+++
-** On X, Emacs can optionally synchronize display with the graphics hardware.
-When this is enabled by setting the X resource "synchronizeResize" to
-"extended", frame content "tearing" is drastically reduced. This is
-only supported on the Motif, Lucid, and no-toolkit builds, and
-requires an X compositing manager supporting the extended frame
-synchronization protocol (see
-https://fishsoup.net/misc/wm-spec-synchronization.html).
-
-This behavior can be toggled on and off via the frame parameter
-'use-frame-synchronization'.
-
-+++
-** New frame parameter 'alpha-background' and X resource "alphaBackground".
-This controls the opacity of the text background when running on a
-composited display.
-
-+++
-** New frame parameter 'shaded'.
-With window managers which support this, it controls whether or not a
-frame's contents will be hidden, leaving only the title bar on display.
-
----
-** New user option 'x-gtk-use-native-input'.
-This controls whether or not GTK input methods are used by Emacs,
-instead of XIM input methods.
-
-+++
-** New user option 'use-system-tooltips'.
-This controls whether to use the toolkit tooltips, or Emacs's own
-native implementation of tooltips as small frames. This option is
-only meaningful if Emacs was built with GTK+, Nextstep, or Haiku
-support, and defaults to t, which makes Emacs use the toolkit
-tooltips. The existing GTK-specific option
-'x-gtk-use-system-tooltips' is now an alias of this new option.
-
-+++
-** Non-native tooltips are now supported on Nextstep.
-This means Emacs built with GNUstep or built on macOS is now able to
-display different faces and images inside tooltips when the
-'use-system-tooltips' user option is nil.
-
----
-** New minor mode 'pixel-scroll-precision-mode'.
-When enabled, and if your mouse supports it, you can scroll the
-display up or down at pixel resolution, according to what your mouse
-wheel reports. Unlike 'pixel-scroll-mode', this mode scrolls the
-display pixel-by-pixel, as opposed to only animating line-by-line
-scrolls.
-
-** Terminal Emacs
-
----
-*** Emacs will now use 24-bit colors on terminals that support "Tc" capability.
-This is in addition to previously-supported ways of discovering 24-bit
-color support: either via the "RGB" or "setf24" capabilities, or if
-the 'COLORTERM' environment variable is set to the value "truecolor".
-
----
-*** Select active regions with xterm selection support.
-On terminals with xterm setSelection support, the active region may be
-saved to the X primary selection, following the
-'select-active-regions' variable. This support is enabled when
-'tty-select-active-regions' is non-nil.
-
----
-*** New command to set up display of unsupported characters.
-The new command 'standard-display-by-replacement-char' produces Lisp
-code that sets up the 'standard-display-table' to use a replacement
-character for display of characters that the text-mode terminal
-doesn't support. This code is intended to be used in your init files.
-This feature is most useful with the Linux console and similar
-terminals, where Emacs has a reliable way of determining which
-characters have glyphs in the font loaded into the terminal's memory.
-
----
-*** New functions to set terminal output buffer size.
-The new functions 'tty--set-output-buffer-size' and
-'tty--output-buffer-size' allow setting and retrieving the output
-buffer size of a terminal device. The default buffer size is and has
-always been BUFSIZ, which is defined in your system's stdio.h. When
-you set a buffer size with 'tty--set-output-buffer-size', this also
-prevents Emacs from explicitly flushing the tty output stream, except
-at the end of display update.
-
-** ERT
-
-+++
-*** New ERT variables 'ert-batch-print-length' and 'ert-batch-print-level'.
-These variables will override 'print-length' and 'print-level' when
-printing Lisp values in ERT batch test results.
-
----
-*** Redefining an ERT test in batch mode now signals an error.
-Executing 'ert-deftest' with the same name as an existing test causes
-the previous definition to be discarded, which was probably not
-intended when this occurs in batch mode. To remedy the error, rename
-tests so that they all have unique names.
-
-+++
-*** ERT can generate JUnit test reports.
-When environment variable 'EMACS_TEST_JUNIT_REPORT' is set, ERT
-generates a JUnit test report under this file name. This is useful
-for Emacs integration into CI/CD test environments.
-
----
-*** Unbound test symbols now signal an 'ert-test-unbound' error.
-This affects the 'ert-select-tests' function and its callers.
-
-** Emoji
-
-+++
-*** Emacs now has several new methods for inserting Emoji.
-The Emoji commands are under the new 'C-x 8 e' prefix.
-
-+++
-*** New command 'emoji-insert' (bound to 'C-x 8 e e' and 'C-x 8 e i').
-This command guides you through various Emoji categories and
-combinations in a graphical menu system.
-
-+++
-*** New command 'emoji-search' (bound to 'C-x 8 e s').
-This command lets you search for Emoji based on names.
-
-+++
-*** New command 'emoji-list' (bound to 'C-x 8 e l').
-This command lists all Emoji (categorized by themes) in a special
-buffer and lets you choose one of them.
-
----
-*** New command 'emoji-recent' (bound to 'C-x 8 e r').
-This command lets you choose among the Emoji you have recently
-inserted.
-
-+++
-*** New command 'emoji-describe' (bound to 'C-x 8 e d').
-This command will tell you the name of the Emoji at point. (It also
-works for non-Emoji characters.)
-
----
-*** New commands 'emoji-zoom-increase' and 'emoji-zoom-decrease'.
-These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They
-can be used on any character, but are mainly useful for Emoji.
-
----
-*** New input method 'emoji'.
-This allows you to enter Emoji using short strings, eg ':face_palm:'
-or ':scream:'.
-
-** Help
-
----
-*** Variable values displayed by 'C-h v' in "*Help*" are now fontified.
-
-+++
-*** New user option 'help-clean-buttons'.
-If non-nil, link buttons in "*Help*" buffers will have any surrounding
-quotes removed.
-
----
-*** 'M-x apropos-variable' output now includes values of variables.
-
-+++
-*** New docstring syntax to indicate that symbols shouldn't be links.
-When displaying docstrings in "*Help*" buffers, strings that are
-"`like-this'" are made into links (if they point to a bound
-function/variable). This can lead to false positives when talking
-about values that are symbols that happen to have the same names as
-functions/variables. To inhibit this buttonification, use the new
-"\\+`like-this'" syntax.
-
-+++
-*** New user option 'help-window-keep-selected'.
-If non-nil, commands to show the info manual and the source will reuse
-the same window in which the "*Help*" buffer is shown.
-
----
-*** Commands like 'C-h f' have changed how they describe menu bindings.
-For instance, previously a command might be described as having the
-following bindings:
-
- It is bound to <open>, C-x C-f, <menu-bar> <file> <new-file>.
-
-This has been changed to:
-
- It is bound to <open> and C-x C-f.
- It can also be invoked from the menu: File → Visit New File...
-
-+++
-*** The 'C-h .' command now accepts a prefix argument.
-'C-u C-h .' would previously inhibit displaying a warning message if
-there's no local help at point. This has been changed to call
-'button-describe'/'widget-describe' and display button/widget help
-instead.
-
----
-*** New user option 'help-enable-variable-value-editing'.
-If enabled, 'e' on a value in "*Help*" will pop you to a new buffer
-where you can edit the value. This is not enabled by default, because
-it's easy to make an edit that yields an invalid result.
-
----
-*** 'C-h b' uses outlining by default.
-Set 'describe-bindings-outline' to nil to get back the old behavior.
-
----
-*** Jumping to function/variable source now saves mark before moving point.
-Jumping to source from a "*Help*" buffer moves point when the source
-buffer is already open. Now, the old point is pushed onto mark ring.
-
-+++
-*** New key bindings in "*Help*" buffers: 'n' and 'p'.
-These will take you (respectively) to the next and previous "page".
-
----
-*** 'describe-char' now also outputs the name of Emoji sequences.
-
-+++
-*** New key binding in "*Help*" buffer: 'I'.
-This will take you to the Emacs Lisp manual entry for the item
-displayed, if any.
-
----
-*** The 'C-h m' ('describe-mode') "*Help*" buffer has been reformatted.
-It now only includes local minor modes at the start, and the global
-minor modes are listed after the major mode.
-
-+++
-*** The user option 'help-window-select' now affects apropos commands.
-The apropos commands will now select the apropos window if
-'help-window-select' is non-nil.
-
----
-*** 'describe-keymap' now considers the symbol at point.
-If the symbol at point is a keymap, 'describe-keymap' suggests it as
-the default candidate.
-
----
-*** New command 'help-quick' displays an overview of common commands.
-The command pops up a buffer at the bottom of the screen with a few
-helpful commands for various tasks. You can toggle the display using
-'C-h C-q'.
-
-** Emacs now comes with Org v9.6.
-See the file ORG-NEWS for user-visible changes in Org.
-
-** Outline Mode
-
-+++
-*** Support for customizing the default visibility state of headings.
-Customize the user option 'outline-default-state' to define what
-headings will be visible initially, after Outline mode is turned on.
-When the value is a number, the user option 'outline-default-rules'
-determines the visibility of the subtree starting at the corresponding
-level. Values are provided to control showing a heading subtree
-depending on whether the heading matches a regexp, or on whether its
-subtree has long lines or is itself too long.
-
-** Outline Minor Mode
-
-+++
-*** New user option 'outline-minor-mode-use-buttons'.
-If non-nil, Outline Minor Mode will use buttons to hide/show outlines
-in addition to the ellipsis. The default is nil, but in 'help-mode'
-it has the value 'insert' that inserts the buttons directly into the
-buffer, and you can use 'RET' to cycle outline visibility. When
-the value is 'in-margins', Outline Minor Mode uses the window margins
-for buttons that hide/show outlines.
-
-** Windows
-
-+++
-*** New commands 'split-root-window-below' and 'split-root-window-right'.
-These commands split the root window in two, and are bound to 'C-x w 2'
-and 'C-x w 3', respectively. A number of other useful window-related
-commands are now available with key sequences that start with the
-'C-x w' prefix.
-
-+++
-*** New user option 'display-buffer-avoid-small-windows'.
-If non-nil, this should be a window height in lines, a number.
-Windows smaller than this will be avoided by 'display-buffer', if
-possible.
-
-+++
-*** New display action 'display-buffer-full-frame'.
-This action removes other windows from the frame when displaying a
-buffer on that frame.
-
-+++
-*** 'display-buffer' now can set up the body size of the chosen window.
-For example, a 'display-buffer-alist' entry of
-
- '(window-width . (body-columns . 40))'
-
-will make the body of the chosen window 40 columns wide. For the
-height use 'window-height' and 'body-lines', respectively.
-
----
-*** You can customize on which window 'scroll-other-window' operates.
-This is controlled by the new 'other-window-scroll-default' user option.
-
-** Frames
-
-+++
-*** Deleted frames can now be undeleted.
-The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when
-'undelete-frame-mode' is enabled. Without a prefix argument, undelete
-the most recently deleted frame. With a numerical prefix argument
-between 1 and 16, where 1 is the most recently deleted frame, undelete
-the corresponding deleted frame.
-
-** Tab Bars and Tab Lines
-
----
-*** New user option 'tab-bar-auto-width' to automatically determine tab width.
-This option is non-nil by default, which resizes tab-bar tabs so that
-their width is evenly distributed across the tab bar. A companion
-option 'tab-bar-auto-width-max' controls the maximum width of a tab
-before its name on display is truncated.
-
----
-*** 'C-x t RET' creates a new tab when the provided tab name doesn't exist.
-It prompts for the name of a tab and switches to it, creating a new
-tab if no tab exists by that name.
-
----
-*** New keymap 'tab-bar-history-mode-map'.
-By default, it contains 'C-c <left>' and 'C-c <right>' to browse
-the history of tab window configurations back and forward.
-
----
-** Better detection of text suspiciously reordered on display.
-The function 'bidi-find-overridden-directionality' has been extended
-to detect reordering effects produced by embeddings and isolates
-(started by directional formatting control characters such as RLO and
-LRI). The new command 'highlight-confusing-reorderings' finds and
-highlights segments of buffer text whose reordering for display is
-suspicious and could be malicious.
-
-** Emacs server and client changes
-
-+++
-*** New command-line option '-r'/'--reuse-frame' for emacsclient.
-With this command-line option, Emacs reuses an existing graphical client
-frame if one exists; otherwise it creates a new frame.
-
-+++
-*** New command-line option '-w N'/'--timeout=N' for emacsclient.
-With this command-line option, emacsclient will exit if Emacs does not
-respond within N seconds. The default is to wait forever.
-
-+++
-*** 'server-stop-automatically' can be used to automatically stop the server.
-The Emacs server will be automatically stopped when certain conditions
-are met. The conditions are given by the argument, which can be
-'empty', 'delete-frame' or 'kill-terminal'.
-
-** Rcirc
-
-+++
-*** New command 'rcirc-when'.
-
-+++
-*** New user option 'rcirc-cycle-completion-flag'.
-Rcirc will use the default 'completion-at-point' mechanism. The
-conventional IRC behavior of completing by cycling through the
-available options can be restored by enabling this option.
-
-+++
-*** New user option 'rcirc-bridge-bot-alist'.
-If you are in a channel where a bot is responsible for bridging
-between networks, you can use this variable to make these messages
-appear more native. For example you might set the option to:
-
- (setq rcirc-bridge-bot-alist '(("bridge" . "{\\(.+?\\)}[[:space:]]+")))
-
-for messages like
-
- 09:47 <bridge> {john} I am not on IRC
-
-to be reformatted into
-
- 09:47 <john> I am not on IRC
-
----
-*** New formatting commands.
-Most IRC clients (including rcirc) support basic formatting using
-control codes. Under the 'C-c C-f' prefix a few commands have been
-added to insert these automatically. For example, if a region is
-active and 'C-c C-f C-b' is invoked, markup is inserted for the region
-to be highlighted in bold.
-
-** Imenu
-
-+++
-*** 'imenu' is now bound to 'M-g i' globally.
-
----
-*** New function 'imenu-flush-cache'.
-Use it if you want Imenu to forget the buffer's index alist and
-recreate it anew next time 'imenu' is invoked.
-
----
-** Emacs is now capable of abandoning a window's redisplay that takes too long.
-This is controlled by the new variable 'max-redisplay-ticks'. If that
-variable is set to a non-zero value, display of a window will be
-aborted after that many low-level redisplay operations, thus
-preventing Emacs from becoming wedged when visiting files with very
-long lines. The default is zero, which disables the feature: Emacs
-will wait forever for redisplay to finish. (We believe you won't need
-this feature, given the ability to display buffers with very long
-lines.)
-
-* Editing Changes in Emacs 29.1
-
-+++
-** 'M-SPC' is now bound to 'cycle-spacing'.
-Formerly it invoked 'just-one-space'. The actions performed by
-'cycle-spacing' and their order can now be customized via the user
-option 'cycle-spacing-actions'.
-
----
-** 'zap-to-char' and 'zap-up-to-char' are case-sensitive for upper-case chars.
-These commands now behave as case-sensitive for interactive calls when
-they are invoked with an uppercase character, regardless of the value
-of 'case-fold-search'.
-
----
-** 'scroll-other-window' and 'scroll-other-window-down' now respect remapping.
-These commands (bound to 'C-M-v' and 'C-M-V') used to scroll the other
-windows without looking at customizations in that other window. These
-functions now check whether they have been rebound in the buffer shown
-in that other window, and then call the remapped function instead. In
-addition, these commands now also respect the
-'scroll-error-top-bottom' user option.
-
----
-** Indentation of 'cl-flet' and 'cl-labels' has changed.
-These forms now indent like this:
-
- (cl-flet ((bla (x)
- (* x x)))
- (bla 42))
-
-This change also affects 'cl-macrolet', 'cl-flet*' and
-'cl-symbol-macrolet'.
-
-+++
-** New user option 'translate-upper-case-key-bindings'.
-Set this option to nil to inhibit the default translation of upper
-case keys to their lower case variants.
-
-+++
-** New command 'ensure-empty-lines'.
-This command increases (or decreases) the number of empty lines before
-point.
-
----
-** Improved mouse behavior with auto-scrolling modes.
-When clicking inside the 'scroll-margin' or 'hscroll-margin' region,
-point is now moved only when releasing the mouse button. This no
-longer results in a bogus selection, unless the mouse has also been
-dragged.
-
-+++
-** 'kill-ring-max' now defaults to 120.
-
----
-** New user option 'yank-menu-max-items'.
-Customize this option to limit the number of entries in the menu
-"Edit->Paste from Kill Menu". The default is 60.
-
-+++
-** Performing a pinch gesture on a touchpad now increases the text scale.
-
-** show-paren-mode
-
-+++
-*** New user option 'show-paren-context-when-offscreen'.
-When non-nil, if the point is in a closing delimiter and the opening
-delimiter is offscreen, shows some context around the opening
-delimiter in the echo area. The default is nil.
-
-This option can also be set to the symbols 'overlay' or 'child-frame',
-in which case the context is shown in an overlay or child-frame at the
-top-left of the current window. The latter option requires a
-graphical frame. On non-graphical frames, the context is shown in the
-echo area.
-
-** Comint
-
-+++
-*** 'comint-term-environment' is now aware of connection-local variables.
-The user option 'comint-terminfo-terminal' and the variable
-'system-uses-terminfo' can now be set as connection-local variables to
-change the terminal used on a remote host.
-
----
-*** New user option 'comint-delete-old-input'.
-When nil, this prevents comint from deleting the current input when
-inserting previous input using '<mouse-2>'. The default is t, to
-preserve previous behavior.
-
----
-*** New minor mode 'comint-fontify-input-mode'.
-This minor mode is enabled by default in "*shell*" and "*ielm*"
-buffers. It fontifies input text according to 'shell-mode' or
-'emacs-lisp-mode' font-lock rules. Customize the user options
-'shell-fontify-input-enable' and 'ielm-fontify-input-enable' to nil if
-you don't want to enable input fontification by default.
-
-** Mwheel
-
----
-*** New user options for alternate wheel events.
-The options 'mouse-wheel-down-alternate-event',
-'mouse-wheel-up-alternate-event', 'mouse-wheel-left-alternate-event',
-and 'mouse-wheel-right-alternate-event' have been added to better
-support systems where two kinds of wheel events can be received.
-
-** Internationalization changes
-
----
-*** The <Delete> function key now allows deleting the entire composed sequence.
-For the details, see the item about the 'delete-forward-char' command
-above.
-
----
-*** New user option 'composition-break-at-point'.
-Setting it to a non-nil value temporarily disables automatic
-composition of character sequences at point, and thus makes it easier
-to edit such sequences by allowing point to "enter" the composed
-sequence.
-
----
-*** Support for many old scripts and writing systems.
-Emacs now supports, and has language-environments and input methods,
-for several dozens of old scripts that were used in the past for
-various languages. For each such script Emacs now has font-selection
-and character composition rules, a language environment, and an input
-method. The newly-added scripts and the corresponding language
-environments are:
-
- Tai Tham script and the Northern Thai language environment
-
- Brahmi script and language environment
-
- Kaithi script and language environment
-
- Tirhuta script and language environment
-
- Sharada script and language environment
-
- Siddham script and language environment
-
- Syloti Nagri script and language environment
-
- Modi script and language environment
-
- Baybayin script and Tagalog language environment
-
- Hanunoo script and language environment
-
- Buhid script and language environment
-
- Tagbanwa script and language environment
-
- Limbu script and language environment
-
- Balinese script and language environment
-
- Javanese script and language environment
-
- Sundanese script and language environment
-
- Batak script and language environment
-
- Rejang script and language environment
-
- Makasar script and language environment
-
- Lontara script and language environment
-
- Hanifi Rohingya script and language environment
-
- Grantha script and language environment
-
- Kharoshthi script and language environment
-
- Lepcha script and language environment
-
- Meetei Mayek script and language environment
-
- Adlam script and language environment
-
- Mende Kikakui script and language environment
-
- Wancho script and language environment
-
- Toto script and language environment
-
- Gothic script and language environment
-
- Coptic script and language environment
-
----
-*** The "Oriya" language environment was renamed to "Odia".
-This is to follow the change in the official name of the script. The
-'oriya' input method was also renamed to 'odia'. However, the old
-name of the language environment and the input method are still
-supported.
-
----
-*** New Greek translation of the Emacs tutorial.
-Type 'C-u C-h t' to select it in case your language setup does not do
-so automatically.
-
----
-*** New Ukrainian translation of the Emacs Tutorial.
-
----
-*** New default phonetic input method for the Tamil language environment.
-The default input method for the Tamil language environment is now
-"tamil-phonetic" which is a customizable phonetic input method. To
-change the input method's translation rules, customize the user option
-'tamil-translation-rules'.
-
----
-*** New tamil99 input method for the Tamil language.
-This supports the keyboard layout specifically designed for the Tamil
-language.
-
----
-*** New input method 'slovak-qwerty'.
-This is a variant of the 'slovak' input method, which corresponds to
-the QWERTY Slovak keyboards.
-
----
-*** New input method 'cyrillic-chuvash'.
-This input method is based on the russian-computer input method, and
-is intended for typing in the Chuvash language written in the Cyrillic
-script.
+** New function 'treesit-transpose-sexps'
+treesit.el now unconditionally sets 'transpose-sexps-function' for all
+Tree-sitter modes. This functionality utilizes the new
+'transpose-sexps-function'.
-* Changes in Specialized Modes and Packages in Emacs 29.1
-
-** Ecomplete
-
----
-*** New commands 'ecomplete-edit' and 'ecomplete-remove'.
-These allow you to (respectively) edit and bulk-remove entries from
-the ecomplete database.
-
----
-*** New user option 'ecomplete-auto-select'.
-If non-nil and there's only one matching option, auto-select that.
-
----
-*** New user option 'ecomplete-filter-regexp'.
-If non-nil, this user option describes what entries not to add to the
-database stored on disk.
-
-** Auth-Source
-
-+++
-*** New user option 'auth-source-pass-extra-query-keywords'.
-Whether to recognize additional keyword params, like ':max' and
-':require', as well as accept lists of query terms paired with
-applicable keywords. This disables most known behavioral quirks
-unique to auth-source-pass, such as wildcard subdomain matching.
-
-** Dired
-
-+++
-*** 'dired-guess-shell-command' moved from dired-x to dired.
-This means that 'dired-do-shell-command' will now provide smarter
-defaults without first having to require 'dired-x'. See the node
-"(emacs) Shell Command Guessing" in the Emacs manual for more details.
-
----
-*** 'dired-clean-up-buffers-too' moved from dired-x to dired.
-This means that Dired now offers to kill buffers visiting files and
-dirs when they are deleted in Dired. Before, you had to require
-'dired-x' to enable this behavior. To disable this behavior,
-customize the user option 'dired-clean-up-buffers-too' to nil. The
-related user option 'dired-clean-confirm-killing-deleted-buffers'
-(which see) has also been moved to 'dired'.
-
-+++
-*** 'dired-do-relsymlink' moved from dired-x to dired.
-The corresponding key 'Y' is now bound by default in Dired.
-
-+++
-*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
-The corresponding key '% Y' is now bound by default in Dired.
-
----
-*** 'M-G' is now bound to 'dired-goto-subdir'.
-Before, that binding was only available if the dired-x package was
-loaded.
-
-+++
-*** 'dired-info' and 'dired-man' moved from dired-x to dired.
-The 'dired-info' and 'dired-man' commands have been moved from the
-dired-x package to dired. They have also been renamed to
-'dired-do-info' and 'dired-do-man'; the old command names are obsolete
-aliases.
-
-The keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound
-in Dired mode by default. The user options 'dired-bind-man' and
-'dired-bind-info' no longer have any effect and are obsolete.
-
-To get the old behavior back and unbind these keys in Dired mode, add
-the following to your Init file:
-
- (with-eval-after-load 'dired
- (keymap-set dired-mode-map "N" nil)
- (keymap-set dired-mode-map "I" nil))
-
----
-*** New command 'dired-do-eww'.
-This command visits the file on the current line with EWW.
-
----
-*** New user option 'dired-omit-lines'.
-This is used by 'dired-omit-mode', and now allows you to hide based on
-other things than just the file names.
-
-+++
-*** New user option 'dired-mouse-drag-files'.
-If non-nil, dragging file names with the mouse in a Dired buffer will
-initiate a drag-and-drop session allowing them to be opened in other
-programs.
-
-+++
-*** New user option 'dired-free-space'.
-Dired will now, by default, include the free space in the first line
-instead of having it on a separate line. To get the previous behavior
-back, say:
-
- (setq dired-free-space 'separate)
-
----
-*** New user option 'dired-make-directory-clickable'.
-If non-nil (which is the default), hitting 'RET' or 'mouse-1' on
-the directory components at the directory displayed at the start of
-the buffer will take you to that directory.
-
----
-*** Search and replace in Dired/Wdired supports more regexps.
-For example, the regexp ".*" will match only characters that are part
-of the file name. Also "^.*$" can be used to match at the beginning
-of the file name and at the end of the file name. This is used only
-when searching on file names. In Wdired this can be used when the new
-user option 'wdired-search-replace-filenames' is non-nil (which is the
-default).
-
-** Elisp
-
----
-*** New command 'elisp-eval-region-or-buffer' (bound to 'C-c C-e').
-This command evals the forms in the active region or in the whole buffer.
-
----
-*** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'.
-These commands (bound to 'C-c C-f' and 'C-c C-b', respectively)
-byte-compile the visited file and the current buffer, respectively.
-
-** Games
-
----
-*** New user option 'tetris-allow-repetitions'.
-This controls how randomness is implemented (whether to use pure
-randomness as before, or to use a bag).
-
-** Battery
-
-+++
-*** New user option 'battery-update-functions'.
-This can be used to trigger actions based on the battery status.
-
-** Enriched Mode
-
-+++
-*** New command 'enriched-toggle-markup'.
-This allows you to see the markup in 'enriched-mode' buffers (e.g.,
-the "HELLO" file).
-
-** Shell Script Mode
-
----
-*** New user option 'sh-indent-statement-after-and'.
-This controls how statements like the following are indented:
-
- foo &&
- bar
-
-*** New Flymake backend using the ShellCheck program.
-It is enabled by default, but requires that the external "shellcheck"
-command is installed.
-
-** CC Mode
-
----
-*** C++ Mode now supports most of the new features in the C++20 Standard.
-
-** Cperl Mode
-
----
-*** New user option 'cperl-file-style'.
-This option determines the indentation style to be used. It can also
-be used as a file-local variable.
-
-** Gud
-
----
-*** 'gud-go' is now bound to 'C-c C-v'.
-If given a prefix, it will prompt for an argument to use for the
-run/continue command.
-
----
-*** 'perldb' now recognizes '-E'.
-As of Perl 5.10, 'perl -E 0' behaves like 'perl -e 0' but also activates
-all optional features of the Perl version in use. 'perldb' now uses
-this invocation as its default.
-
-** Customize
-
----
-*** New command 'custom-toggle-hide-all-widgets'.
-This is bound to 'H' and toggles whether to hide or show the widget
-contents.
-
-** Diff mode
-
----
-*** New user option 'diff-whitespace-style'.
-Sets the value of the buffer-local variable 'whitespace-style' in
-'diff-mode' buffers. By default, this variable is '(face trailing)',
-which preserves behavior of previous Emacs versions.
-
-+++
-*** New user option 'diff-add-log-use-relative-names'.
-If non-nil insert file names in ChangeLog skeletons relative to the
-VC root directory.
-
-** Ispell
-
----
-*** 'ispell-region' and 'ispell-buffer' now push the mark.
-These commands push onto the mark ring the location of the last
-misspelled word where corrections were offered, so that you can then
-skip back to that location with 'C-x C-x'.
-
-** Dabbrev
-
----
-*** New function 'dabbrev-capf' for use on 'completion-at-point-functions'.
-
-+++
-*** New user option 'dabbrev-ignored-buffer-modes'.
-Buffers with major modes in this list will be ignored. By default,
-this includes "binary" buffers like 'archive-mode' and 'image-mode'.
-
-** Package
-
-+++
-*** New command 'package-update'.
-This command allows you to upgrade packages without using 'M-x
-list-packages'.
-
-+++
-*** New command 'package-update-all'.
-This command allows updating all packages without any queries.
-
-+++
-*** New commands 'package-recompile' and 'package-recompile-all'.
-These commands can be useful if the ".elc" files are out of date
-(invalid byte code and macros).
-
-+++
-*** New DWIM action on 'x' in "*Packages*" buffer.
-If no packages are marked, 'x' will install the package under point if
-it isn't already, and remove it if it is installed.
-
-+++
-*** New command 'package-vc-install'.
-Packages can now be installed directly from source by cloning from
-their repository.
-
-+++
-*** New command 'package-vc-install-from-checkout'.
-An existing checkout can now be loaded via package.el, by creating a
-symbolic link from the usual package directory to the checkout.
-
-+++
-*** New command 'package-vc-checkout'.
-Used to fetch the source of a package by cloning a repository without
-activating the package.
-
-+++
-*** New command 'package-vc-prepare-patch'.
-This command allows you to send patches to package maintainers, for
-packages checked out using 'package-vc-install'.
-
-+++
-*** New command 'package-report-bug'.
-This command helps you compose an email for sending bug reports to
-package maintainers.
-
-+++
-*** New user option 'package-vc-selected-packages'.
-By customizing this user option you can specify specific packages to
-install.
-
-** Emacs Sessions (Desktop)
-
-+++
-*** New user option to load a locked desktop if locking Emacs is not running.
-The option 'desktop-load-locked-desktop' can now be set to the value
-'check-pid', which means to allow loading a locked ".emacs.desktop"
-file if the Emacs process which locked it is no longer running on the
-local machine. This allows avoiding questions about locked desktop
-files when the Emacs session which locked it crashes, or was otherwise
-interrupted and didn't exit gracefully. See the "(emacs) Saving
-Emacs Sessions" node in the Emacs manual for more details.
-
-** Miscellaneous
-
-+++
-*** New command 'scratch-buffer'.
-This command switches to the "*scratch*" buffer. If "*scratch*" doesn't
-exist, the command creates it first. You can use this command if you
-inadvertently delete the "*scratch*" buffer.
-
-** Debugging
-
----
-*** 'q' in a "*Backtrace*" buffer no longer clears the buffer.
-Instead it just buries the buffer and switches the mode from
-'debugger-mode' to 'backtrace-mode', since commands like 'e' are no
-longer available after exiting the recursive edit.
-
-+++
-*** New user option 'debug-allow-recursive-debug'.
-This user option controls whether the 'e' (in a "*Backtrace*"
-buffer or while edebugging) and 'C-x C-e' (while edebugging) commands
-lead to a (further) backtrace. By default, this variable is nil,
-which is a change in behavior from previous Emacs versions.
-
-+++
-*** 'e' in edebug can now take a prefix arg to pretty-print the results.
-When invoked with a prefix argument, as in 'C-u e', this command will
-pop up a new buffer and show the full pretty-printed value there.
-
-+++
-*** 'C-x C-e' now interprets a non-zero prefix arg to pretty-print the results.
-When invoked with a non-zero prefix argument, as in 'C-u C-x C-e',
-this command will pop up a new buffer and show the full pretty-printed
-value there.
-
-+++
-*** You can now generate a backtrace from Lisp errors in redisplay.
-To do this, set the new variable 'backtrace-on-redisplay-error' to a
-non-nil value. The backtrace will be written to a special buffer
-named "*Redisplay-trace*". This buffer will not be automatically
-displayed in a window.
-
-** Compile
-
-+++
-*** New user option 'compilation-hidden-output'.
-This can be used to make specific parts of compilation output
-invisible.
-
-+++
-*** The 'compilation-auto-jump-to-first-error' user option has been extended.
-It can now have the additional values 'if-location-known' (which will
-only jump if the location of the first error is known), and
-'first-known' (which will jump to the first known error location).
-
-+++
-*** New user option 'compilation-max-output-line-length'.
-Lines longer than the value of this variable will have their ends
-hidden, with a button to reveal the hidden text. This speeds up
-operations like grepping on files that have few newlines. The default
-value is 400; set to nil to disable hiding.
-
-** Flymake
-
-+++
-*** New user option 'flymake-mode-line-lighter'.
-
-+++
-** New minor mode 'word-wrap-whitespace-mode' for extending 'word-wrap'.
-This mode switches 'word-wrap' on, and breaks on all the whitespace
-characters instead of just 'SPC' and 'TAB'.
-
----
-** New mode, 'emacs-news-mode', for editing the NEWS file.
-This mode adds some highlighting, makes the 'M-q' command aware of the
-format of NEWS entries, and has special commands for doing maintenance
-of the Emacs NEWS files. In addition, this mode turns on
-'outline-minor-mode', and thus displays customizable icons (see
-'icon-preference') in the margins. To disable these icons, set
-'outline-minor-mode-use-buttons' to a nil value.
-
----
-** Kmacro
-Kmacros are now OClosures and have a new constructor 'kmacro' which
-uses the 'key-parse' syntax. It replaces the old 'kmacro-lambda-form'
-(which is now declared obsolete).
-
----
-** savehist.el can now truncate variables that are too long.
-An element of 'savehist-additional-variables' can now be of the form
-'(VARIABLE . MAX-ELTS)', which means to truncate the VARIABLE's value to
-at most MAX-ELTS elements (if the value is a list) before saving the
-value.
-
-** Minibuffer and Completions
-
-+++
-*** New commands for navigating completions from the minibuffer.
-When the minibuffer is the current buffer, typing 'M-<up>' or
-'M-<down>' selects a previous/next completion candidate from the
-"*Completions*" buffer and inserts it to the minibuffer.
-When the user option 'minibuffer-completion-auto-choose' is nil,
-'M-<up>' and 'M-<down>' do the same, but without inserting
-a completion candidate to the minibuffer, then 'M-RET' can be used
-to choose the currently active candidate from the "*Completions*"
-buffer and exit the minibuffer. With a prefix argument, 'C-u M-RET'
-inserts the currently active candidate to the minibuffer, but doesn't
-exit the minibuffer. These keys are also available for in-buffer
-completion, but they don't insert candidates automatically, you need
-to type 'M-RET' to insert the selected candidate to the buffer.
-
-+++
-*** Choosing a completion with a prefix argument doesn't exit the minibuffer.
-This means that typing 'C-u RET' on a completion candidate in the
-"*Completions*" buffer inserts the completion into the minibuffer,
-but doesn't exit the minibuffer.
-
-+++
-*** The "*Completions*" buffer can now be automatically selected.
-To enable this behavior, customize the user option
-'completion-auto-select' to t, then pressing 'TAB' will switch to the
-"*Completions*" buffer when it pops up that buffer. If the value is
-'second-tab', then the first 'TAB' will display "*Completions*", and
-the second one will switch to the "*Completions*" buffer.
-
----
-*** New user option 'completion-auto-wrap'.
-When non-nil, the commands 'next-completion' and 'previous-completion'
-automatically wrap around on reaching the beginning or the end of
-the "*Completions*" buffer.
-
-+++
-*** New values for the 'completion-auto-help' user option.
-There are two new values to control the way the "*Completions*" buffer
-behaves after pressing a 'TAB' if completion is not unique. The value
-'always' updates or shows the "*Completions*" buffer after any attempt
-to complete. The value 'visual' is like 'always', but only updates
-the completions if they are already visible. The default value t
-always hides the completion buffer after some completion is made.
-
----
-*** New commands to complete the minibuffer history.
-'minibuffer-complete-history' ('C-x <up>') is like 'minibuffer-complete'
-but completes on the history items instead of the default completion
-table. 'minibuffer-complete-defaults' ('C-x <down>') completes
-on the list of default items.
-
-+++
-*** User option 'minibuffer-eldef-shorten-default' is now obsolete.
-Customize the user option 'minibuffer-default-prompt-format' instead.
-
-+++
-*** New user option 'completions-sort'.
-This option controls the sorting of the completion candidates in
-the "*Completions*" buffer. Available styles are no sorting,
-alphabetical (the default), or a custom sort function.
-
-+++
-*** New user option 'completions-max-height'.
-This option limits the height of the "*Completions*" buffer.
-
-+++
-*** New user option 'completions-header-format'.
-This is a string to control the header line to show in the
-"*Completions*" buffer before the list of completions.
-If it contains "%s", that is replaced with the number of completions.
-If nil, the header line is not shown.
-
-+++
-*** New user option 'completions-highlight-face'.
-When this user option names a face, the current
-candidate in the "*Completions*" buffer is highlighted with that face.
-The nil value disables this highlighting. The default is to highlight
-using the 'completions-highlight' face.
-
-+++
-*** You can now define abbrevs for the minibuffer modes.
-'minibuffer-mode-abbrev-table' and
-'minibuffer-inactive-mode-abbrev-table' are now defined.
-
-** Isearch and Replace
-
-+++
-*** Changes in how Isearch responds to 'mouse-yank-at-point'.
-If a user does 'C-s' and then uses '<mouse-2>' ('mouse-yank-primary')
-outside the echo area, Emacs will, by default, end the Isearch and
-yank the text at mouse cursor. But if 'mouse-yank-at-point' is
-non-nil, the text will now be added to the Isearch instead.
-
-+++
-*** Changes for values 'no' and 'no-ding' of 'isearch-wrap-pause'.
-Now with these values the search will wrap around not only on repeating
-with 'C-s C-s', but also after typing a character.
-
-+++
-*** New user option 'char-fold-override'.
-Non-nil means that the default definitions of equivalent characters
-are overridden.
-
-*** New command 'describe-char-fold-equivalences'.
-It displays character equivalences used by 'char-fold-to-regexp'.
-
-+++
-*** New command 'isearch-emoji-by-name'.
-It is bound to 'C-x 8 e RET' during an incremental search. The
-command accepts the Unicode name of an Emoji (for example, "smiling
-face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
-completion, and adds the Emoji into the search string.
-
-** Glyphless characters
-
-+++
-*** New minor mode 'glyphless-display-mode'.
-This allows an easy way to toggle seeing all glyphless characters in
-the current buffer.
-
----
-*** The extra slot of 'glyphless-char-display' can now have cons values.
-The extra slot of the 'glyphless-char-display' char-table can now have
-values that are cons cells, specifying separate values for text-mode
-and GUI terminals.
-
-+++
-*** "Replacement character" feature for undisplayable characters on TTYs.
-The 'acronym' method of displaying glyphless characters on text-mode
-frames treats single-character acronyms specially: they are displayed
-without the surrounding [..] "box", thus in effect treating such
-"acronyms" as replacement characters.
-
-** Registers
-
-+++
-*** Buffer names can now be stored in registers.
-For instance, to enable jumping to the "*Messages*" buffer with
-'C-x r j m':
-
- (set-register ?m '(buffer . "*Messages*"))
-
-** Pixel-fill
-
-+++
-*** This is a new package that deals with filling variable-pitch text.
-
-+++
-*** New function 'pixel-fill-region'.
-This fills the region to be no wider than a specified pixel width.
-
-** Info
-
-+++
-*** 'M-x info-apropos' now takes a prefix argument to search for regexps.
-
+* Changes in Specialized Modes and Packages in Emacs 30.1
---
-*** New command 'Info-goto-node-web' and key binding 'G'.
-This will take you to the gnu.org web server's version of the current
-info node. This command only works for the Emacs and Emacs Lisp manuals.
+** Variable order and truncation can now be configured in gdb-many-window mode.
+The new variable 'gdb-locals-table-row-config' allows users to
+configure the order and max length of various properties in the local
+variables buffer when using 'gdb-many-windows'.
-** Shortdoc
+By default, this variable is set to write the properties in the order:
+name, type and value, where the name and type are truncated to 20
+characters, and the value is truncated according to the value of
+'gdb-locals-value-limit'.
----
-*** New command 'shortdoc-copy-function-as-kill' bound to 'w'.
-It copies the name of the function near point into the kill ring.
+If you want to get back the old behavior, set
+'gdb-locals-table-row-config' to the value
----
-*** 'N' and 'P' are now bound to 'shortdoc-{next,previous}-section'.
-This is in addition to the old keybindings 'C-c C-n' and 'C-c C-p'.
+ ((type . 0)(name . 0)(value . ,gdb-locals-value-limit)).
** VC
---
-*** New command 'vc-pull-and-push'.
-This commands first does a "pull" command, and if that is successful,
-does a "push" command afterwards.
-
-+++
-*** 'C-x v b' prefix key is used now for branch commands.
-'vc-print-branch-log' is bound to 'C-x v b l', and new commands are
-'vc-create-branch' ('C-x v b c') and 'vc-switch-branch' ('C-x v b s').
-The VC Directory buffer now uses the prefix 'b' for these branch-related
-commands.
-
-+++
-*** New command '%' ('vc-dir-mark-by-regexp').
-This command marks files based on a regexp. If given a prefix
-argument, unmark instead.
-
-+++
-*** New command 'C-x v !' ('vc-edit-next-command').
-This prefix command requests editing of the next VC shell command
-before execution. For example, in a Git repository, you can produce a
-log of more than one branch by typing 'C-x v ! C-x v b l' and then
-appending additional branch names to the 'git log' command.
-
----
-*** 'C-x v v' in a diffs buffer allows to commit only some of the changes.
-This command is intended to allow you to commit only some of the
-changes you have in your working tree. Begin by creating a buffer
-with the changes against the last commit, e.g. with 'C-x v D'
-('vc-root-diff'). Then edit the diffs to remove the hunks you don't
-want to commit. Finally, type 'C-x v v' in that diff buffer to commit
-only part of your changes, those whose hunks were left in the buffer.
-
----
-*** 'C-x v v' on an unregistered file will now use the most specific backend.
-Previously, if you had an SVN-covered "~/" directory, and a Git-covered
-directory in "~/foo/bar", using 'C-x v v' on a new, unregistered file
-"~/foo/bar/zot" would register it in the SVN repository in "~/" instead of
-in the Git repository in "~/foo/bar". This makes this command
-consistent with 'vc-responsible-backend'.
-
----
-*** Log Edit now fontifies long Git commit summary lines.
-Writing shorter summary lines avoids truncation in contexts in which
-Git commands display summary lines. See the two new user options
-'vc-git-log-edit-summary-target-len' and 'vc-git-log-edit-summary-max-len'.
-
----
-*** New 'log-edit-headers-separator' face.
-It is used to style the line that separates the 'log-edit' headers
-from the 'log-edit' summary.
-
----
-*** The function 'vc-read-revision' accepts a new MULTIPLE argument.
-If non-nil, multiple revisions can be queried. This is done using
-'completing-read-multiple'.
-
----
-*** New function 'vc-read-multiple-revisions'.
-This function invokes 'vc-read-revision' with a non-nil value for
-MULTIPLE.
-
-+++
-*** New command 'vc-prepare-patch'.
-Patches for any version control system can be prepared using VC. The
-command will query what commits to send and will compose messages for
-your mail user agent. The behavior of 'vc-prepare-patch' can be
-modified by the user options 'vc-prepare-patches-separately' and
-'vc-default-patch-addressee'.
-
-** Message
-
----
-*** New user option 'mml-attach-file-at-the-end'.
-If non-nil, 'C-c C-a' will put attached files at the end of the message.
-
----
-*** Message Mode now supports image yanking.
-
-+++
-*** New user option 'message-server-alist'.
-This controls automatic insertion of the "X-Message-SMTP-Method"
-header before sending a message.
-
-** HTML Mode
-
----
-*** HTML Mode now supports "text/html" and "image/*" yanking.
-
-** Texinfo Mode
-
----
-*** 'texinfo-mode' now has a specialized 'narrow-to-defun' definition.
-It narrows to the current node.
-
-** EUDC
-
-+++
-*** Deprecations planned for next release.
-After Emacs 29.1, some aspects of EUDC will be deprecated. The goal
-of these deprecations is to simplify EUDC server configuration by
-making 'eudc-server-hotlist' the only place to add servers. There
-will not be a need to set the server using the 'eudc-set-server'
-command. Instead, the 'eudc-server-hotlist' user option should be
-customized to have an entry for the server. The plan is to obsolete
-the 'eudc-hotlist' package since Customize is sufficient for changing
-'eudc-server-hotlist'. How the 'eudc-server' user option works in this
-context is to-be-determined; it can't be removed, because that would
-break compatibility, but it may become synchronized with
-'eudc-server-hotlist' so that 'eudc-server' is always equal to '(car
-eudc-server-hotlist)'. The first entry in 'eudc-server-hotlist' is the
-first server tried by 'eudc-expand-try-all'. The hotlist
-simplification will allow 'eudc-query-form' to show a drop down of
-possible servers, instead of requiring a call to 'eudc-set-server'
-like it does in this release. The default value of
-'eudc-ignore-options-file' will be changed from nil to t.
-
-+++
-*** New user option 'eudc-ignore-options-file' that defaults to nil.
-The 'eudc-ignore-options-file' user option can be configured to ignore
-the 'eudc-options-file' (typically "~/.emacs.d/eudc-options"). Most
-users should configure this to t and put EUDC configuration in the
-main Emacs initialization file ("~/.emacs" or "~/.emacs.d/init.el").
-
-+++
-*** 'eudc-expansion-overwrites-query' to 'eudc-expansion-save-query-as-kill'.
-'eudc-expansion-overwrites-query' is renamed to
-'eudc-expansion-save-query-as-kill' to reflect the actual behavior of
-the user option.
-
-+++
-*** New command 'eudc-expand-try-all'.
-This command can be used in place of 'eudc-expand-inline'. It takes a
-prefix argument that causes 'eudc-expand-try-all' to return matches
-from all servers instead of just the matches from the first server to
-return any. This is useful for example, if one wants to search LDAP
-for a name that happens to match a contact in one's BBDB.
-
-+++
-*** New behavior and default for user option 'eudc-inline-expansion-format'.
-EUDC inline expansion result formatting defaulted to
-
- '("%s %s <%s>" firstname name email)
-
-Since email address specifications need to comply with RFC 5322 in
-order to be useful in messages, there was a risk to produce syntax
-which was standard with RFC 822, but is marked as obsolete syntax by
-its successor RFC 5322. Also, the first and last name part was never
-enclosed in double quotes, potentially producing invalid address
-specifications, which may be rejected by a receiving MTA. Thus, this
-variable can now additionally be set to nil (the new default), or a
-function. In both cases, the formatted result will be in compliance
-with RFC 5322. When set to nil, a default format very similar to the
-old default will be produced. When set to a function, that function
-is called, and the returned values are used to populate the phrase and
-comment parts (see RFC 5322 for definitions). In both cases, the
-phrase part will be automatically quoted if necessary.
-
-+++
-*** New function 'eudc-capf-complete' with 'message-mode' integration.
-EUDC can now contribute email addresses to 'completion-at-point' by
-adding the new function 'eudc-capf-complete' to
-'completion-at-point-functions' in 'message-mode'.
-
-+++
-*** Additional attributes of query and results in eudcb-macos-contacts.el.
-The EUDC back-end for the macOS Contacts app now provides a wider set
-of attributes to use for queries, and delivers more attributes in
-query results.
-
-+++
-*** New back-end for ecomplete.
-A new back-end for ecomplete allows information from that database to
-be queried by EUDC, too. The attributes present in the EUDC query are
-used to select the entry type in the ecomplete database.
-
-+++
-*** New back-end for mailabbrev.
-A new back-end for mailabbrev allows information from that database to
-be queried by EUDC, too. The attributes 'email', 'name', and 'firstname'
-are supported only.
-
-** EWW/SHR
-
-+++
-*** New user option to automatically rename EWW buffers.
-The 'eww-auto-rename-buffer' user option can be configured to rename
-rendered web pages by using their title, URL, or a user-defined
-function which returns a string. For the first two cases, the length
-of the resulting name is controlled by 'eww-buffer-name-length'. By
-default, no automatic renaming is performed.
-
-+++
-*** New user option 'shr-allowed-images'.
-This complements 'shr-blocked-images', but allows specifying just the
-allowed images.
-
-+++
-*** New user option 'shr-use-xwidgets-for-media'.
-If non-nil (and Emacs has been built with support for xwidgets),
-display <video> elements with an xwidget. Note that this is
-experimental; it is known to crash Emacs on some systems, and just
-doesn't work on other systems. Also see etc/PROBLEMS.
-
-+++
-*** New user option 'eww-url-transformers'.
-These are used to alter an URL before using it. By default it removes
-the common "utm_" trackers from URLs.
-
-** Find-Dired
-
----
-*** New command 'find-dired-with-command'.
-This enables users to run 'find-dired' with an arbitrary command,
-enabling running commands previously unsupported and also enabling new
-commands to be built on top.
-
-** Gnus
-
-+++
-*** Tool bar changes in Gnus/Message.
-There were previously two styles of tool bars available in Gnus and
-Message, referred to as 'gnus-summary-tool-bar-retro',
-'gnus-group-tool-bar-retro' and 'message-tool-bar-retro', and
-'gnus-summary-tool-bar-gnome', 'gnus-group-tool-bar-gnome' and
-'message-tool-bar-gnome'. The "retro" tool bars have been removed (as
-well as the icons used), and the "Gnome" tool bars are now the only
-pre-defined toolbars.
-
----
-*** 'gnus-summary-up-thread' and 'gnus-summary-down-thread' bindings removed.
-The 'gnus-summary-down-thread' binding to "M-C-d" was shadowed by
-'gnus-summary-read-document', and these commands are also available on
-"T-u" and "T-d" respectively.
-
----
-*** Gnus now uses a variable-pitch font in the headers by default.
-To get the monospace font back, you can put something like the
-following in your ".gnus" file:
-
- (set-face-attribute 'gnus-header nil :inherit 'unspecified)
-
----
-*** The default value of 'gnus-treat-fold-headers' is now 'head'.
-
----
-*** New face 'gnus-header'.
-All other 'gnus-header-*' faces inherit from this face now.
-
-+++
-*** New user option 'gnus-treat-emojize-symbols'.
-If non-nil, symbols that have an Emoji representation will be
-displayed as emojis. The default is nil.
-
-+++
-*** New command 'gnus-article-emojize-symbols'.
-This is bound to 'W D e' and will display symbols that have Emoji
-representation as Emoji.
-
-+++
-*** New mu backend for gnus-search.
-Configuration is very similar to the notmuch and namazu backends. It
-supports the unified search syntax.
-
----
-*** 'gnus-html-image-cache-ttl' is now a seconds count.
-Formerly it was a pair of numbers '(A B)' that represented 65536*A + B,
-to cater to older Emacs implementations that lacked bignums.
-The older form still works but is undocumented.
-
-** Rmail
-
----
-*** Rmail partial summaries can now be applied one on top of the other.
-You can now narrow the set of messages selected by Rmail summary's
-criteria (recipients, topic, senders, etc.) by making a summary of the
-already summarized messages. For example, invoking
-'rmail-summary-by-senders', followed by 'rmail-summary-by-topic' will
-produce a summary where both the senders and the topic are according
-to your selection. The new user option
-'rmail-summary-progressively-narrow' controls whether the stacking of
-the filters is in effect; customize it to a non-nil value to enable
-this feature.
-
----
-*** New Rmail summary: by thread.
-The new command 'rmail-summary-by-thread' produces a summary of
-messages that belong to a single thread of discussion.
-
-** EIEIO
-
-+++
-*** 'slot-value' can now be used to access slots of 'cl-defstruct' objects.
-
-** Align
-
----
-*** Alignment in 'text-mode' has changed.
-Previously, 'M-x align' didn't do anything, and you had to say 'C-u
-M-x align' for it to work. This has now been changed. The default
-regexp for 'C-u M-x align-regexp' has also been changed to be easier
-for inexperienced users to use.
-
-** Help
-
----
-*** New mode, 'emacs-news-view-mode', for viewing the NEWS file.
-This mode is used by the 'C-h N' command, and adds buttons to manual
-entries and symbol references.
-
----
-*** New user option 'help-link-key-to-documentation'.
-When this option is non-nil (which is the default), key bindings
-displayed in the "*Help*" buffer will be linked to the documentation
-for the command they are bound to. This does not affect listings of
-key bindings and functions (such as 'C-h b').
+*** New user option 'vc-git-shortlog-switches'.
+This is a string or a list of strings that specifies the Git log
+switches for shortlogs, such as the one produced by 'C-x v L'.
+'vc-git-log-switches' is no longer used for shortlogs.
-** Info-look
+** bs
---
-*** info-look specs can now be expanded at run time instead of a load time.
-The new ':doc-spec-function' element can be used to compute the
-':doc-spec' element when the user asks for info on that particular
-mode (instead of at load time).
-
-** Ansi-color
-
----
-*** Support for ANSI 256-color and 24-bit colors.
-256-color and 24-bit color codes are now handled by ANSI color
-filters and displayed with the specified color.
-
-** Term-mode
-
----
-*** New user option 'term-bind-function-keys'.
-If non-nil, 'term-mode' will pass the function keys on to the
-underlying shell instead of using the normal Emacs bindings.
-
----
-*** Support for ANSI 256-color and 24-bit colors, italic and other fonts.
-'term-mode' can now display 256-color and 24-bit color codes. It can
-also handle ANSI codes for faint, italic and blinking text, displaying
-it with new 'term-{faint,italic,slow-blink,fast-blink}' faces.
-
-** Project
-
-+++
-*** 'project-find-file' and 'project-or-external-find-file' can include all.
-The commands 'project-find-file' and 'project-or-external-find-file'
-now accept a prefix argument, which is interpreted to mean "include
-all files".
-
-+++
-*** New command 'project-list-buffers' bound to 'C-x p C-b'.
-This command displays a list of buffers from the current project.
-
-+++
-*** 'project-kill-buffers' can display the list of buffers to kill.
-Customize the user option 'project-kill-buffers-display-buffer-list'
-to enable the display of the buffer list.
-
-*** New user option 'project-vc-extra-root-markers'.
-Use it to add detection of nested projects (inside a VCS repository),
-or projects outside of VCS repositories.
-
-As a consequence, the 'VC project backend' is formally renamed to
-'VC-aware project backend'.
-
-+++
-*** New user option 'project-vc-include-untracked'.
-If non-nil, files untracked by a VCS are considered to be part of
-the project by a VC project based on that VCS.
-
-** Xref
-
-+++
-*** New command 'xref-go-forward'.
-It is bound to 'C-M-,' and jumps to the location where 'xref-go-back'
-('M-,', also known as 'xref-pop-marker-stack') was invoked previously.
-
-+++
-*** 'xref-query-replace-in-results' prompting change.
-This command no longer prompts for FROM when called without prefix
-argument. This makes the most common case faster: replacing entire
-matches.
-
-+++
-*** New command 'xref-find-references-and-replace' to rename one identifier.
-
----
-*** New variable 'xref-current-item' (renamed from a private version).
-
----
-*** New function 'xref-show-xrefs'.
-
-** File notifications
-
-+++
-*** The new command 'file-notify-rm-all-watches' removes all file notifications.
-
-** Sql
-
----
-*** Sql now supports sending of passwords in-process.
-To improve security, if an sql product has ':password-in-comint' set
-to t, a password supplied via the minibuffer will be sent in-process,
-as opposed to via the command-line.
-
-** Image Mode
-
-+++
-*** New command 'image-transform-fit-to-window'.
-This command fits the image to the current window by scaling down or
-up as necessary. Unlike 'image-transform-fit-both', this does not
-only scale the image down, but up as well. It is bound to 's w' in
-Image Mode by default.
-
----
-*** New command 'image-mode-wallpaper-set'.
-This command sets the desktop background to the current image. It is
-bound to 'W' by default.
-
-+++
-*** 'image-transform-fit-to-{height,width}' are now obsolete.
-Use the new command 'image-transform-fit-to-window' instead.
-The keybinding for 'image-transform-fit-to-width' is now 's i'.
-
----
-*** User option 'image-auto-resize' can now be set to 'fit-window'.
-This works like 'image-transform-fit-to-window'.
-
----
-*** New user option 'image-auto-resize-max-scale-percent'.
-The new 'fit-window' option will never scale an image more than this
-much (in percent). It is nil by default, which means no limit.
-
----
-*** New user option 'image-text-based-formats'.
-This controls whether or not to show a message when opening certain
-image formats saying how to edit it as text. The default is to show
-this message for SVG and XPM.
-
-+++
-*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'.
-These commands horizontally and vertically flip the image under point,
-and are bound to 'i h' and 'i v', respectively.
-
-+++
-*** New command 'image-transform-set-percent'.
-It allows setting the image size to a percentage of its original size,
-and is bound to 's p' in Image mode.
-
-+++
-*** 'image-transform-original' renamed to 'image-transform-reset-to-original'.
-The old name was confusing, and is now an obsolete function alias.
-
-+++
-*** 'image-transform-reset' renamed to 'image-transform-reset-to-initial'.
-The old name was confusing, and is now an obsolete function alias.
-
-** Images
-
-+++
-*** Users can now add special image conversion functions.
-This is done via 'image-converter-add-handler'.
-
-** Image-Dired
-
-+++
-*** 'image-dired-image-mode' is now based on 'image-mode'.
-This avoids converting images in the background, and makes Image-Dired
-noticeably faster. New keybindings from 'image-mode' are now
-available in the "*image-dired-display-image*" buffer; press '?' or
-'h' in that buffer to see the full list.
-
----
-*** Navigation and marking commands now work in image display buffer.
-The following new bindings have been added:
-- 'n', 'SPC' => 'image-dired-display-next'
-- 'p', 'DEL' => 'image-dired-display-previous'
-- 'm' => 'image-dired-mark-thumb-original-file'
-- 'd' => 'image-dired-flag-thumb-original-file'
-- 'u' => 'image-dired-unmark-thumb-original-file'
-
----
-*** New command 'image-dired-unmark-all-marks'.
-It removes all marks from all files in the thumbnail and the
-associated Dired buffer, and is bound to 'U' in the thumbnail and
-display buffer.
-
----
-*** New command 'image-dired-do-flagged-delete'.
-It deletes all flagged files, and is bound to 'x' in the thumbnail
-buffer. It replaces the command 'image-dired-delete-marked', which is
-now an obsolete alias.
-
----
-*** New command 'image-dired-copy-filename-as-kill'.
-It copies the name of the marked or current image to the kill ring,
-and is bound to 'w' in the thumbnail buffer.
-
----
-*** New command 'image-dired-wallpaper-set'.
-This command sets the desktop background to the image at point in the
-thumbnail buffer. It is bound to 'W' by default.
-
----
-*** 'image-dired-slideshow-start' is now bound to 'S'.
-It is bound in both the thumbnail and display buffer, and no longer
-prompts for a timeout; use a numerical prefix (e.g. 'C-u 8 S') to set
-the timeout.
-
----
-*** New user option 'image-dired-marking-shows-next'.
-If this option is non-nil (the default), marking, unmarking or
-flagging an image in either the thumbnail or display buffer shows the
-next image.
-
----
-*** New face 'image-dired-thumb-flagged'.
-If 'image-dired-thumb-mark' is non-nil (the default), this face is
-used for images that are flagged for deletion in the Dired buffer
-associated with Image-Dired.
-
----
-*** Image information is now shown in the header line of the thumbnail buffer.
-This replaces the message that most navigation commands in the
-thumbnail buffer used to show at the bottom of the screen.
-
----
-*** New specifiers for 'image-dired-display-properties-format'.
-This is used to format the new header line. The new specifiers are:
-"%d" for the name of the directory that the file is in, "%n" for
-file's number in the thumbnail buffer, and "%s" for the file size.
-
-The default format has been updated to use this. If you prefer the
-old format, add this to your Init file:
-
- (setopt image-dired-display-properties-format "%b: %f (%t): %c")
-
----
-*** New faces for the header line of the thumbnail buffer.
-These faces correspond to different parts of the header line, as
-specified in 'image-dired-display-properties-format':
-- 'image-dired-thumb-header-directory-name'
-- 'image-dired-thumb-header-file-name'
-- 'image-dired-thumb-header-file-size'
-- 'image-dired-thumb-header-image-count'
-
----
-*** PDF support.
-Image-Dired now displays thumbnails for PDF files. Type 'RET' on a
-PDF file in the thumbnail buffer to visit the corresponding PDF.
-
----
-*** Support GraphicsMagick command line tools.
-Support for the GraphicsMagick command line tool ("gm") has been
-added, and is used when it is available instead of ImageMagick.
-
----
-*** Support Thumbnail Managing Standard v0.9.0 (Dec 2020).
-This standard allows sharing generated thumbnails across different
-programs. Version 0.9.0 adds two larger thumbnail sizes: 512x512 and
-1024x1024 pixels. See the user option 'image-dired-thumbnail-storage'
-to use it; it is not enabled by default.
-
----
-*** Reduce dependency on external "exiftool" command.
-The 'image-dired-copy-with-exif-file-name' no longer requires an
-external "exiftool" command to be available. The user options
-'image-dired-cmd-read-exif-data-program' and
-'image-dired-cmd-read-exif-data-options' are now obsolete.
-
----
-*** Support for bookmark.el.
-The command 'bookmark-set' (bound to 'C-x r m') is now supported in
-the thumbnail view, and will create a bookmark that opens the current
-directory in Image-Dired.
-
----
-*** The 'image-dired-slideshow-start' command no longer prompts.
-It no longer inconveniently prompts for a number of images and a
-delay: it runs indefinitely, but stops automatically on any command.
-You can set the delay with a prefix argument, or a negative prefix
-argument to prompt for a delay. Customize the user option
-'image-dired-slideshow-delay' to change the default from 5 seconds.
-
-+++
-*** 'image-dired-show-all-from-dir-max-files' increased to 1000.
-This user option controls asking for confirmation when starting
-Image-Dired in a directory with many files. Since Image-Dired creates
-thumbnails in the background in recent versions, this is not as
-important as it used to be. You can now also customize this option to
-nil to disable this confirmation completely.
-
----
-*** 'image-dired-thumb-size' increased to 128.
-
-+++
-*** 'image-dired-db-file' renamed to 'image-dired-tags-db-file'.
-
----
-*** 'image-dired-display-image-mode' renamed to 'image-dired-image-mode'.
-The corresponding keymap is now named 'image-dired-image-mode-map'.
-
-+++
-*** Some commands have been renamed to be shorter.
-- 'image-dired-display-thumbnail-original-image' has been renamed to
- 'image-dired-display-this'.
-- 'image-dired-display-next-thumbnail-original' has been renamed to
- 'image-dired-display-next'.
-- 'image-dired-display-previous-thumbnail-original' has been renamed
- to 'image-dired-display-previous'.
-The old names are now obsolete aliases.
-
----
-*** 'image-dired-thumb-{height,width}' are now obsolete.
-Customize 'image-dired-thumb-size' instead, which will set both the
-height and width.
-
----
-*** HTML image gallery generation is now obsolete.
-The 'image-dired-gallery-generate' command and these user options are
-now obsolete: 'image-dired-gallery-thumb-image-root-url',
-'image-dired-gallery-hidden-tags', 'image-dired-gallery-dir',
-'image-dired-gallery-image-root-url'.
-
----
-*** 'image-dired-rotate-thumbnail-{left,right}' are now obsolete.
-Instead, use commands 'image-dired-refresh-thumb' to generate a new
-thumbnail, or 'image-rotate' to rotate the thumbnail without updating
-the thumbnail file.
-
-+++
-*** Some commands and user options are now obsolete.
-Since 'image-dired-display-image-mode' is now based on 'image-mode',
-some commands and user options are no longer needed and are now obsolete:
-'image-dired-cmd-create-temp-image-options',
-'image-dired-cmd-create-temp-image-program',
-'image-dired-display-current-image-full',
-'image-dired-display-current-image-sized',
-'image-dired-display-window-height-correction',
-'image-dired-display-window-width-correction',
-'image-dired-temp-image-file'.
-
-** Bookmarks
-
----
-*** 'list-bookmarks' now includes a type column.
-Types are registered via a 'bookmark-handler-type' symbol property on
-the jumping function.
-
-+++
-*** 'bookmark-sort-flag' can now be set to 'last-modified'.
-This will display bookmark list from most recently set to least
-recently set.
-
----
-*** When editing a bookmark annotation, 'C-c C-k' will now cancel.
-It is bound to the new command 'bookmark-edit-annotation-cancel'.
-
----
-*** New user option 'bookmark-fringe-mark'.
-This option controls the bitmap used to indicate bookmarks in the
-fringe (or nil to disable showing this marker).
-
-** Exif
-
----
-*** New function 'exif-field'.
-This is a convenience function to extract the field data from
-'exif-parse-file' and 'exif-parse-buffer'.
-
-** Xwidgets
-
----
-*** New user option 'xwidget-webkit-buffer-name-format'.
-This option controls how xwidget-webkit buffers are named.
-
----
-*** New user option 'xwidget-webkit-cookie-file'.
-This option controls whether the xwidget-webkit buffers save cookies
-set by web pages, and if so, in which file to save them.
-
-+++
-*** New minor mode 'xwidget-webkit-edit-mode'.
-When this mode is enabled, self-inserting characters and other common
-web browser shortcut keys are redefined to send themselves to the
-WebKit widget.
-
-+++
-*** New minor mode 'xwidget-webkit-isearch-mode'.
-This mode acts similarly to incremental search, and allows searching
-the contents of a WebKit widget. In xwidget-webkit mode, it is bound
-to 'C-s' and 'C-r'.
-
-+++
-*** New command 'xwidget-webkit-browse-history'.
-This command displays a buffer containing the page load history of
-the current WebKit widget, and allows you to navigate it.
-
----
-*** On X, the WebKit inspector is now available inside xwidgets.
-To access the inspector, right click on the widget and select "Inspect
-Element".
-
----
-*** "Open in New Window" in a WebKit widget's context menu now works.
-The newly created buffer will be displayed via 'display-buffer', which
-can be customized through the usual mechanism of 'display-buffer-alist'
-and friends.
-
-** Tramp
-
-+++
-*** New connection methods "docker", "podman" and "kubernetes".
-They allow accessing environments provided by Docker and similar
-programs.
-
----
-*** Tramp supports abbreviating remote home directories now.
-When calling 'abbreviate-file-name' on a Tramp file name, the result
-will abbreviate the user's home directory, for example by abbreviating
-"/ssh:user@host:/home/user" to "/ssh:user@host:~".
-
-+++
-*** New user option 'tramp-use-scp-direct-remote-copying'.
-When set to non-nil, Tramp does not copy files between two remote
-hosts via a local copy in its temporary directory, but lets the 'scp'
-command do this job.
-
-+++
-*** Proper password prompts for methods "doas", "sudo" and "sudoedit".
-The password prompts for these methods reflect now the credentials of
-the user requesting such a connection, and not of the user who is the
-target. This has always been needed, just the password prompt and the
-related 'auth-sources' entry were wrong.
-
-+++
-*** New user option 'tramp-completion-use-cache'.
-During user and host name completion in the minibuffer, results from
-Tramp's connection cache are taken into account. This can be disabled
-by setting the user option 'tramp-completion-use-cache' to nil.
-
-** Browse URL
-
----
-*** New user option 'browse-url-default-scheme'.
-This user option decides which URL scheme that 'browse-url' and
-related functions will use by default. For example, you could
-customize this to "https" to always prefer HTTPS URLs.
-
----
-*** New user option 'browse-url-irc-function'.
-This option specifies a function for opening "irc://" links. It
-defaults to the new function 'browse-url-irc'.
-
----
-*** New function 'browse-url-irc'.
-This multipurpose autoloaded function can be used for opening "irc://"
-and "ircs://" URLS by any caller that passes a URL string as an initial
-arg.
-
----
-*** Support for the Netscape web browser has been removed.
-This support has been obsolete since Emacs 25.1. The final version of
-the Netscape web browser was released in February, 2008.
-
----
-*** Support for the Galeon web browser has been removed.
-This support has been obsolete since Emacs 25.1. The final version of
-the Galeon web browser was released in September, 2008.
-
----
-*** Support for the Mozilla web browser is now obsolete.
-Note that this historical web browser is different from Mozilla
-Firefox; it is its predecessor.
-
-** Python Mode
-
-+++
-*** Project shells and a new user option 'python-shell-dedicated'.
-When called with a prefix argument, 'run-python' now offers the choice
-of creating a shell dedicated to the current project. This shell runs
-in the project root directory and is shared among all project buffers.
-
-Without a prefix argument, the kind of shell (buffer-dedicated,
-project-dedicated or global) is specified by the new
-'python-shell-dedicated' user option.
-
-** Ruby Mode
-
----
-*** New user option 'ruby-toggle-block-space-before-parameters'.
-
----
-*** Support for endless methods.
-
----
-*** New user options that determine indentation logic.
-'ruby-method-params-indent', 'ruby-block-indent',
-'ruby-after-operator-indent', 'ruby-method-call-indent',
-'ruby-parenless-call-arguments-indent'. See the docstrings for
-explanations and examples.
+*** New user option 'bs-default-action-list'.
+You can now configure how to display the "*buffer-selection*" buffer
+using this new option. (Or set 'display-buffer-alist' directly.)
** Eshell
+++
-*** New feature to easily bypass Eshell's own pipelining.
-Prefixing '|', '<' or '>' with an asterisk, i.e. '*|', '*<' or '*>',
-will cause the whole command to be passed to the operating system
-shell. This is particularly useful to bypass Eshell's own pipelining
-support for pipelines which will move a lot of data. See section
-"Running Shell Pipelines Natively" in the Eshell manual, node
-"(eshell) Input/Output".
-
-+++
-*** New module to help supplying absolute file names to remote commands.
-After enabling the new 'eshell-elecslash' module, typing a forward
-slash as the first character of a command line argument will
-automatically insert the Tramp prefix. The automatic insertion
-applies only when 'default-directory' is remote and the command is a
-Lisp function. This frees you from having to keep track of whether
-commands are Lisp function or external when supplying absolute file
-name arguments. See the "(eshell) Electric forward slash" node in the
-Eshell manual for details.
-
-+++
-*** Improved support for redirection operators in Eshell.
-Eshell now supports a wider variety of redirection operators. For
-example, you can now redirect both stdout and stderr via '&>' or
-duplicate one output handle to another via 'NEW-FD>&OLD-FD'. For more
-information, see the "(eshell) Redirection" node in the Eshell manual.
-
-+++
-*** New eshell built-in command 'doas'.
-The privilege-escalation program 'doas' has been added to the existing
-'su' and 'sudo' commands from the 'eshell-tramp' module. The external
-command may still be accessed by using '*doas'.
-
-+++
-*** Double-quoting an Eshell expansion now treats the result as a single string.
-If an Eshell expansion like '$FOO' is surrounded by double quotes, the
-result will always be a single string, no matter the type that would
-otherwise be returned.
+*** New splice operator for Eshell dollar expansions.
+Dollar expansions in Eshell now let you splice the elements of the
+expansion in-place using '$@expr'. This makes it easier to fill lists
+of arguments into a command, such as when defining aliases. For more
+information, see the "(eshell) Dollars Expansion" node in the Eshell
+manual.
+++
-*** Concatenating Eshell expansions now works more similarly to other shells.
-When concatenating an Eshell expansion that returns a list, "adjacent"
-elements of each operand are now concatenated together,
-e.g. '$(list "a" "b")c' returns '("a" "bc")'. See the "(eshell)
-Expansion" node in the Eshell manual for more details.
-
-+++
-*** Eshell subcommands with multiline numeric output return lists of numbers.
-If every line of the output of an Eshell subcommand like '${COMMAND}'
-is numeric, the result will be a list of numbers (or a single number
-if only one line of output). Previously, this only converted numbers
-when there was a single line of output.
-
----
-*** Built-in Eshell commands now follow Posix/GNU argument syntax conventions.
-Built-in commands in Eshell now accept command-line options with
-values passed as a single token, such as '-oVALUE' or
-'--option=VALUE'. New commands can take advantage of this with the
-'eshell-eval-using-options' macro. See "Defining new built-in
-commands" in the "(eshell) Built-ins" node of the Eshell manual.
-
----
-*** Eshell globs ending with '/' now match only directories.
-Additionally, globs ending with '**/' or '***/' no longer raise an
-error, and now expand to all directories recursively (following
-symlinks in the latter case).
+*** 'eshell-read-aliases-list' is now an interactive command.
+After manually editing 'eshell-aliases-file', you can use
+'M-x eshell-read-aliases-list' to load the edited aliases.
+** Prog Mode
+++
-*** Lisp forms in Eshell now treat a nil result as a failed exit status.
-When executing a command that looks like '(lisp form)' and returns
-nil, Eshell will set the exit status (available in the '$?'
-variable) to 2. This allows commands like that to be used in
-conditionals. To change this behavior, customize the new
-'eshell-lisp-form-nil-is-failure' user option.
-
-** Shell
-
----
-*** New user option 'shell-kill-buffer-on-exit'.
-Enabling this will automatically kill a "*shell*" buffer as soon as
-the shell session terminates.
-
----
-*** New minor mode 'shell-highlight-undef-mode'.
-Customize 'shell-highlight-undef-enable' to t if you want to enable
-this minor mode in "*shell*" buffers. It will highlight undefined
-commands with a warning face as you type.
-
-** Calc
-
-+++
-*** New user option 'calc-kill-line-numbering'.
-Set it to nil to exclude line numbering from kills and copies.
-
-** Hierarchy
-
-+++
-*** Tree Display can delay computation of children.
-'hierarchy-add-tree' and 'hierarchy-add-trees' have an optional
-argument which allows tree-widget display to be activated and computed
-only when the user expands the node.
-
-** Proced
-
----
-*** proced.el shows system processes of remote hosts.
-When 'default-directory' is remote, and 'proced' is invoked with a
-negative argument like 'C-u - proced', the system processes of that
-remote host are shown. Alternatively, the user option
-'proced-show-remote-processes' can be set to non-nil.
-'proced-signal-function' has been marked obsolete.
-
----
-*** Proced can now optionally show process details in color.
-New user option 'proced-enable-color-flag' enables coloring of Proced
-buffers. This option is disabled by default; customize it to a
-non-nil value to enable colors.
-
-** Miscellaneous
-
----
-*** New user option 'webjump-use-internal-browser'.
-When non-nil, WebJump will use an internal browser to open web pages,
-instead of the default external browser.
-
-+++
-*** New user option 'font-lock-ignore'.
-This option provides a mechanism to selectively disable font-lock
-keyword-driven fontifications.
-
----
-*** New user option 'auto-save-visited-predicate'.
-This user option is a predicate function which is called by
-'auto-save-visited-mode' to decide whether or not to save a buffer.
-You can use it to automatically save only specific buffers, for
-example buffers using a particular mode or in some directory.
-
----
-*** New user option 'remote-file-name-inhibit-auto-save-visited'.
-If this user option is non-nil, 'auto-save-visited-mode' will not
-auto-save remote buffers. The default is nil.
-
-+++
-*** New package vtable.el for formatting tabular data.
-This package allows formatting data using variable-pitch fonts.
-The resulting tables can display text in variable pitch fonts, text
-using fonts of different sizes, and images. See the "(vtable) Top"
-manual for more details.
-
----
-*** New minor mode 'elide-head-mode'.
-Enabling this minor mode turns on hiding header material, like
-'elide-head' does; disabling it shows the header. The commands
-'elide-head' and 'elide-head-show' are now obsolete.
-
-*** New package ansi-osc.el.
-Support for OSC ("Operating System Command") escape sequences has been
-extracted from comint.el in order to provide interpretation of OSC
-sequences in compilation buffers.
-
-Adding the new function 'ansi-osc-compilation-filter' to
-'compilation-filter-hook' enables interpretation of OSC escape
-sequences in compilation buffers. By default, all sequences are
-filtered out.
-
-The list of handlers (already covering OSC 7 and 8) has been extended
-with a handler for OSC 2, the command to set a window title.
-
----
-*** 'recentf-mode' now uses abbreviated file names by default.
-This means that e.g. "/home/foo/bar" is now displayed as "~/bar".
-Customize the user option 'recentf-filename-handlers' to nil to get
-back the old behavior.
-
----
-*** New command 'recentf-open'.
-This command prompts for a recently opened file in the minibuffer, and
-visits it.
-
----
-*** 'ffap-machine-at-point' no longer pings hosts by default.
-It will now simply look at a hostname to determine if it is valid,
-instead of also trying to ping it. Customize the user option
-'ffap-machine-p-known' to 'ping' to get the old behavior back.
-
----
-*** The 'run-dig' command is now obsolete; use 'dig' instead.
-
----
-*** Some 'bib-mode' commands and variables have been renamed.
-To respect Emacs naming conventions, the variable 'unread-bib-file'
-has been renamed to 'bib-unread-file'. The following commands have
-also been renamed:
- 'addbib' to 'bib-add'
- 'return-key-bib' to 'bib-return-key'
- 'mark-bib' to 'bib-mark'
- 'unread-bib' to 'bib-unread'
-
----
-*** 'outlineify-sticky' command is renamed to 'allout-outlinify-sticky'.
-The old name is still available as an obsolete function alias.
-
----
-*** The url-irc library now understands "ircs://" links.
-
----
-*** New command 'world-clock-copy-time-as-kill' for 'M-x world-clock'.
-It copies the current line into the kill ring.
-
----
-*** 'edit-abbrevs' now uses font-locking.
-The new face 'abbrev-table-name' is used to display the abbrev table
-name.
-
----
-*** New key binding 'O' in 'M-x list-buffers'.
-This key is now bound to 'Buffer-menu-view-other-window', which will
-view this line's buffer in View mode in another window.
-
-** Scheme mode
-
----
-*** Auto-detection of Scheme library files.
-Emacs now automatically enables the Scheme mode when opening R6RS
-Scheme Library Source ('.sls') files and R7RS Scheme Library
-Definition ('.sld') files.
-
----
-*** Imenu members for R6RS and R7RS library members.
-Imenu now lists the members directly nested in R6RS Scheme libraries
-('library') and R7RS libraries ('define-library').
-
+*** New command 'prog-fill-reindent-defun'
+This command either fills a single paragraph in a defun, such as a
+doc-string, or a comment, or (re)indents the surrounding defun if
+point is not in a comment or a string. It is by default bound to
+'M-q' in 'prog-mode' and all its descendants.
-* New Modes and Packages in Emacs 29.1
-
-+++
-** Eglot: Emacs Client for the Language Server Protocol.
-Emacs now comes with the Eglot package, which enhances various Emacs
-features, such as completion, documentation, error detection, etc.,
-based on data provided by language servers using the Language Server
-Protocol (LSP).
-
-+++
-*** use-package: Declarative package configuration.
-use-package is now shipped with Emacs. It provides the 'use-package'
-macro, which allows you to isolate package configuration in your init
-file in a way that is declarative, tidy, and performance-oriented.
-See the new Info manual "(use-package) Top" for more.
-
-+++
-** New commands 'image-crop' and 'image-cut'.
-These commands allow interactively cropping/cutting the image at
-point. The commands are bound to keys 'i c' and 'i x' (respectively)
-in the local keymap over images. They rely on external programs, by
-default "convert" from ImageMagick, to do the actual cropping/eliding
-of the image file.
-
----
-** New package 'wallpaper'.
-This package provides the command 'wallpaper-set', which sets the
-desktop background image. Depending on the system and the desktop,
-this may require an external program (such as "swaybg", "gm",
-"display" or "xloadimage"). If so, a suitable command should be
-detected automatically in most cases. It can also be customized
-manually if needed, using the new user options 'wallpaper-command' and
-'wallpaper-command-args'.
-
-+++
-** New package 'oclosure'.
-This allows the creation of "functions with slots" or "function
-objects" via the macros 'oclosure-define' and 'oclosure-lambda'.
-
-+++
-*** New generic function 'oclosure-interactive-form'.
-Used by 'interactive-form' when called on an OClosure.
-This allows specific OClosure types to compute their interactive specs
-on demand rather than precompute them when created.
-
----
-** New theme 'leuven-dark'.
-This is a dark version of the 'leuven' theme.
-
-+++
-** New mode 'erts-mode'.
-This mode is used to edit files geared towards testing actions in
-Emacs buffers, like indentation and the like. The new ert function
-'ert-test-erts-file' is used to parse these files.
-
----
-** New major mode 'js-json-mode'.
-This is a lightweight variant of 'js-mode' that is used by default
-when visiting JSON files.
-
-+++
-** New major mode 'csharp-mode'.
-A major mode based on CC Mode for editing programs in the C# language.
-This mode is auto-enabled for files with the ".cs" extension.
-
-+++
-** New major modes based on the tree-sitter library.
-These new major modes are available if Emacs was built with the
-tree-sitter library. They provide support for font-locking,
-indentation, and navigation by defuns based on parsing the buffer text
-by a tree-sitter parser. Some major modes also offer support for
-Imenu and 'which-func'.
-
-Where major modes already exist in Emacs for editing certain kinds of
-files, the new modes based on tree-sitter are for now entirely
-optional, and you must turn them on manually, or customize
-'auto-mode-alist' to turn them on automatically.
-
-Each major mode based on tree-sitter needs a language grammar library,
-usually named "libtree-sitter-LANG.so" ("libtree-sitter-LANG.dll" on
-MS-Windows), where LANG is the corresponding language name. Emacs
-looks for these libraries in the following places:
-
- . in the directories mentioned in the list 'treesit-extra-load-path'
- . in the "tree-sitter" subdirectory of your 'user-emacs-directory'
- (by default, "~/.emacs.d/tree-sitter")
- . in the standard system directories where other shared libraries are
- usually installed
-
-We recommend to install these libraries in one of the standard system
-locations (the last place in the above list).
-
-If a language grammar library required by a mode is not found in any
-of the above places, the mode will signal an error when you try to
-turn it on.
-
-+++
-*** New major mode 'typescript-ts-mode'.
-A major mode based on the tree-sitter library for editing programs
-in the TypeScript language. This mode is auto-enabled for files with
-the ".ts" extension.
-
-+++
-*** New major mode 'tsx-ts-mode'.
-A major mode based on the tree-sitter library for editing programs
-in the TypeScript language, with support for TSX. This mode is
-auto-enabled for files with the ".tsx" extension.
-
-+++
-*** New major mode 'c-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the C language.
-
-+++
-*** New major mode 'c++-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the C++ language.
-
-+++
-*** New major mode 'java-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the Java language.
-
-+++
-*** New major mode 'python-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the Python language.
-
-+++
-*** New major mode 'css-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-CSS (Cascading Style Sheets).
-
-+++
-*** New major mode 'json-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the JSON language.
-
-+++
-*** New major mode 'csharp-ts-mode'.
-An optional major mode based on the tree-sitter library for editing
-programs in the C# language.
-
-+++
-*** New major mode 'bash-ts-mode'.
-Am optional major mode based on the tree-sitter library for editing
-Bash shell scripts.
-
-+++
-*** New major mode 'dockerfile-ts-mode'.
-A major mode based on the tree-sitter library for editing
-Dockerfiles. This mode is auto-enabled for files which are named
-"Dockerfile", have the "Dockerfile." prefix, or have the ".dockerfile"
-extension.
-
-+++
-*** New major mode 'cmake-ts-mode'.
-A major mode based on the tree-sitter library for editing CMake files.
-It is auto-enabled for files whose name is "CMakeLists.txt" or whose
-extension is ".cmake".
-
-+++
-*** New major mode 'toml-ts-mode'.
-A major mode based on the tree-sitter library for editing files
-written in TOML, a format for writing configuration files. It is
-auto-enabled for files with the ".toml" extension.
-
-+++
-*** New major mode 'go-ts-mode'.
-A major mode based on the tree-sitter library for editing programs in
-the Go language. It is auto-enabled for files with the ".go" extension.
-
-+++
-*** New major mode 'go-mod-ts-mode'.
-A major mode based on the tree-sitter library for editing "go.mod"
-files. It is auto-enabled for files which are named "go.mod".
-
-+++
-*** New major mode 'yaml-ts-mode'.
-A major mode based on the tree-sitter library for editing files
-written in YAML. It is auto-enabled for files with the ".yaml" or
-".yml" extensions.
-
-+++
-*** New major mode 'rust-ts-mode'.
-A major mode based on the tree-sitter library for editing programs in
-the Rust language. It is auto-enabled for files with the ".rs" extension.
+* New Modes and Packages in Emacs 30.1
-* Incompatible Lisp Changes in Emacs 29.1
-
-+++
-** The implementation of overlays has changed.
-Emacs now uses an implementation of overlays that is much more
-efficient than the original one, and should speed up all the
-operations that involve overlays, especially when there are lots of
-them in a buffer.
-
-As result of this, some minor incompatibilities in behavior could be
-observed, as described below. Except those minor incompatibilities,
-no other changes in behavior of overlays should be visible on the Lisp
-or user level, with the exception of better performance and the order
-of overlays returned by functions that don't promise any particular
-order.
-
----
-*** The function 'overlay-recenter' is now a no-op.
-This function does nothing, and in particular has no effect on the
-value returned by 'overlay-lists'. The purpose of 'overlay-recenter'
-was to allow more efficient lookup of overlays around a certain buffer
-position; however with the new implementation the lookup of overlays
-is efficient regardless of their position, and there's no longer any
-need to "optimize" the lookup, nor any notion of a "center" of the
-overlays.
-
----
-*** The function 'overlay-lists' returns one unified list of overlays.
-This function used to return a cons of two lists, one with overlays
-before the "center" position, the other after that "center". It now
-returns a list whose 'car' is the list of all the buffer overlays, and
-whose 'cdr' is always nil.
-
-+++
-** 'format-prompt' now uses 'substitute-command-keys'.
-This means that both the prompt and 'minibuffer-default-prompt-format'
-will have key definitions and single quotes handled specially.
-
-+++
-** New function 'substitute-quotes'.
-This function works like 'substitute-command-keys' but only
-substitutes quote characters.
-
----
-** 'find-image' now uses 'create-image'.
-This means that images found through 'find-image' also have
-auto-scaling applied. (This only makes a difference on HiDPI
-displays.)
-
-+++
-** Changes in how "raw" in-memory xbm images are specified.
-Some years back Emacs gained the ability to scale images, and you
-could then specify ':width' and ':height' when using 'create-image' on all
-image types -- except xbm images, because this format already used the
-':width' and ':height' arguments to specify the width/height of the "raw"
-in-memory format. This meant that if you used these specifications
-on, for instance, xbm files, Emacs would refuse to display them. This
-has been changed, and ':width'/':height' now works as with all other image
-formats, and the way to specify the width/height of the "raw"
-in-memory format is now by using ':data-width' and ':data-height'.
-
-+++
-** "loaddefs.el" generation has been reimplemented.
-The various "loaddefs.el" files in the Emacs tree (which contain
-information about autoloads, built-in packages and package prefixes)
-used to be generated by functions in autoloads.el. These are now
-generated by loaddefs-gen.el instead. This leads to functionally
-equivalent "loaddef.el" files, but they do not use exactly the same
-syntax, so using 'M-x update-file-autoloads' no longer works. (This
-didn't work well in most files in the past, either, but it will now
-signal an error in any file.)
-
-In addition, files are scanned in a slightly different way.
-Previously, ';;;###' specs inside a top-level form (i.e., something
-like '(when ... ;;;### ...)' would be ignored. They are now parsed as
-usual.
-
----
-** Themes have special autoload cookies.
-All built-in themes are scraped for ';;;###theme-autoload' cookies
-that are loaded along with the regular auto-loaded code.
-
-+++
-** 'buffer-modified-p' has been extended.
-This function was previously documented to return only nil or t. This
-has been changed to nil/'autosaved'/non-nil. The new 'autosaved'
-value means that the buffer is modified, but that it hasn't been
-modified since the time of last auto-save.
-
----
-** 'with-silent-modifications' also restores buffer autosave status.
-'with-silent-modifications' is a macro meant to be used by the font
-locking machinery to allow applying text properties without changing
-the modification status of the buffer. However, it didn't restore the
-buffer autosave status, so applying font locking to a modified buffer
-that had already been auto-saved would trigger another auto-saving.
-This is no longer the case.
-
----
-** 'prin1' doesn't always escape "." and "?" in symbols any more.
-Previously, symbols like 'foo.bar' would be printed by 'prin1' as
-"foo\.bar". This now prints as "foo.bar" instead. The Emacs Lisp
-reader interprets these strings as referring to the same symbol, so
-this is virtually always backwards-compatible, but there may
-theoretically be code out there that expects a specific printed
-representation.
-
-The same is the case with the "?" character: The 'foo?' symbol is now
-printed as "foo?" instead of "foo\?".
-
-If the "." and "?" characters are the first character in the symbol,
-they will still be escaped, so the '.foo' symbol is still printed as
-"\.foo" and the '?bar' symbol is still printed as "\?bar".
-
-+++
-** Remapping 'mode-line' face no longer works as expected.
-'mode-line' is now the parent face of the new 'mode-line-active' face,
-and remapping parent of basic faces does not work reliably.
-Instead of remapping 'mode-line', you have to remap 'mode-line-active'.
-
-+++
-** 'make-process' has been extended to support ptys when ':stderr' is set.
-Previously, setting ':stderr' to a non-nil value would force the
-process's connection to use pipes. Now, Emacs will use a pty for
-stdin and stdout if requested no matter the value of ':stderr'.
-
----
-** User option 'mail-source-ignore-errors' is now obsolete.
-The whole mechanism for prompting users to continue in case of
-mail-source errors has been removed, so this option is no longer
-needed.
-
-** Fonts
-
----
-*** Emacs now supports 'medium' fonts.
-Emacs previously didn't distinguish between the 'regular'/'normal'
-weight and the 'medium' weight, but it now also supports the (heavier)
-'medium' weight. However, this means that if you specify a weight of
-'normal' and the font doesn't have this weight, Emacs won't find the
-font spec. In these cases, replacing ":weight 'normal" with ":weight
-'medium" should fix the issue.
-
----
-** Keymap descriptions have changed.
-'help--describe-command', 'C-h b' and associated functions that output
-keymap descriptions have changed. In particular, prefix commands are
-not output at all, and instead of "??" for closures/functions,
-"[closure]"/"[lambda]" is output.
-
----
-** 'downcase' details have changed slightly.
-In certain locales, changing the case of an ASCII-range character may
-turn it into a multibyte character, most notably with "I" in Turkish
-(the lowercase is "ı", 0x0131). Previously, 'downcase' on a unibyte
-string was buggy, and would mistakenly just return the lower byte of
-this, 0x31 (the digit "1"). 'downcase' on a unibyte string has now
-been changed to downcase such characters as if they were ASCII. To
-get proper locale-dependent downcasing, the string has to be converted
-to multibyte first. (This goes for the other case-changing functions,
-too.)
-
----
-** Functions in 'tramp-foreign-file-name-handler-alist' have changed.
-Functions to determine which Tramp file name handler to use are now
-passed a file name in dissected form (via 'tramp-dissect-file-name')
-instead of in string form.
-
----
-** 'def' indentation changes.
-In 'emacs-lisp-mode', forms with a symbol with a name that start with
-"def" have been automatically indented as if they were 'defun'-like
-forms, for instance:
-
- (defzot 1
- 2 3)
-
-This heuristic has now been removed, and all functions/macros that
-want to be indented this way have to be marked with
-
- (declare (indent defun))
-
-or the like. If the function/macro definition itself can't be
-changed, the indentation can also be adjusted by saying something
-like:
-
- (put 'defzot 'lisp-indent-function 'defun)
-
----
-** The 'inhibit-changing-match-data' variable is now obsolete.
-Instead, functions like 'string-match' and 'looking-at' now take an
-optional INHIBIT-MODIFY argument.
-
----
-** 'gnus-define-keys' is now obsolete.
-Use 'define-keymap' instead.
-
----
-** MozRepl has been removed from js.el.
-MozRepl was removed from Firefox in 2017, so this code doesn't work
-with recent versions of Firefox.
-
----
-** The function 'image-dired-get-exif-data' is now obsolete.
-Use 'exif-parse-file' and 'exif-field' instead.
-
----
-** 'insert-directory' alternatives should not change the free disk space line.
-This change is now applied in 'dired-insert-directory'.
-
----
-** 'compilation-last-buffer' is (finally) declared obsolete.
-It's been obsolete since Emacs-22.1, actually.
-
----
-** Calling 'lsh' now elicits a byte-compiler warning.
-'lsh' behaves in somewhat surprising and platform-dependent ways for
-negative arguments, and is generally slower than 'ash', which should be
-used instead. This warning can be suppressed by surrounding calls to
-'lsh' with the construct '(with-suppressed-warnings ((suspicious lsh)) ...)',
-but switching to 'ash' is generally much preferable.
-
----
-** Some functions and variables obsolete since Emacs 24 have been removed:
-'Buffer-menu-buffer+size-width', 'Electric-buffer-menu-mode',
-'Info-edit-map', 'allout-abbreviate-flattened-numbering',
-'allout-exposure-change-hook', 'allout-mode-deactivate-hook',
-'allout-structure-added-hook', 'allout-structure-deleted-hook',
-'allout-structure-shifted-hook', 'ansi-color-unfontify-region',
-'archive-extract-hooks', 'auth-source-forget-user-or-password',
-'auth-source-hide-passwords', 'auth-source-user-or-password',
-'automatic-hscrolling', 'automount-dir-prefix', 'bibtex-complete',
-'bibtex-entry-field-alist', 'buffer-has-markers-at',
-'buffer-substring-filters', 'byte-compile-disable-print-circle',
-'c-prepare-bug-report-hooks', 'cfengine-mode-abbrevs',
-'change-log-acknowledgement', 'chart-map',
-'checkdoc-comment-style-hooks', 'comint--unquote&expand-filename',
-'comint-dynamic-complete', 'comint-dynamic-complete-as-filename',
-'comint-dynamic-simple-complete', 'comint-unquote-filename',
-'command-history-map', 'compilation-parse-errors-function',
-'completion-annotate-function', 'condition-case-no-debug',
-'count-lines-region', 'crisp-mode-modeline-string',
-'custom-print-functions', 'custom-print-functions',
-'cvs-string-prefix-p', 'data-debug-map', 'deferred-action-function',
-'deferred-action-list', 'dired-pop-to-buffer', 'dired-shrink-to-fit',
-'dired-sort-set-modeline', 'dired-x-submit-report',
-'display-buffer-function',
-'ediff-choose-window-setup-function-automatically',
-'eieio-defgeneric', 'eieio-defmethod', 'emacs-lock-from-exiting',
-'erc-complete-word', 'erc-dcc-chat-filter-hook',
-'eshell-add-to-window-buffer-names', 'eshell-cmpl-suffix-list',
-'eshell-for', 'eshell-remove-from-window-buffer-names',
-'eshell-status-in-modeline', 'filesets-cache-fill-content-hooks',
-'font-list-limit', 'font-lock-maximum-size',
-'font-lock-reference-face', 'gnus-carpal',
-'gnus-debug-exclude-variables', 'gnus-debug-files',
-'gnus-local-domain', 'gnus-outgoing-message-group',
-'gnus-registry-user-format-function-M', 'gnus-secondary-servers',
-'gnus-subscribe-newsgroup-hooks', 'gud-inhibit-global-bindings',
-'hangul-input-method-inactivate', 'hfy-post-html-hooks',
-'image-extension-data', 'image-library-alist',
-'inactivate-current-input-method-function', 'inactivate-input-method',
-'inhibit-first-line-modes-regexps',
-'inhibit-first-line-modes-suffixes', 'input-method-inactivate-hook',
-'intdos', 'javascript-generic-mode', 'javascript-generic-mode-hook',
-'latex-string-prefix-p', 'macro-declaration-function' (function),
-'macro-declaration-function' (variable), 'mail-complete-function',
-'mail-completion-at-point-function',
-'mail-mailer-swallows-blank-line', 'mail-sent-via', 'make-register',
-'makefile-complete', 'menu-bar-kill-ring-save',
-'meta-complete-symbol', 'meta-mode-map',
-'mh-kill-folder-suppress-prompt-hooks',
-'minibuffer-completing-symbol',
-'minibuffer-local-filename-must-match-map', 'mode25', 'mode4350',
-'mpc-string-prefix-p', 'msb-after-load-hooks',
-'nndiary-request-accept-article-hooks',
-'nndiary-request-create-group-hooks',
-'nndiary-request-update-info-hooks', 'nnimap-split-rule',
-'nntp-authinfo-file', 'ns-alternatives-map',
-'ns-store-cut-buffer-internal', 'package-menu-view-commentary',
-'pascal-last-completions', 'pascal-show-completions',
-'pascal-toggle-completions', 'pcomplete-arg-quote-list',
-'pcomplete-quote-argument', 'prolog-char-quote-workaround',
-'python-buffer', 'python-guess-indent', 'python-indent',
-'python-info-ppss-comment-or-string-p', 'python-info-ppss-context',
-'python-info-ppss-context-type', 'python-preoutput-result',
-'python-proc', 'python-send-receive', 'python-send-string',
-'python-use-skeletons', 'quail-inactivate', 'quail-inactivate-hook',
-'query-replace-interactive', 'rcirc-activity-hooks',
-'rcirc-print-hooks', 'rcirc-receive-message-hooks',
-'rcirc-sentinel-hooks', 'read-filename-at-point', 'redraw-modeline',
-'reftex-index-map', 'reftex-index-phrases-map',
-'reftex-select-bib-map', 'reftex-select-label-map', 'reftex-toc-map',
-'register-name-alist', 'register-value', 'report-emacs-bug-info',
-'report-emacs-bug-pretest-address',
-'rmail-default-dont-reply-to-names', 'rmail-dont-reply-to',
-'rmail-dont-reply-to-names', 'robin-inactivate',
-'robin-inactivate-hook', 'rst-block-face', 'rst-comment-face',
-'rst-definition-face', 'rst-directive-face', 'rst-emphasis1-face',
-'rst-emphasis2-face', 'rst-external-face', 'rst-literal-face',
-'rst-reference-face', 'semantic-change-hooks',
-'semantic-edits-delete-change-hooks',
-'semantic-edits-new-change-hooks',
-'semantic-edits-reparse-change-hooks', 'semantic-grammar-map',
-'semantic-grammar-syntax-table', 'semantic-lex-reset-hooks',
-'semanticdb-elisp-sym-function-arglist',
-'semanticdb-save-database-hooks', 'set-face-underline-p',
-'set-register-value', 'sh-maybe-here-document', 'speedbar-key-map',
-'speedbar-syntax-table', 'starttls-any-program-available',
-'strokes-modeline-string', 'strokes-report-bug',
-'term-default-bg-color', 'term-default-fg-color',
-'tex-string-prefix-p', 'timeclock-modeline-display',
-'timeclock-modeline-display', 'timeclock-update-modeline',
-'toggle-emacs-lock', 'tooltip-use-echo-area', 'turn-on-cwarn-mode',
-'turn-on-iimage-mode', 'ucs-input-inactivate', 'ucs-insert',
-'url-recreate-url-attributes', 'user-variable-p',
-'vc-string-prefix-p', 'vc-toggle-read-only', 'view-return-to-alist',
-'view-return-to-alist-update', 'w32-default-color-map' (function),
-'which-func-mode' (function), 'window-system-version',
-'winner-mode-leave-hook', 'x-cut-buffer-or-selection-value'.
-
----
-** Some functions and variables obsolete since Emacs 23 have been removed:
-'find-emacs-lisp-shadows', 'newsticker-cache-filename',
-'process-filter-multibyte-p', 'redisplay-end-trigger-functions',
-'set-process-filter-multibyte', 'set-window-redisplay-end-trigger',
-'unify-8859-on-decoding-mode', 'unify-8859-on-encoding-mode',
-'vc-arch-command', 'window-redisplay-end-trigger', 'x-selection'.
-
----
-** Some functions and variables obsolete since Emacs 21 or 22 have been removed:
-'c-toggle-auto-state', 'find-file-not-found-hooks',
-'ls-lisp-dired-ignore-case', 'query-replace-regexp-eval'.
-
-+++
-** New generic function 'function-documentation'.
-It can dynamically generate a raw docstring depending on the type of a
-function. Used mainly for docstrings of OClosures.
-
-+++
-** Base64 encoding no longer tolerates latin-1 input.
-The functions 'base64-encode-string', 'base64url-encode-string',
-'base64-encode-region' and 'base64url-encode-region' no longer accept
-characters in the range U+0080..U+00FF as substitutes for single bytes
-in the range 128..255, but signal an error for all multibyte characters.
-The input must be unibyte encoded text.
-
-+++
-** The 'clone-indirect-buffer-hook' is now run by 'make-indirect-buffer'.
-It was previously only run by 'clone-indirect-buffer' and
-'clone-indirect-buffer-other-window'. Since 'make-indirect-buffer' is
-called by both of these, the hook is now run by all 3 of these
-functions.
-
----
-** '?\' at the end of a line now signals an error.
-Previously, it produced a nonsense value, -1, that was never intended.
-
----
-** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed:
-abbrevlist.el, assoc.el, complete.el, cust-print.el,
-erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el,
-patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
-
-+++
-** Many seldom-used generalized variables have been made obsolete.
-Emacs has a number of rather obscure generalized variables defined,
-that, for instance, allowed you to say things like:
-
- (setf (point-min) 4)
-
-These never caught on and have been made obsolete. The form above,
-for instance, is the same as saying
-
- (narrow-to-region 4 (point-max))
-
-The following generalized variables have been made obsolete:
-'buffer-file-name', 'buffer-local-value', 'buffer-modified-p',
-'buffer-name', 'buffer-string', 'buffer-substring', 'current-buffer',
-'current-column', 'current-global-map', 'current-input-mode',
-'current-local-map', 'current-window-configuration',
-'default-file-modes', 'documentation-property', 'eq', 'frame-height',
-'frame-width', 'frame-visible-p', 'global-key-binding',
-'local-key-binding', 'mark', 'mark-marker', 'marker-position',
-'mouse-position', 'point', 'point-marker', 'point-max', 'point-min',
-'read-mouse-position', 'screen-height', 'screen-width',
-'selected-frame', 'selected-screen', 'selected-window',
-'standard-case-table', 'syntax-table', 'visited-file-modtime',
-'window-height', 'window-width', and 'x-get-secondary-selection'.
+* Incompatible Lisp Changes in Emacs 30.1
-* Lisp Changes in Emacs 29.1
-
-+++
-** Interpreted closures are "safe for space".
-As was already the case for byte-compiled closures, instead of capturing
-the whole current lexical environment, interpreted closures now only
-capture the part of the environment that they need.
-The previous behavior could occasionally lead to memory leaks or
-to problems where a printed closure would not be 'read'able because
-of an un'read'able value in an unrelated lexical variable.
-
-+++
-** New accessor function 'file-attribute-file-identifier'.
-It returns the list of the inode number and device identifier
-retrieved by 'file-attributes'. This value can be used to identify a
-file uniquely. The device identifier can be a single number or (for
-remote files) a cons of 2 numbers.
-
-+++
-** New macro 'while-let'.
-This is like 'when-let', but repeats until a binding form is nil.
-
-+++
-** New function 'make-obsolete-generalized-variable'.
-This can be used to mark setters used by 'setf' as obsolete, and the
-byte-compiler will then warn about using them.
-
-+++
-** New functions 'pos-eol' and 'pos-bol'.
-These are like 'line-end-position' and 'line-beginning-position'
-(respectively), but ignore fields (and are more efficient).
-
-+++
-** New function 'compiled-function-p'.
-This returns non-nil if its argument is either a built-in, or a
-byte-compiled, or a natively-compiled function object, or a function
-loaded from a dynamic module.
-
----
-** 'deactivate-mark' can have new value 'dont-save'.
-This value means that Emacs should deactivate the mark as usual, but
-without setting the primary selection, if 'select-active-regions' is
-enabled.
-
-+++
-** New 'declare' form 'interactive-args'.
-This can be used to specify what forms to put into 'command-history'
-when executing commands interactively.
-
-+++
-** The FORM arg of 'time-convert' is mandatory.
-'time-convert' can still be called without it, as before, but the
-compiler now emits a warning about this deprecated usage.
-
-+++
-** Emacs now supports user-customizable and themable icons.
-These can be used for buttons in buffers and the like. See the
-"(elisp) Icons" and "(emacs) Icons" nodes in the manuals for details.
-
-+++
-** New arguments MESSAGE and TIMEOUT of 'set-transient-map'.
-MESSAGE specifies a message to display after activating the transient
-map, including a special formatting spec to list available keys.
-TIMEOUT is the idle time after which to deactivate the transient map.
-The default timeout value can be defined by the new variable
-'set-transient-map-timeout'.
-
-** Connection-local variables
-
-+++
-*** Some connection-local variables are now user options.
-The variables 'connection-local-profile-alist' and
-'connection-local-criteria-alist' are now user options, in order to
-make it more convenient to inspect and modify them.
-
-+++
-*** New function 'connection-local-update-profile-variables'.
-This function allows to modify the settings of an existing
-connection-local profile.
-
-+++
-*** New macro 'with-connection-local-application-variables'.
-This macro works like 'with-connection-local-variables', but it allows
-to use another application but 'tramp'. This is useful when running
-code in a buffer where Tramp has already set some connection-local
-variables.
-
-+++
-*** New macro 'setq-connection-local'.
-This allows dynamically setting variable values for a particular
-connection within the body of 'with-connection-local-{application-}variables'.
-See the "(elisp) Connection Local Variables" node in the Lisp
-Reference manual for more information.
-
-+++
-** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
-These function now take an optional comparison predicate argument.
-
-+++
-** 'read-multiple-choice' can now use long-form answers.
-
-+++
-** 'M-c' in 'read-regexp' now toggles case folding.
-
-+++
-** 'completing-read' now allows a function as its REQUIRE-MATCH argument.
-This function is called to see whether what the user has typed is a
-match. This is also available from functions that call
-'completing-read', like 'read-file-name'.
-
-+++
-** 'posn-col-row' can now give position data based on windows.
-Previously, it reported data only based on the frame.
-
-+++
-** 'file-expand-wildcards' can now also take a regexp as PATTERN argument.
-
----
-** vc-mtn (the VC backend for Monotone) has been made obsolete.
-
-+++
-** 'gui-set-selection' can specify different values for different data types.
-If DATA is a string, then its text properties are searched for values
-for each specific data type while the selection is being converted.
-
----
-** New eldoc function 'elisp-eldoc-var-docstring-with-value'.
-This function includes the current value of the variable in eldoc display
-and can be used as a more detailed alternative to 'elisp-eldoc-var-docstring'.
-
-+++
-** 'save-some-buffers' can now be extended to save other things.
-Traditionally, 'save-some-buffers' saved buffers, and also saved
-abbrevs. This has been generalized via the
-'save-some-buffers-functions' variable, and packages can now register
-things to be saved.
-
-+++
-** New function 'string-equal-ignore-case'.
-This compares strings ignoring case differences.
-
-+++
-** 'symbol-file' can now report natively-compiled ".eln" files.
-If Emacs was built with native-compilation enabled, Lisp programs can
-now call 'symbol-file' with the new optional 3rd argument non-nil to
-request the name of the ".eln" file which defined a given symbol.
-
-+++
-** New macro 'with-memoization' provides a very primitive form of memoization.
-
-+++
-** 'max-char' can now report the maximum codepoint according to Unicode.
-When called with a new optional argument UNICODE non-nil, 'max-char'
-will now report the maximum valid codepoint defined by the Unicode
-Standard.
-
-** seq
-
-+++
-** New function 'seq-split'.
-This returns a list of sub-sequences of the specified sequence.
-
-+++
-** New function 'seq-remove-at-position'.
-This function returns a copy of the specified sequence where the
-element at a given (zero-based) index got removed.
-
-+++
-** New function 'seq-positions'.
-This returns a list of the (zero-based) indices of elements matching a
-given predicate in the specified sequence.
-
-+++
-** New function 'seq-keep'.
-This is like 'seq-map', but removes all nil results from the returned
-list.
-
-** Themes
-
----
-*** New hooks 'enable-theme-functions' and 'disable-theme-functions'.
-These are run after enabling and disabling a theme, respectively.
-
----
-*** Themes can now be made obsolete.
-Using 'make-obsolete' on a theme is now supported. This will make
-'load-theme' issue a warning when loading the theme.
-
-+++
-** New hook 'display-monitors-changed-functions'.
-It is called whenever the configuration of different monitors on a
-display changes.
-
-+++
-** 'prin1' and 'prin1-to-string' now take an optional OVERRIDES parameter.
-This parameter can be used to override values of print-related settings.
-
-+++
-** New minor mode 'header-line-indent-mode'.
-This is meant to be used in modes that have a header line that should
-be kept aligned with the buffer contents when the user switches
-'display-line-numbers-mode' on or off.
-
-+++
-** New minor mode 'lost-selection-mode'.
-This minor mode makes Emacs deactivate the mark in all buffers when
-the primary selection is obtained by another program.
-
----
-** On X, Emacs will try to preserve selection ownership when a frame is deleted.
-This means that if you make Emacs the owner of a selection, such as by
-selecting some text into the clipboard or primary selection, and then
-delete the current frame, you will still be able to insert the
-contents of that selection into other programs as long as another
-frame is open on the same display. This behavior can be disabled by
-setting the user option 'x-auto-preserve-selections' to nil.
-
-+++
-** New predicate 'char-uppercase-p'.
-This returns non-nil if its argument its an uppercase character.
-
-** Byte compilation
-
----
-*** Byte compilation will now warn about some quoting mistakes in docstrings.
-When writing code snippets that contains the "'" character (APOSTROPHE),
-that quote character has to be escaped to avoid Emacs displaying it as
-"’" (LEFT SINGLE QUOTATION MARK), which would make code examples like
-
- (setq foo '(1 2 3))
-
-invalid. Emacs will now warn during byte compilation if it seems
-something like that, and also warn about when using RIGHT/LEFT SINGLE
-QUOTATION MARK directly. In both these cases, if these characters
-should really be present in the docstring, they should be quoted with
-"\=".
-
----
-*** Byte compilation will now warn about some malformed 'defcustom' types.
-It's very common to write 'defcustom' types on the form:
-
- :type '(choice (const :tag "foo" 'bar))
-
-I.e., double-quoting the 'bar', which is almost never the correct
-value. The byte compiler will now issue a warning if it encounters
-these forms.
-
-+++
-** 'restore-buffer-modified-p' can now alter buffer auto-save state.
-With a FLAG value of 'autosaved', it will mark the buffer as having
-been auto-saved since the time of last modification.
-
----
-** New minor mode 'isearch-fold-quotes-mode'.
-This sets up 'search-default-mode' so that quote characters are
-char-folded into each other. It is used, by default, in "*Help*" and
-"*info*" buffers.
-
-+++
-** New macro 'buffer-local-set-state'.
-This is a helper macro to be used by minor modes that wish to restore
-buffer-local variables back to their original states when the mode is
-switched off.
-
----
-** New macro 'with-buffer-unmodified-if-unchanged'.
-If the buffer is marked as unmodified, and code does modifications
-that, in total, means that the buffer is identical to the buffer
-before, mark the buffer as unmodified again.
-
----
-** New function 'malloc-trim'.
-This function allows returning unused memory back to the operating
-system, and is mainly meant as a debugging tool. It is currently
-available only when Emacs was built with glibc as the C library.
-
----
-** 'x-show-tip' no longer hard-codes a timeout default.
-The new variable 'x-show-tooltip-timeout' allows the user to alter
-this for packages that don't use 'tooltip-show', but instead call the
-lower level function directly.
-
----
-** New function 'current-cpu-time'.
-It gives access to the CPU time used by the Emacs process, for
-example for benchmarking purposes.
-
----
-** New function 'string-edit'.
-This is meant to be used when the user has to edit a (potentially)
-long string. It pops up a new buffer where you can edit the string,
-and a callback is called when the user types 'C-c C-c'.
-
-+++
-** New function 'read-string-from-buffer'.
-This is a modal version of 'string-edit', and can be used as an
-alternative to 'read-string'.
-
-+++
-** The return value of 'clear-message-function' is not ignored anymore.
-If the function returns 'dont-clear-message', then the message is not
-cleared, with the assumption that the function cleared it itself.
-
-+++
-** The local variables section now supports defining fallback modes.
-This was previously only available when using a property line (i.e.,
-putting the modes on the first line of a file).
-
-+++
-** New function 'flush-standard-output'.
-This enables display of lines that don't end in a newline from
-batch-based Emacs scripts.
-
-+++
-** New convenience function 'buttonize-region'.
-This works like 'buttonize', but for a region instead of a string.
-
-+++
-** 'macroexp-let2*' can omit TEST arg and use single-var bindings.
-
-+++
-** New macro-writing macros, 'cl-with-gensyms' and 'cl-once-only'.
-See the "(cl) Macro-Writing Macros" manual section for descriptions.
-
-+++
-** New variable 'last-event-device' and new function 'device-class'.
-On X Windows, 'last-event-device' specifies the input extension device
-from which the last input event originated, and 'device-class' can be
-used to determine the type of an input device.
-
-+++
-** 'track-mouse' can have a new value 'drag-source'.
-This means the same as 'dropping', but modifies the mouse position
-list in reported motion events if there is no frame underneath the
-mouse pointer.
-
-+++
-** New functions for dragging items from Emacs to other programs.
-The new functions 'x-begin-drag', 'dnd-begin-file-drag',
-'dnd-begin-drag-files', and 'dnd-direct-save' allow dragging contents
-(such as files and text) from Emacs to other programs.
-
----
-** New function 'ietf-drums-parse-date-string'.
-This function parses RFC5322 (and RFC822) date strings, and should be
-used instead of 'parse-time-string' when parsing data that's standards
-compliant.
-
-+++
-** New macro 'setopt'.
-This is like 'setq', but is meant to be used for user options instead
-of plain variables, and uses 'custom-set'/'set-default' to set them.
-
-+++
-** New utility predicate 'mode-line-window-selected-p'.
-This is meant to be used from ':eval' mode line constructs to create
-different mode line looks for selected and unselected windows.
-
-+++
-** New variable 'messages-buffer-name'.
-This variable (defaulting to "*Messages*") allows packages to override
-where messages are logged.
-
-+++
-** New function 'readablep'.
-This function says whether an object can be written out and then
-read back by the Emacs Lisp reader.
-
-+++
-** New variable 'print-unreadable-function'.
-This variable allows changing how Emacs prints unreadable objects.
-
----
-** The user option 'polling-period' now accepts floating point values.
-This means Emacs can now poll for input during Lisp execution more
-frequently than once in a second.
-
----
-** New function 'bidi-string-strip-control-characters'.
-This utility function is meant for displaying strings when it's
-essential that there's no bidirectional context. It removes all the
-bidirectional formatting control characters (such as RLM, LRO, PDF,
-etc.) from its argument string. The characters it removes are listed
-in the value of 'bidi-control-characters'.
-
----
-** The Gnus range functions have been moved to a new library, range.el.
-All the old names have been made obsolete.
-
-+++
-** New function 'function-alias-p'.
-This predicate says whether an object is a function alias, and if it
-is, the alias chain is returned.
-
-+++
-** New variable 'lisp-directory' holds the directory of Emacs's own Lisp files.
-
-+++
-** New facility for handling session state: 'multisession-value'.
-This can be used as a convenient way to store (simple) application
-state, and the command 'list-multisession-values' allows users to list
-(and edit) this data.
-
-+++
-** New function 'get-display-property'.
-This is like 'get-text-property', but works on the 'display' text
-property.
-
-+++
-** New function 'add-display-text-property'.
-This is like 'put-text-property', but works on the 'display' text
-property.
-
-+++
-** New 'min-width' 'display' property.
-This allows setting a minimum display width for a region of text.
-
-+++
-** New 'cursor-face' text property.
-This uses 'cursor-face' instead of the default face when cursor is on or
-near the character and 'cursor-face-highlight-mode' is enabled. The
-user option 'cursor-face-highlight-nonselected-window' is similar to
-'highlight-nonselected-windows', but for this property.
-
-+++
-** New event type 'touch-end'.
-This event is sent whenever the user's finger moves off the mouse
-wheel on some mice, or when the user's finger moves off the touchpad.
-
-+++
-** New event type 'pinch'.
-This event is sent when a user performs a pinch gesture on a touchpad,
-which is comprised of placing two fingers on the touchpad and moving
-them towards or away from each other.
-
-+++
-** New hook 'x-pre-popup-menu-hook'.
-This hook is run before 'x-popup-menu' is about to display a
-deck-of-cards menu on screen.
-
----
-** New hook 'post-select-region-hook'.
-This hook is run immediately after 'select-active-regions' causes the
-region to be set as the primary selection.
-
-+++
-** New function 'buffer-match-p'.
-Check if a buffer satisfies some condition. Some examples for
-conditions can be regular expressions that match a buffer name, a
-cons-cell like '(major-mode . shell-mode)' that matches any buffer
-where 'major-mode' is 'shell-mode' or a combined with a condition like
-'(and "\\`\\*.+\\*\\'" (major-mode . special-mode))'.
-
-+++
-** New function 'match-buffers'.
-Use 'buffer-match-p' to gather a list of buffers that match a
-condition.
-
----
-** New optional arguments 'text-face' and 'default-face' for 'tooltip-show'.
-They allow changing the faces used for the tooltip text and frame
-colors of the resulting tooltip frame from the default 'tooltip' face.
-
-** Text security and suspiciousness
-
-+++
-*** New library textsec.el.
-This library contains a number of checks for whether a string is
-"suspicious". This usually means that the string contains characters
-that have glyphs that can be confused with other, more commonly used
-glyphs, or contain bidirectional (or other) formatting characters that
-may be used to confuse a user.
-
-+++
-*** New user option 'textsec-check'.
-If non-nil (which is the default), Emacs packages that are vulnerable
-to attackers trying to confuse the users will use the textsec library
-to mark suspicious text. For instance shr/eww will mark suspicious
-URLs and links, Gnus will mark suspicious From addresses, and
-Message mode will query the user if the user is sending mail to a
-suspicious address. If this variable is nil, these checks are
-disabled.
-
-+++
-*** New function 'textsec-suspicious-p'.
-This is the main function Emacs applications should be using to check
-whether a string is suspicious. It heeds the 'textsec-check' user
-option.
-
-** Keymaps and key definitions
-
-+++
-*** 'where-is-internal' can now filter events marked as non key events.
-If a command maps to a key binding like '[some-event]', and 'some-event'
-has a symbol plist containing a non-nil 'non-key-event' property, then
-that binding is ignored by 'where-is-internal'.
-
-+++
-*** New functions for defining and manipulating keystrokes.
-These all take the syntax defined by 'key-valid-p'. None of the older
-functions have been deprecated or altered, but they are now
-de-emphasized in the documentation.
+* Lisp Changes in Emacs 30.1
-+++
-*** Use 'keymap-set' instead of 'define-key'.
-
-+++
-*** Use 'keymap-global-set' instead of 'global-set-key'.
-
-+++
-*** Use 'keymap-local-set' instead of 'local-set-key'.
-
-+++
-*** Use 'keymap-global-unset' instead of 'global-unset-key'.
-
-+++
-*** Use 'keymap-local-unset' instead of 'local-unset-key'.
-
-+++
-*** Use 'keymap-substitute' instead of 'substitute-key-definition'.
-
-+++
-*** Use 'keymap-set-after' instead of 'define-key-after'.
-
-+++
-*** Use 'keymap-lookup' instead of 'lookup-keymap' and 'key-binding'.
-
-+++
-*** Use 'keymap-local-lookup' instead of 'local-key-binding'.
-
-+++
-*** Use 'keymap-global-lookup' instead of 'global-key-binding'.
-
-+++
-*** 'define-key' now takes an optional REMOVE argument.
-If non-nil, remove the definition from the keymap. This is subtly
-different from setting a definition to nil (when the keymap has a
-parent).
-
-+++
-*** 'read-multiple-choice' now takes an optional SHOW-HELP argument.
-If non-nil, show the help buffer immediately, before any user input.
-
-+++
-*** New function 'key-valid-p'.
-The 'kbd' function is quite permissive, and will try to return
-something usable even if the syntax of the argument isn't completely
-correct. The 'key-valid-p' predicate does a stricter check of the
-syntax.
-
----
-*** New function 'key-parse'.
-This is like 'kbd', but only returns vectors instead of a mix of
-vectors and strings.
-
-+++
-*** New ':type' for 'defcustom' for keys.
-The new 'key' type can be used for options that should be a valid key
-according to 'key-valid-p'. The type 'key-sequence' is now obsolete.
-
-+++
-** New substitution in docstrings and 'substitute-command-keys'.
-Use \\`KEYSEQ' to insert a literal key sequence "KEYSEQ" (for example
-\\`C-k') in a docstring or when calling 'substitute-command-keys',
-which will use the same face as a command substitution. This should
-be used only when a key sequence has no corresponding command, for
-example when it is read directly with 'read-key-sequence'. It must be
-a valid key sequence according to 'key-valid-p'.
-
-+++
-** New function 'file-name-split'.
-This returns a list of all the components of a file name.
-
-+++
-** New function 'file-name-parent-directory'.
-This returns the parent directory of a file name.
-
-+++
-** New macro 'with-undo-amalgamate'.
-It records a particular sequence of operations as a single undo step.
-
-+++
-** New command 'yank-media'.
-This command supports yanking non-plain-text media like images and
-HTML from other applications into Emacs. It is only supported in
-modes that have registered support for it, and only on capable
-platforms.
-
-+++
-** New command 'yank-media-types'.
-This command lets you examine all data in the current selection and
-the clipboard, and insert it into the buffer.
-
-+++
-** New variable 'yank-transform-functions'.
-This variable allows the user to alter the string to be inserted.
-
----
-** New command 'yank-in-context'.
-This command tries to preserve string/comment syntax when yanking.
-
----
-** New function 'minibuffer-lazy-highlight-setup'.
-This function allows setting up the minibuffer so that lazy
-highlighting of its content is applied in the original window.
-
-+++
-** New text property 'inhibit-isearch'.
-If set, 'isearch' will skip these areas, which can be useful (for
-instance) when covering huge amounts of data (that has no meaningful
-searchable data, like image data) with a 'display' text property.
-
-+++
-** 'insert-image' now takes an INHIBIT-ISEARCH optional parameter.
-It marks the image with the 'inhibit-isearch' text property, which
-inhibits 'isearch' matching the STRING parameter.
+** New or changed byte-compilation warnings
---
-** New variable 'replace-regexp-function'.
-Function to call to convert the entered FROM string to an Emacs
-regexp in 'query-replace' and similar commands. It can be used to
-implement a different regexp syntax for search/replace.
+*** Warn about empty bodies for more special forms and macros.
+The compiler now warns about an empty body argument to 'when',
+'unless', 'ignore-error' and 'with-suppressed-warnings' in addition to
+the existing warnings for 'let' and 'let*'. Example:
----
-** New variables to customize defaults of FROM for 'query-replace*' commands.
-The new variable 'query-replace-read-from-default' can be set to a
-function that returns the default value of FROM when 'query-replace'
-prompts for a string to be replaced. An example of such a function is
-'find-tag-default'.
+ (when (> x 2))
-The new variable 'query-replace-read-from-regexp-default' can be set
-to a function (such as 'find-tag-default-as-regexp') that returns the
-default value of FROM when 'query-replace-regexp' prompts for a regexp
-whose matches are to be replaced. If these variables are nil (which
-is the default), 'query-replace' and 'query-replace-regexp' take the
-default value from the previous FROM-TO pair.
+This warning can be suppressed using 'with-suppressed-warnings' with
+the warning name 'empty-body'.
---
-** New user option 'pp-use-max-width'.
-If non-nil, 'pp' will attempt to limit the line length when formatting
-long lists and vectors.
+*** Warn about quoted error names in 'condition-case' and 'ignore-error'.
+The compiler now warns about quoted condition (error) names
+in 'condition-case' and 'ignore-error'. Example:
----
-** New function 'pp-emacs-lisp-code'.
-'pp' formats general Lisp sexps. This function does much the same,
-but applies formatting rules appropriate for Emacs Lisp code.
+ (condition-case nil
+ (/ x y)
+ ('arith-error "division by zero"))
-+++
-** New function 'file-has-changed-p'.
-This convenience function is useful when writing code that parses
-files at run-time, and allows Lisp programs to re-parse files only
-when they have changed.
-
-+++
-** 'abbreviate-file-name' now respects magic file name handlers.
+Quoting them adds the error name 'quote' to those handled or ignored
+respectively, which was probably not intended.
---
-** New function 'font-has-char-p'.
-This can be used to check whether a specific font has a glyph for a
-character.
+*** Warn about comparison with literal constants without defined identity.
+The compiler now warns about comparisons by identity with a literal
+string, cons, vector, record, function, large integer or float as this
+may not match any value at all. Example:
-+++
-** 'window-text-pixel-size' now accepts a new argument IGNORE-LINE-AT-END.
-This controls whether or not the last screen line of the text being
-measured will be counted for the purpose of calculating the text
-dimensions.
-
-+++
-** 'window-text-pixel-size' understands a new meaning of FROM.
-Specifying a cons as the FROM argument allows to start measuring text
-from a specified amount of pixels above or below a position.
+ (eq x "hello")
-+++
-** 'window-body-width' and 'window-body-height' can use remapped faces.
-Specifying 'remap' as the PIXELWISE argument now checks if the default
-face was remapped, and if so, uses the remapped face to determine the
-character width/height.
+Only literals for symbols and small integers (fixnums), including
+characters, are guaranteed to have a consistent (unique) identity.
+This warning applies to 'eq', 'eql', 'memq', 'memql', 'assq', 'rassq',
+'remq' and 'delq'.
-+++
-** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P.
-This means the vscroll will not be reset when set on a window that is
-"frozen" due to a mini-window being resized.
+To compare by (structural) value, use 'equal', 'member', 'assoc',
+'rassoc', 'remove' or 'delete' instead. Floats and bignums can also
+be compared using 'eql', '=' and 'memql'. Function literals cannot be
+compared reliably at all.
-** XDG support
+This warning can be suppressed using 'with-suppressed-warnings' with
+the warning name 'suspicious'.
----
-*** New function 'xdg-state-home'.
-It returns the new 'XDG_STATE_HOME' environment variable. It should
-point to a file name that "contains state data that should persist
-between (application) restarts, but that is not important or portable
-enough to the user that it should be stored in $XDG_DATA_HOME".
-(This variable was introduced in the XDG Base Directory Specification
-version 0.8 released on May 8, 2021.)
-
----
-*** New function 'xdg-current-desktop'.
-It returns a list of strings, corresponding to the colon-separated
-list of names in the 'XDG_CURRENT_DESKTOP' environment variable, which
-identify the current desktop environment.
-(This variable was introduced in XDG Desktop Entry Specification
-version 1.2.)
-
----
-*** New function 'xdg-session-type'.
-It returns the 'XDG_SESSION_TYPE' environment variable. (This is not
-part of any official standard; see the man page pam_systemd(8) for
-more information.)
-
-+++
-** New macro 'with-delayed-message'.
-This macro is like 'progn', but will output the specified message if
-the body takes longer to execute than the specified timeout.
-
----
-** New function 'funcall-with-delayed-message'.
-This function is like 'funcall', but will output the specified message
-if the function takes longer to execute than the specified timeout.
-
-** Locale
-
----
-*** New variable 'current-locale-environment'.
-This holds the value of the previous call to 'set-locale-environment'.
-
----
-*** New macro 'with-locale-environment'.
-This macro can be used to change the locale temporarily while
-executing code.
-
-** table.el
-
----
-*** New user option 'table-latex-environment'.
-This allows switching between "table" and "tabular".
-
-** Tabulated List Mode
-
-+++
-*** A column can now be set to an image descriptor.
-The 'tabulated-list-entries' variable now supports using an image
-descriptor, which means to insert an image in that column instead of
-text. See the documentation string of that variable for details.
-
-+++
-** ':keys' in 'menu-item' can now be a function.
-If so, it is called whenever the menu is computed, and can be used to
-calculate the keys dynamically.
-
-+++
-** New major mode 'clean-mode'.
-This is a new major mode meant for debugging. It kills absolutely all
-local variables and removes overlays and text properties.
-
-+++
-** 'kill-all-local-variables' can now kill all local variables.
-If given the new optional KILL-PERMANENT argument, also kill permanent
-local variables.
-
-+++
-** Third 'mapconcat' argument SEPARATOR is now optional.
-An explicit nil always meant the empty string, now it can be left out.
-
-+++
-** New function 'define-keymap'.
-This function allows defining a number of keystrokes with one form.
-
-+++
-** New macro 'defvar-keymap'.
-This macro allows defining keymap variables more conveniently.
-
-** 'defvar-keymap' can specify 'repeat-mode' behavior for the keymap.
-Use ':repeat t' to have all bindings be repeatable or for more
-advanced usage:
-
- ':repeat (:enter (commands ...) :exit (commands ...))'
-
----
-** 'kbd' can now be used in built-in, preloaded libraries.
-It no longer depends on edmacro.el and cl-lib.el.
-
-+++
-** New function 'image-at-point-p'.
-This function returns t if point is on a valid image, and nil
-otherwise.
-
-+++
-** New function 'buffer-text-pixel-size'.
-This is similar to 'window-text-pixel-size', but can be used when the
-buffer isn't displayed.
-
-+++
-** New function 'string-pixel-width'.
-This returns the width of a string in pixels. This can be useful when
-dealing with variable pitch fonts and glyphs that have widths that
-aren't integer multiples of the default font.
-
-+++
-** New function 'string-glyph-split'.
-This function splits a string into a list of strings representing
-separate glyphs. This takes into account combining characters and
-grapheme clusters, by treating each sequence of characters composed on
-display as a single unit.
-
----
-** 'lookup-key' is more permissive when searching for extended menu items.
-In Emacs 28.1, the behavior of 'lookup-key' was changed: when looking
-for a menu item '[menu-bar Foo-Bar]', first try to find an exact
-match, then look for the lowercased '[menu-bar foo-bar]'.
-
-This has been extended, so that when looking for a menu item with a
-symbol containing spaces, as in '[menu-bar Foo\ Bar]', first look for
-an exact match, then the lowercased '[menu-bar foo\ bar]' and finally
-'[menu-bar foo-bar]'. This further improves backwards-compatibility
-when converting menus to use 'easy-menu-define'.
-
-** xwidgets
-
-+++
-*** The function 'make-xwidget' now accepts an optional RELATED argument.
-This argument is used as another widget for the newly created WebKit
-widget to share settings and subprocesses with. It must be another
-WebKit widget.
-
-+++
-*** New function 'xwidget-perform-lispy-event'.
-This function allows you to send events to xwidgets. Usually, some
-equivalent of the event will be sent, but there is no guarantee of
-what the widget will actually receive.
-
-On GTK+, only key and function key events are implemented.
-
-+++
-*** New function 'xwidget-webkit-load-html'.
-This function is used to load HTML text into WebKit xwidgets
-directly, in contrast to creating a temporary file to hold the
-markup, and passing the URI of the file as an argument to
-'xwidget-webkit-goto-uri'.
-
-+++
-*** New functions for performing searches on WebKit xwidgets.
-Some new functions, such as 'xwidget-webkit-search', have been added
-for performing searches on WebKit xwidgets.
-
-+++
-*** New function 'xwidget-webkit-back-forward-list'.
-This function returns the history of page-loads in a WebKit xwidget.
-
-+++
-*** New function 'xwidget-webkit-estimated-load-progress'.
-This function returns the estimated progress of page loading in a
-WebKit xwidget.
-
-+++
-*** New function 'xwidget-webkit-stop-loading'.
-This function terminates all data transfer during page loads in a
-WebKit xwidget.
-
-+++
-*** 'load-changed' xwidget events are now more detailed.
-In particular, they can now have different arguments based on the
-state of the WebKit widget. 'load-finished' is sent when a load has
-completed, 'load-started' when a load first starts, 'load-redirected'
-after a redirect, and 'load-committed' when the WebKit widget first
-commits to the load.
-
-+++
-*** New event type 'xwidget-display-event'.
-These events are sent whenever an xwidget requests that Emacs display
-another xwidget. The only arguments to this event are the xwidget
-that should be displayed, and the xwidget that asked to display it.
-
-+++
-*** New function 'xwidget-webkit-set-cookie-storage-file'.
-This function is used to control where and if an xwidget stores
-cookies set by web pages on disk.
-
----
-** New variable 'help-buffer-under-preparation'.
-This variable is bound to t during the preparation of a "*Help*" buffer.
-
-+++
-** Timestamps like '(1 . 1000)' now work without warnings being generated.
-For example, '(time-add nil '(1 . 1000))' no longer warns that the
-'(1 . 1000)' acts like '(1000 . 1000000)'. This warning, which was a
-temporary transition aid for Emacs 27, has served its purpose.
-
-+++
-** 'encode-time' now also accepts a 6-element list with just time and date.
-'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR))' is now short for
-'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR nil -1 nil))'.
-
-+++
-** 'date-to-time' now accepts arguments that lacks month, day, or time.
-The function now assumes the earliest possible values if its argument
-lacks month, day, or time. For example, (date-to-time "2021-12-04")
-now assumes a time of 00:00 instead of signaling an error.
-
-+++
-** 'format-seconds' now allows suppressing zero-value trailing elements.
-The new "%x" non-printing control character will suppress zero-value
-elements that appear after "%x".
-
-+++
-** New events for taking advantage of touchscreen devices.
-The events 'touchscreen-begin, 'touchscreen-update', and
-'touchscreen-end' have been added to take better advantage of
-touch-capable display panels.
-
-+++
-** New error symbol 'permission-denied'.
-This is a subcategory of 'file-error', and is signaled when some file
-operation fails because the OS doesn't allow Emacs to access a file or
-a directory.
-
-+++
-** The ':underline' face attribute now accepts a new property.
-The property ':position' now specifies the position of the underline
-when used as part of a property list specification for the
-':underline' attribute.
-
-+++
-** 'defalias' records a more precise history of definitions.
-This is recorded in the 'function-history' symbol property.
-
----
-** New hook 'save-place-after-find-file-hook'.
-This is called at the end of 'save-place-find-file-hook'.
-
----
-** 'indian-tml-base-table' no longer translates digits.
-Use 'indian-tml-base-digits-table' if you want digits translation.
-
----
-** 'indian-tml-itrans-v5-hash' no longer translates digits.
-Use 'indian-tml-itrans-digits-v5-hash' if you want digits
-translation.
-
-+++
-** 'shell-quote-argument' has a new optional parameter POSIX.
-This is useful when quoting shell arguments for a remote shell
-invocation. Such shells are POSIX conformant by default.
-
-+++
-** 'make-process' can set connection type independently for input and output.
-When calling 'make-process', communication via pty can be enabled
-selectively for just input or output by passing a cons cell for
-':connection-type', e.g. '(pipe . pty)'. When examining a process
-later, you can determine whether a particular stream for a process
-uses a pty by passing one of 'stdin', 'stdout', or 'stderr' as the
-second argument to 'process-tty-name'.
-
-+++
-** 'signal-process' now consults the list 'signal-process-functions'.
-This is to determine which function has to be called in order to
-deliver the signal. This allows Tramp to send the signal to remote
-asynchronous processes. The hitherto existing implementation has been
-moved to 'internal-default-signal-process'.
-
-+++
-** Some system information functions honor remote systems now.
-'list-system-processes' returns remote process IDs.
-'memory-info' returns memory information of remote systems.
-'process-attributes' expects a remote process ID.
-This happens only when the current buffer's 'default-directory' is
-remote. In order to preserve the old behavior, bind
-'default-directory' to a local directory, like
-
- (let ((default-directory temporary-file-directory))
- (list-system-processes))
-
-+++
-** New functions 'take' and 'ntake'.
-'(take N LIST)' returns the first N elements of LIST; 'ntake' does
-the same but works by modifying LIST destructively.
-
----
-** 'string-split' is now an alias for 'split-string'.
-
-+++
-** 'format-spec' now accepts functions in the replacement.
-The function is called only when used in the format string. This is
-useful to avoid side-effects such as prompting, when the value is not
-actually being used for anything.
-
-+++
-** The variable 'max-specpdl-size' has been made obsolete.
-Now 'max-lisp-eval-depth' alone is used for limiting Lisp recursion
-and stack usage. 'max-specpdl-size' is still present as a plain
-variable for compatibility but its limiting powers have been taken away.
-
-** New function 'external-completion-table'.
-This function returns a completion table designed to ease
-communication between Emacs's completion facilities and external tools
-offering completion services, particularly tools whose full working
-set is too big to transfer to Emacs every time a completion is
-needed. The table uses new 'external' completion style exclusively
-and cannot work with regular styles such as 'basic' or 'flex'.
-
-+++
-** Magic file name handlers for 'make-directory-internal' are no longer needed.
-Instead, Emacs uses the already-existing 'make-directory' handlers.
-
-+++
-** '(make-directory DIR t)' returns non-nil if DIR already exists.
-This can let a caller know whether it created DIR. Formerly,
-'make-directory's return value was unspecified.
-* Changes in Emacs 29.1 on Non-Free Operating Systems
-
-** MS-Windows
-
----
-*** Emacs now supports double-buffering on MS-Windows to reduce display flicker.
-(This was supported on Free systems since Emacs 26.1.)
-
-To disable double-buffering (e.g., if it causes display problems), set
-the frame parameter 'inhibit-double-buffering' to a non-nil value.
-You can do that either by adding
-
- '(inhibit-double-buffering . t)
-
-to 'default-frame-alist', or by modifying the frame parameters of the
-selected frame by evaluating
-
- (modify-frame-parameters nil '((inhibit-double-buffering . t)))
-
-+++
-*** Emacs now supports system dark mode.
-On Windows 10 (version 1809 and higher) and Windows 11, Emacs will now
-follow the system's dark mode: GUI frames use the appropriate light or
-dark title bar and scroll bars, based on the user's Windows-wide color
-settings.
-
----
-*** Emacs now uses native image APIs to display some image formats.
-On Windows 2000 and later, Emacs now defaults to using the native
-image APIs for displaying the BMP, GIF, JPEG, PNG, and TIFF images.
-This means Emacs on MS-Windows needs no longer use external image
-support libraries to display those images. Other image types -- XPM,
-SVG, and WEBP -- still need support libraries for Emacs to be able to
-display them.
-
-The use of native image APIs is controlled by the variable
-'w32-use-native-image-API', whose value now defaults to t on systems
-where those APIs are available.
-
-+++
-*** Emacs now supports display of BMP images using native image APIs.
-When 'w32-use-native-image-API' is non-nil, Emacs on MS-Windows now
-has built-in support for displaying BMP images.
-
----
-*** GUI Yes/No dialogs now include a "Cancel" button.
-The "Cancel" button is in addition to "Yes" and "No", and is intended
-to allow users to quit the dialog, as an equivalent of C-g when Emacs
-asks a yes/no question via the echo area. This is controlled by the
-new variable 'w32-yes-no-dialog-show-cancel', by default t. Set it to
-nil to get back the old behavior of showing a modal dialog with only
-two buttons: "Yes" and "No".
-
-** Cygwin
-
----
-*** 'process-attributes' is now implemented.
+* Changes in Emacs 30.1 on Non-Free Operating Systems
----------------------------------------------------------------------
diff --git a/etc/NEWS.29 b/etc/NEWS.29
new file mode 100644
index 00000000000..38b7865626d
--- /dev/null
+++ b/etc/NEWS.29
@@ -0,0 +1,4745 @@
+GNU Emacs NEWS -- history of user-visible changes.
+
+Copyright (C) 2021-2022 Free Software Foundation, Inc.
+See the end of the file for license conditions.
+
+Please send Emacs bug reports to 'bug-gnu-emacs@gnu.org'.
+If possible, use 'M-x report-emacs-bug'.
+
+This file is about changes in Emacs version 29.
+
+See file HISTORY for a list of GNU Emacs versions and release dates.
+See files NEWS.28, NEWS.27, ..., NEWS.18, and NEWS.1-17 for changes
+in older Emacs versions.
+
+You can narrow news to a specific version by calling 'view-emacs-news'
+with a prefix argument or by typing 'C-u C-h C-n'.
+
+Temporary note:
++++ indicates that all relevant manuals in doc/ have been updated.
+--- means no change in the manuals is needed.
+When you add a new item, use the appropriate mark if you are sure it
+applies, and please also update docstrings as needed.
+
+
+* Installation Changes in Emacs 29.1
+
+---
+** Ahead-of-time native compilation can now be specified via configure.
+Use '--with-native-compilation=aot' to specify that all the Lisp files
+in the Emacs tree should be natively compiled ahead of time. (This is
+slow on most machines.)
+
++++
+** Emacs can be built with the tree-sitter parsing library.
+This library, together with grammar libraries, provides incremental
+parsing capabilities for several popular programming languages and
+other formatted files. Emacs built with this library offers major
+modes, described elsewhere in this file, that are based on the
+tree-sitter's parsers. If you have the tree-sitter library
+installed, the configure script will automatically include it in the
+build; use '--without-tree-sitter' at configure time to disable that.
+
+Emacs modes based on the tree-sitter library require an additional
+grammar library for each mode. These grammar libraries provide the
+tree-sitter library with language-specific lexical analysis and
+parsing capabilities, and are developed separately from the
+tree-sitter library itself. If you don't have a grammar library
+required by some Emacs major mode, and your distro doesn't provide it
+as an installable package, you can compile and install such a library
+yourself. Many libraries can be downloaded from the tree-sitter site:
+
+ https://github.com/tree-sitter
+
+To compile such a library, compile the files "scanner.c" and "parser.c"
+(sometimes named "scanner.cc" and "parser.cc") in the "src" subdirectory
+of the library's source tree using the C or C++ compiler, then link
+these two files into a shared library named "libtree-sitter-LANG.so",
+where LANG is the name of the language supported by the grammar as it
+is expected by the Emacs major mode (for example, "c" for 'c-ts-mode',
+"cpp" for 'c++-ts-mode', "python" for 'python-ts-mode', etc.). Then place
+the shared library you've built in the same directory where you keep
+the other shared libraries used by Emacs, or in the "tree-sitter"
+subdirectory of your 'user-emacs-directory', or in a directory
+mentioned in the variable 'treesit-extra-load-path'.
+
+You only need to install language grammar libraries required by the
+Emacs modes you will use, as Emacs loads these libraries only when the
+corresponding mode is turned on in some buffer for the first time in
+an Emacs session.
+
++++
+** Emacs can be built with built-in support for accessing SQLite databases.
+This uses the popular sqlite3 library, and can be disabled by using
+the '--without-sqlite3' option to the 'configure' script.
+
++++
+** Support for the WebP image format.
+This support is built by default when the libwebp library is
+available, and includes support for animated WebP images. To disable
+WebP support, use the '--without-webp' configure flag. Image
+specifiers can now use ':type webp'.
+
++++
+** Emacs has been ported to the Haiku operating system.
+The configuration process should automatically detect and build for
+Haiku. There is also an optional window-system port to Haiku, which
+can be enabled by configuring Emacs with the option '--with-be-app',
+which will require the Haiku Application Kit development headers and a
+C++ compiler to be present on your system. If Emacs is not built with
+the option '--with-be-app', the resulting Emacs will only run in
+text-mode terminals.
+
+To enable Cairo support, ensure that the Cairo and FreeType
+development files are present on your system, and configure Emacs with
+'--with-be-cairo'.
+
+Unlike X, there is no compile-time option to enable or disable
+double-buffering; it is always enabled. To disable it, change the
+frame parameter 'inhibit-double-buffering' instead.
+
+---
+** Emacs now installs the ".pdmp" file using a unique fingerprint in the name.
+The file is typically installed using a file name akin to
+"...dir/libexec/emacs/29.1/x86_64-pc-linux-gnu/emacs-<fingerprint>.pdmp".
+If a constant file name is required, the file can be renamed to
+"emacs.pdmp", and Emacs will find it during startup anyway.
+
+---
+** Emacs on X now uses XInput 2 for input events.
+If your X server has support and you have the XInput 2 development
+headers installed, Emacs will use the X Input Extension for handling
+input. If this causes problems, you can configure Emacs with the
+option '--without-xinput2' to disable this support.
+
+'(featurep 'xinput2)' can be used to test for the presence of XInput 2
+support from Lisp programs.
+
++++
+** Emacs now supports being built with pure GTK.
+To use this option, make sure the GTK 3 (version 3.22.23 or later) and
+Cairo development files are installed, and configure Emacs with the
+option '--with-pgtk'. Unlike the default X and GTK build, the
+resulting Emacs binary will work on any underlying window system
+supported by GDK, such as Wayland and Broadway. We recommend that you
+use this configuration only if you are running a window system other
+than X that's supported by GDK. Running this configuration on X is
+known to have problems, such as undesirable frame positioning and
+various issues with keyboard input of sequences such as 'C-;' and
+'C-S-u'.
+
+---
+** Emacs no longer reduces the size of the Japanese dictionary.
+Building Emacs includes generation of a Japanese dictionary, which is
+used by Japanese input methods. Previously, the build included a step
+of reducing the size of this dictionary's vocabulary. This vocabulary
+reduction is now optional, by default off. If you need the Emacs
+build to include the vocabulary reduction, configure Emacs with the
+option '--with-small-ja-dic'. In an Emacs source tree already
+configured without that option, you can force the vocabulary reduction
+by saying
+
+ make -C leim generate-ja-dic JA_DIC_NO_REDUCTION_OPTION=''
+
+after deleting "lisp/leim/ja-dic/ja-dic.el".
+
+---
+** The docstrings of preloaded files are not in "etc/DOC" any more.
+Instead, they're fetched as needed from the corresponding ".elc"
+files, as was already the case for all the non-preloaded files.
+
+
+* Startup Changes in Emacs 29.1
+
++++
+** '--batch' and '--script' now adjust the garbage collection levels.
+These switches now set 'gc-cons-percentage' to 1.0 (up from the
+default of 0.1). This means that batch processes will typically use
+more memory than before, but use less time doing garbage collection.
+Batch jobs that are supposed to run for a long time should adjust the
+limit back down again.
+
++++
+** Emacs can now be used more easily in an executable script.
+If you start an executable script with
+
+ #!/usr/bin/emacs -x
+
+Emacs will start without reading any init files (like with '--quick'),
+and then execute the rest of the script file as Emacs Lisp. When it
+reaches the end of the script, Emacs will exit with an exit code from
+the value of the final form.
+
++++
+** Emacs now supports setting 'user-emacs-directory' via '--init-directory'.
+Use the '--init-directory' command-line option to set
+'user-emacs-directory'.
+
++++
+** Emacs now has a '--fingerprint' option.
+This will output a string identifying the current Emacs build, and exit.
+
++++
+** New hook 'after-pdump-load-hook'.
+This is run at the end of the Emacs startup process, and is meant to
+be used to reinitialize data structures that would normally be done at
+load time.
+
+** Native Compilation
+
++++
+*** New variable 'inhibit-automatic-native-compilation'.
+If set, Emacs will inhibit native compilation (and won't write
+anything to the eln cache automatically). The variable is initialized
+during Emacs startup from the environment variable
+'EMACS_INHIBIT_AUTOMATIC_NATIVE_COMPILATION'.
+
+---
+*** New command 'native-compile-prune-cache'.
+This command deletes old subdirectories of the eln cache (but not the
+ones for the current Emacs version). Note that subdirectories of the
+system directory where the "*.eln" files are installed (usually, the
+last entry in 'native-comp-eln-load-path') are not deleted.
+
+---
+*** New function 'startup-redirect-eln-cache'.
+This function can be called in your init files to change the
+user-specific directory where Emacs stores the "*.eln" files produced
+by native compilation of Lisp packages Emacs loads. The default
+eln cache directory is unchanged: it is the "eln-cache" subdirectory
+of 'user-emacs-directory'.
+
+
+* Incompatible changes in Emacs 29.1
+
++++
+** The image commands have changed key bindings.
+In previous Emacs versions, images have had the '+', '-' and 'r' keys
+bound when point is over an image. In Emacs 29.1, additional commands
+were added, and this made it more likely that users would trigger the
+image commands by mistake. To avoid this, all image commands have
+moved to the 'i' keymap, so '+' is now 'i +', '-' is now 'i -', and
+'r' is now 'i r'. In addition, these commands are now repeating, so
+you can rotate an image twice by saying 'i r r', for instance.
+
++++
+** Emacs now picks the correct coding-system for X input methods.
+Previously, Emacs would use 'locale-coding-system' for input
+methods, which could in some circumstances be incorrect, especially
+when the input method chose to fall back to some other coding system.
+
+Emacs now automatically detects the coding-system used by input
+methods, and uses that to decode input in preference to the value of
+'locale-coding-system'. This unfortunately means that users who have
+changed the coding system used to decode X keyboard input must adjust
+their customizations to 'locale-coding-system' to the variable
+'x-input-coding-system' instead.
+
++++
+** Bookmarks no longer include context for encrypted files.
+If you're visiting an encrypted file, setting a bookmark no longer
+includes excerpts from that buffer in the bookmarks file. This is
+implemented by the new hook 'bookmark-inhibit-context-functions',
+where packages can register a function which returns non-nil for file
+names to be excluded from adding such excerpts.
+
+---
+** 'show-paren-mode' is now disabled in 'special-mode' buffers.
+In Emacs versions previous to Emacs 28.1, 'show-paren-mode' defaulted
+off. In Emacs 28.1, the mode was switched on in all buffers. In
+Emacs 29.1, this was changed to be switched on in all editing-related
+buffers, but not in buffers that inherit from 'special-mode'. To go
+back to how things worked in Emacs 28.1, put the following in your
+init file:
+
+ (setopt show-paren-predicate t)
+
++++
+** Explicitly-set read-only state is preserved when reverting a buffer.
+If you use the 'C-x C-q' command to change the read-only state of the
+buffer and then revert it, Emacs would previously use the file
+permission bits to determine whether the buffer should be read-only
+after reverting the buffer. Emacs now remembers the decision made in
+'C-x C-q'.
+
+---
+** The Gtk selection face is no longer used for the region.
+The combination of a Gtk-controlled background and a foreground color
+controlled by the internal Emacs machinery led to low-contrast faces
+in common default setups. Emacs now uses the same 'region' face on
+Gtk and non-Gtk setups.
+
+---
+** 'C-h f' and 'C-h x' may now require confirmation when you press 'RET'.
+If the text in the minibuffer cannot be completed to a single function
+or command, typing 'RET' will not automatically complete to the shortest
+candidate, but will instead ask for confirmation. Typing 'TAB' will
+complete as much as possible, and another 'TAB' will show all the
+possible completions. This allows you to insist on the functions name
+even if Help doesn't appear to know about it, by confirming with a
+second 'RET'.
+
+** Dired
+
+---
+*** 'w' ('dired-copy-filename-as-kill') has changed behavior.
+If there are several files marked, file names containing space and
+quote characters will be quoted "like this".
+
+---
+*** The 'd' command now more consistently skips dot files.
+In previous Emacs versions, commands like 'C-u 10 d' would put the "D"
+mark on the next ten files, no matter whether they were dot files
+(i.e., "." and "..") or not, while marking the next ten lines with the
+mouse (in 'transient-mark-mode') and then hitting 'd' would skip dot
+files. These now work equivalently.
+
++++
+** Warning about "eager macro-expansion failure" is now an error.
+
+---
+** Previously, the X "reverseVideo" value at startup was heeded for all frames.
+This meant that if you had a "reverseVideo" resource on the initial
+display, and then opened up a new frame on a display without any
+explicit "reverseVideo" setting, it would get heeded there, too. (This
+included terminal frames.) In Emacs 29, the "reverseVideo" X resource
+is handled like all the other X resources, and set on a per-frame basis.
+
++++
+** 'E' in 'query-replace' now edits the replacement with exact case.
+Previously, this command did the same as 'e'.
+
+---
+** '/ a' in "*Packages*" buffer now limits by archive name(s) instead of regexp.
+
++++
+** Setting the goal columns now also affects '<prior>' and '<next>'.
+Previously, 'C-x C-n' only affected 'next-line' and 'previous-line',
+but it now also affects 'scroll-up-command' and 'scroll-down-command'.
+
+---
+** Isearch in "*Help*" and "*info*" now char-folds quote characters by default.
+This means that you can say 'C-s `foo' (GRAVE ACCENT) if the buffer
+contains "‘foo" (LEFT SINGLE QUOTATION MARK) and the like. These
+quotation characters look somewhat similar in some fonts. To switch
+this off, disable the new 'isearch-fold-quotes-mode' minor mode.
+
+---
+** Sorting commands no longer necessarily change modification status.
+In earlier Emacs versions, commands like 'M-x sort-lines' would always
+change buffer modification status to "modified", whether they changed
+something in the buffer or not. This has been changed: the buffer is
+marked as modified only if the sorting ended up actually changing the
+contents of the buffer.
+
+---
+** 'string-lines' handles trailing newlines differently.
+It no longer returns an empty final string if the string ends with a
+newline.
+
+---
+** 'TAB' and '<backtab>' are now bound in 'button-map'.
+This means that if point is on a button, 'TAB' will take you to the
+next button, even if the mode has bound it to something else. This
+also means that 'TAB' on a button in an 'outline-minor-mode' heading
+will move point instead of collapsing the outline.
+
+---
+** 'Info-default-directory-list' is no longer populated at Emacs startup.
+If you have code in your init file that removes directories from
+'Info-default-directory-list', this will no longer work.
+
+---
+** 'C-k' no longer deletes files in 'ido-mode'.
+To get the previous action back, put something like the following in
+your Init file:
+
+ (require 'ido)
+ (keymap-set ido-file-completion-map "C-k" #'ido-delete-file-at-head)
+
+---
+** New user option 'term-clear-full-screen-programs'.
+By default, term.el will now work like most terminals when displaying
+full-screen programs: When they exit, the output is cleared, leaving
+what was displayed in the window before the programs started. Set
+this user option to nil to revert back to the old behavior.
+
+---
+** Support for old EIEIO functions is not autoloaded any more.
+You need an explicit '(require 'eieio-compat)' to use 'defmethod'
+and 'defgeneric' (which have been made obsolete in Emacs 25.1 with
+'cl-defmethod' and 'cl-defgeneric').
+Similarly you might need to '(require 'eieio-compat)' before loading
+files that were compiled with an old EIEIO (Emacs<25).
+
+---
+** 'C-x 8 .' has been moved to 'C-x 8 . .'.
+This is to open up the 'C-x 8 .' map to bind further characters there.
+
+---
+** 'C-x 8 =' moved to 'C-x 8 = ='.
+You can now use 'C-x 8 =' to insert several characters with macron;
+for example, 'C-x 8 = a' will insert U+0101 LATIN SMALL LETTER A WITH
+MACRON. To insert a lone macron, type 'C-x 8 = =' instead of the
+previous 'C-x ='.
+
+** Eshell
+
+*** Eshell's PATH is now derived from 'exec-path'.
+For consistency with remote connections, Eshell now uses 'exec-path'
+to determine the execution path on the local system, instead of using
+the PATH environment variable directly.
+
+---
+*** 'source' and '.' no longer accept the '--help' option.
+This is for compatibility with the shell versions of these commands,
+which don't handle options like '--help' in any special way.
+
++++
+*** String delimiters in argument predicates/modifiers are more restricted.
+Previously, some argument predicates/modifiers allowed arbitrary
+characters as string delimiters. To provide more unified behavior
+across all predicates/modifiers, the list of allowed delimiters has
+been restricted to "...", '...', /.../, |...|, (...), [...], <...>,
+and {...}. See the "(eshell) Argument Predication and Modification"
+node in the Eshell manual for more details.
+
++++
+*** Eshell pipelines now only pipe stdout by default.
+To pipe both stdout and stderr, use the '|&' operator instead of '|'.
+
+---
+** The 'delete-forward-char' command now deletes by grapheme clusters.
+This command is by default bound to the <Delete> function key
+(a.k.a. <deletechar>). When invoked without a prefix argument or with
+a positive prefix numeric argument, the command will now delete
+complete grapheme clusters produced by character composition. For
+example, if point is before an Emoji sequence, pressing <Delete> will
+delete the entire sequence, not just a single character at its
+beginning.
+
++++
+** 'load-history' does not treat autoloads specially any more.
+An autoload definition appears just as a '(defun . NAME)' and the
+'(t . NAME)' entries are not generated any more.
+
+---
+** The Tamil input methods no longer insert Tamil digits.
+The input methods 'tamil-itrans' and 'tamil-inscript' no longer insert
+the Tamil digits, as those digit characters are not used nowadays by
+speakers of the Tamil language. To get back the previous behavior,
+use the new 'tamil-itrans-digits' and 'tamil-inscript-digits' input
+methods instead.
+
++++
+** New variable 'current-time-list' governing default timestamp form.
+Functions like 'current-time' now yield '(TICKS . HZ)' timestamps if
+this new variable is nil. The variable defaults to t, which means
+these functions default to timestamps of the forms '(HI LO US PS)',
+'(HI LO US)' or '(HI LO)', which are less regular and less efficient.
+This is part of a long-planned change first documented in Emacs 27.
+Developers are encouraged to test timestamp-related code with this
+variable set to nil, as it will default to nil in a future Emacs
+version and will be removed some time after that.
+
++++
+** Functions that recreate the "*scratch*" buffer now also initialize it.
+When functions like 'other-buffer' and 'server-execute' recreate
+"*scratch*", they now also insert 'initial-scratch-message' and set
+the major mode according to 'initial-major-mode', like at Emacs
+startup. Previously, these functions ignored
+'initial-scratch-message' and left "*scratch*" in 'fundamental-mode'.
+
+---
+** Naming of Image-Dired thumbnail files has changed.
+Names of thumbnail files generated when 'image-dired-thumbnail-storage'
+is 'image-dired' now always end in ".jpg". This fixes various issues
+on different platforms, but means that thumbnails generated in Emacs 28
+will not be used in Emacs 29, and vice-versa. If disk space is an
+issue, consider deleting the 'image-dired-dir' directory (usually
+"~/.emacs.d/image-dired/") after upgrading to Emacs 29.
+
+---
+** The 'rlogin' method in the URL library is now obsolete.
+Emacs will now display a warning if you request a URL like
+"rlogin://foo@example.org".
+
+---
+** Setting 'url-gateway-method' to 'rlogin' is now obsolete.
+Emacs will now display a warning when setting it to that value.
+The user options 'url-gateway-rlogin-host',
+'url-gateway-rlogin-parameters', and 'url-gateway-rlogin-user-name'
+are also obsolete.
+
+---
+** The user function 'url-irc-function' now takes a SCHEME argument.
+The user option 'url-irc-function' is now called with a sixth argument
+corresponding to the scheme portion of the target URL. For example,
+this would be "ircs" for a URL like "ircs://irc.libera.chat".
+
+---
+** The linum.el library is now obsolete.
+We recommend using either the built-in 'display-line-numbers-mode', or
+the 'nlinum' package from GNU ELPA instead. The former has better
+performance, but the latter is closer to a drop-in replacement.
+
+1. To use 'display-line-numbers-mode', add something like this to your
+ Init file:
+
+ (global-display-line-numbers-mode 1)
+ ;; Alternatively, to use it only in programming modes:
+ (add-hook 'prog-mode-hook #'display-line-numbers-mode)
+
+2. To use 'nlinum', add this to your Init file:
+
+ (package-install 'nlinum)
+ (global-nlinum-mode 1)
+ ;; Alternatively, to use it only in programming modes:
+ (add-hook 'prog-mode-hook #'nlinum-mode)
+
+3. To continue using the obsolete package 'linum', add this line to
+ your Init file, in addition to any existing customizations:
+
+ (require 'linum)
+
+---
+** The thumbs.el library is now obsolete.
+We recommend using 'M-x image-dired' instead.
+
+---
+** The autoarg.el library is now marked obsolete.
+This library provides the 'autoarg-mode' and 'autoarg-kp-mode' minor
+modes to emulate the behavior of the historical editor Twenex Emacs.
+We believe it is no longer useful.
+
+---
+** The quickurl.el library is now obsolete.
+Use 'abbrev', 'skeleton' or 'tempo' instead.
+
+---
+** The rlogin.el library, and the 'rsh' command are now obsolete.
+Use something like 'M-x shell RET ssh <host> RET' instead.
+
+---
+** The url-about.el library is now obsolete.
+
+---
+** The autoload.el library is now obsolete.
+It is superseded by the new loaddefs-gen.el library.
+
+---
+** The netrc.el library is now obsolete.
+Use the 'auth-source-netrc-parse-all' function in auth-source.el
+instead.
+
+---
+** The url-dired.el library is now obsolete.
+
+---
+** The fast-lock.el and lazy-lock.el libraries have been removed.
+They have been obsolete since Emacs 22.1.
+
+The variable 'font-lock-support-mode' is occasionally useful for
+debugging purposes. It is now a regular variable (instead of a user
+option) and can be set to nil to disable Just-in-time Lock mode.
+
+
+* Changes in Emacs 29.1
+
++++
+** New user option 'major-mode-remap-alist' to specify favorite major modes.
+This user option lets you remap the default modes (e.g. 'perl-mode' or
+'latex-mode') to your favorite ones (e.g. 'cperl-mode' or
+'LaTeX-mode') without having to use 'defalias', which can have
+undesirable side effects.
+This applies to all modes specified via 'auto-mode-alist', file-local
+variables, etc.
+
+---
+** Emacs now supports Unicode Standard version 15.0.
+
+---
+** New user option 'electric-quote-replace-consecutive'.
+
+---
+** Emacs is now capable of editing files with very long lines.
+The display of long lines has been optimized, and Emacs should no
+longer choke when a buffer on display contains long lines. The
+variable 'long-line-threshold' controls whether and when these display
+optimizations are in effect.
+
+A companion variable 'large-hscroll-threshold' controls when another
+set of display optimizations are in effect, which are aimed
+specifically at speeding up display of long lines that are truncated
+on display.
+
+If you still experience slowdowns while editing files with long lines,
+this may be due to line truncation, or to one of the enabled minor
+modes, or to the current major mode. Try turning off line truncation
+with 'C-x x t', or try disabling all known slow minor modes with
+'M-x so-long-minor-mode', or try disabling both known slow minor modes
+and the major mode with 'M-x so-long-mode', or visit the file with
+'M-x find-file-literally' instead of the usual 'C-x C-f'.
+
+Note that the display optimizations in these cases may cause the
+buffer to be occasionally mis-fontified.
+
+The new function 'long-line-optimizations-p' returns non-nil when
+these optimizations are in effect in the current buffer.
+
++++
+** New command to change the font size globally.
+To increase the font size, type 'C-x C-M-+' or 'C-x C-M-='; to
+decrease it, type 'C-x C-M--'; to restore the font size, type 'C-x
+C-M-0'. The final key in these commands may be repeated without the
+leading 'C-x' and without the modifiers, e.g. 'C-x C-M-+ C-M-+ C-M-+'
+and 'C-x C-M-+ + +' increase the font size by three steps. When
+'mouse-wheel-mode' is enabled, 'C-M-wheel-up' and 'C-M-wheel-down' also
+increase and decrease the font size globally. Additionally, the
+user option 'global-text-scale-adjust-resizes-frames' controls whether
+the frames are resized when the font size is changed.
+
+---
+** New config variable 'syntax-wholeline-max' to reduce the cost of long lines.
+This variable is used by some operations (mostly syntax-propertization
+and font-locking) to treat lines longer than this variable as if they
+were made up of various smaller lines. This can help reduce the
+slowdowns seen in buffers made of a single long line, but can also
+cause misbehavior in the presence of such long lines (though most of
+that misbehavior should usually be limited to mis-highlighting). You
+can recover the previous behavior with:
+
+ (setq syntax-wholeline-max most-positive-fixnum)
+
+---
+** New bindings in 'find-function-setup-keys' for 'find-library'.
+When 'find-function-setup-keys' is enabled, 'C-x L' is now bound to
+'find-library', 'C-x 4 L' is now bound to 'find-library-other-window'
+and 'C-x 5 L' is now bound to 'find-library-other-frame'.
+
++++
+** New key binding after 'M-x' or 'M-X': 'M-X'.
+Emacs allows different completion predicates to be used with 'M-x'
+(i.e., 'execute-extended-command') via the
+'read-extended-command-predicate' user option. Emacs also has the
+'M-X' (note upper case X) command, which only displays commands
+especially relevant to the current buffer. Emacs now allows toggling
+between these modes while the user is inputting a command by hitting
+'M-X' while in the minibuffer.
+
+---
+** Interactively, 'kill-buffer' will now offer to save the buffer if unsaved.
+
+---
+** New commands 'duplicate-line' and 'duplicate-dwim'.
+'duplicate-line' duplicates the current line the specified number of times.
+'duplicate-dwim' duplicates the region if it is active. If not, it
+works like 'duplicate-line'. An active rectangular region is
+duplicated on its right-hand side.
+
+---
+** Files with the ".eld" extension are now visited in 'lisp-data-mode'.
+
++++
+** 'network-lookup-address-info' can now check numeric IP address validity.
+Specifying 'numeric' as the new optional 'hints' argument makes it
+check if the passed address is a valid IPv4/IPv6 address (without DNS
+traffic).
+
+ (network-lookup-address-info "127.1" 'ipv4 'numeric)
+ => ([127 0 0 1 0])
+
++++
+** New command 'find-sibling-file'.
+This command jumps to a file considered a "sibling file", which is
+determined according to the new user option 'find-sibling-rules'.
+
++++
+** New user option 'delete-selection-temporary-region'.
+When non-nil, 'delete-selection-mode' will only delete the temporary
+regions (usually set by mouse-dragging or shift-selection).
+
++++
+** New user option 'switch-to-prev-buffer-skip-regexp'.
+This should be a regexp or a list of regexps; buffers whose names
+match those regexps will be ignored by 'switch-to-prev-buffer' and
+'switch-to-next-buffer'.
+
++++
+** New command 'rename-visited-file'.
+This command renames the file visited by the current buffer by moving
+it to a new name or location, and also makes the buffer visit this new
+file.
+
+** Menus
+
+---
+*** The entries following the buffers in the "Buffers" menu can now be altered.
+Change the 'menu-bar-buffers-menu-command-entries' variable to alter
+the entries that follow the buffer list.
+
+---
+** 'delete-process' is now a command.
+When called interactively, it will kill the process running in the
+current buffer (if any). This can be useful if you have runaway
+output in the current buffer (from a process or a network connection),
+and want to stop it.
+
++++
+** New command 'restart-emacs'.
+This is like 'save-buffers-kill-emacs', but instead of just killing
+the current Emacs process at the end, it starts a new Emacs process
+(using the same command line arguments as the running Emacs process).
+'kill-emacs' and 'save-buffers-kill-emacs' have also gained new
+optional parameters to restart instead of just killing the current
+process.
+
+** Drag and Drop
+
++++
+*** New user option 'mouse-drag-mode-line-buffer'.
+If non-nil, dragging on the buffer name part of the mode-line will
+drag the buffer's associated file to other programs. This option is
+currently only available on X, Haiku and Nextstep (GNUstep or macOS).
+
++++
+*** New user option 'mouse-drag-and-drop-region-cross-program'.
+If non-nil, this option allows dragging text in the region from Emacs
+to another program.
+
+---
+*** New user option 'mouse-drag-and-drop-region-scroll-margin'.
+If non-nil, this option allows scrolling a window while dragging text
+around without a scroll wheel.
+
++++
+*** The value of 'mouse-drag-copy-region' can now be the symbol 'non-empty'.
+This prevents mouse drag gestures from putting empty strings onto the
+kill ring.
+
++++
+*** New user options 'dnd-indicate-insertion-point' and 'dnd-scroll-margin'.
+These options allow adjusting point and scrolling a window when
+dragging items from another program.
+
++++
+*** The X Direct Save (XDS) protocol is now supported.
+This means dropping an image or file link from programs such as
+Firefox will no longer create a temporary file in a random directory,
+instead asking you where to save the file first.
+
++++
+** New user option 'record-all-keys'.
+If non-nil, this option will force recording of all input keys,
+including those typed in response to passwords prompt (this was the
+previous behavior). The default is nil, which inhibits recording of
+passwords.
+
++++
+** New function 'command-query'.
+This function makes its argument command prompt the user for
+confirmation before executing.
+
++++
+** The 'disabled' property of a command's symbol can now be a list.
+The first element of the list should be the symbol 'query', which will
+cause the command disabled this way prompt the user with a y/n or a
+yes/no question before executing. The new function 'command-query' is
+a convenient method of making commands disabled in this way.
+
+---
+** 'count-words' will now report buffer totals if given a prefix.
+Without a prefix, it will only report the word count for the narrowed
+part of the buffer.
+
++++
+** 'count-words' will now report sentence count when used interactively.
+
++++
+** New user option 'set-message-functions'.
+It allows selecting more functions for 'set-message-function'
+in addition to the default function that handles messages
+in the active minibuffer. The most useful are 'inhibit-message'
+that allows specifying a list of messages to inhibit via
+'inhibit-message-regexps', and 'set-multi-message' that
+accumulates recent messages and displays them stacked
+in the echo area.
+
+---
+** New user option 'find-library-include-other-files'.
+If set to nil, commands like 'find-library' will only include library
+files in the completion candidates. The default is t, which preserves
+previous behavior, whereby non-library files could also be included.
+
++++
+** New command 'sqlite-mode-open-file' for examining an sqlite3 file.
+This uses the new 'sqlite-mode' which allows listing the tables in a
+DB file, and examining and modifying the columns and the contents of
+those tables.
+
+---
+** 'write-file' will now copy some file mode bits.
+If the current buffer is visiting a file that is executable, the
+'C-x C-w' command will now make the new file executable, too.
+
++++
+** New user option 'process-error-pause-time'.
+This determines how long to pause Emacs after a process
+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-misc-punctuation-face', 'font-lock-operator-face',
+'font-lock-property-face', and 'font-lock-punctuation-face'.
+
++++
+** New face 'variable-pitch-text'.
+This face is like 'variable-pitch' (from which it inherits), but is
+slightly larger, which should help with the visual size differences
+between the default, non-proportional font and proportional fonts when
+mixed.
+
++++
+** New face 'mode-line-active'.
+This inherits from the 'mode-line' face, but is the face actually used
+on the mode lines (along with 'mode-line-inactive').
+
++++
+** New face attribute pseudo-value 'reset'.
+This value stands for the value of the corresponding attribute of the
+'default' face. It can be used to reset attribute values produced by
+inheriting from other faces.
+
++++
+** New X resource: "borderThickness".
+This controls the thickness of the external borders of the menu bars
+and pop-up menus.
+
++++
+** New X resource: "inputStyle".
+This controls the style of the pre-edit and status areas of X input
+methods.
+
++++
+** New X resources: "highlightForeground" and "highlightBackground".
+Only in the Lucid build, this controls colors used for highlighted
+menu item widgets.
+
++++
+** On X, Emacs now tries to synchronize window resize with the window manager.
+This leads to less flicker and empty areas of a frame being displayed
+when a frame is being resized. Unfortunately, it does not work on
+some ancient buggy window managers, so if Emacs appears to freeze, but
+is still responsive to input, you can turn it off by setting the X
+resource "synchronizeResize" to "off".
+
++++
+** On X, Emacs can optionally synchronize display with the graphics hardware.
+When this is enabled by setting the X resource "synchronizeResize" to
+"extended", frame content "tearing" is drastically reduced. This is
+only supported on the Motif, Lucid, and no-toolkit builds, and
+requires an X compositing manager supporting the extended frame
+synchronization protocol (see
+https://fishsoup.net/misc/wm-spec-synchronization.html).
+
+This behavior can be toggled on and off via the frame parameter
+'use-frame-synchronization'.
+
++++
+** New frame parameter 'alpha-background' and X resource "alphaBackground".
+This controls the opacity of the text background when running on a
+composited display.
+
++++
+** New frame parameter 'shaded'.
+With window managers which support this, it controls whether or not a
+frame's contents will be hidden, leaving only the title bar on display.
+
+---
+** New user option 'x-gtk-use-native-input'.
+This controls whether or not GTK input methods are used by Emacs,
+instead of XIM input methods.
+
++++
+** New user option 'use-system-tooltips'.
+This controls whether to use the toolkit tooltips, or Emacs's own
+native implementation of tooltips as small frames. This option is
+only meaningful if Emacs was built with GTK+, Nextstep, or Haiku
+support, and defaults to t, which makes Emacs use the toolkit
+tooltips. The existing GTK-specific option
+'x-gtk-use-system-tooltips' is now an alias of this new option.
+
++++
+** Non-native tooltips are now supported on Nextstep.
+This means Emacs built with GNUstep or built on macOS is now able to
+display different faces and images inside tooltips when the
+'use-system-tooltips' user option is nil.
+
+---
+** New minor mode 'pixel-scroll-precision-mode'.
+When enabled, and if your mouse supports it, you can scroll the
+display up or down at pixel resolution, according to what your mouse
+wheel reports. Unlike 'pixel-scroll-mode', this mode scrolls the
+display pixel-by-pixel, as opposed to only animating line-by-line
+scrolls.
+
+** Terminal Emacs
+
+---
+*** Emacs will now use 24-bit colors on terminals that support "Tc" capability.
+This is in addition to previously-supported ways of discovering 24-bit
+color support: either via the "RGB" or "setf24" capabilities, or if
+the 'COLORTERM' environment variable is set to the value "truecolor".
+
+---
+*** Select active regions with xterm selection support.
+On terminals with xterm setSelection support, the active region may be
+saved to the X primary selection, following the
+'select-active-regions' variable. This support is enabled when
+'tty-select-active-regions' is non-nil.
+
+---
+*** New command to set up display of unsupported characters.
+The new command 'standard-display-by-replacement-char' produces Lisp
+code that sets up the 'standard-display-table' to use a replacement
+character for display of characters that the text-mode terminal
+doesn't support. This code is intended to be used in your init files.
+This feature is most useful with the Linux console and similar
+terminals, where Emacs has a reliable way of determining which
+characters have glyphs in the font loaded into the terminal's memory.
+
+---
+*** New functions to set terminal output buffer size.
+The new functions 'tty--set-output-buffer-size' and
+'tty--output-buffer-size' allow setting and retrieving the output
+buffer size of a terminal device. The default buffer size is and has
+always been BUFSIZ, which is defined in your system's stdio.h. When
+you set a buffer size with 'tty--set-output-buffer-size', this also
+prevents Emacs from explicitly flushing the tty output stream, except
+at the end of display update.
+
+** ERT
+
++++
+*** New ERT variables 'ert-batch-print-length' and 'ert-batch-print-level'.
+These variables will override 'print-length' and 'print-level' when
+printing Lisp values in ERT batch test results.
+
+---
+*** Redefining an ERT test in batch mode now signals an error.
+Executing 'ert-deftest' with the same name as an existing test causes
+the previous definition to be discarded, which was probably not
+intended when this occurs in batch mode. To remedy the error, rename
+tests so that they all have unique names.
+
++++
+*** ERT can generate JUnit test reports.
+When environment variable 'EMACS_TEST_JUNIT_REPORT' is set, ERT
+generates a JUnit test report under this file name. This is useful
+for Emacs integration into CI/CD test environments.
+
+---
+*** Unbound test symbols now signal an 'ert-test-unbound' error.
+This affects the 'ert-select-tests' function and its callers.
+
+** Emoji
+
++++
+*** Emacs now has several new methods for inserting Emoji.
+The Emoji commands are under the new 'C-x 8 e' prefix.
+
++++
+*** New command 'emoji-insert' (bound to 'C-x 8 e e' and 'C-x 8 e i').
+This command guides you through various Emoji categories and
+combinations in a graphical menu system.
+
++++
+*** New command 'emoji-search' (bound to 'C-x 8 e s').
+This command lets you search for Emoji based on names.
+
++++
+*** New command 'emoji-list' (bound to 'C-x 8 e l').
+This command lists all Emoji (categorized by themes) in a special
+buffer and lets you choose one of them.
+
+---
+*** New command 'emoji-recent' (bound to 'C-x 8 e r').
+This command lets you choose among the Emoji you have recently
+inserted.
+
++++
+*** New command 'emoji-describe' (bound to 'C-x 8 e d').
+This command will tell you the name of the Emoji at point. (It also
+works for non-Emoji characters.)
+
+---
+*** New commands 'emoji-zoom-increase' and 'emoji-zoom-decrease'.
+These are bound to 'C-x 8 e +' and 'C-x 8 e -', respectively. They
+can be used on any character, but are mainly useful for Emoji.
+
+---
+*** New input method 'emoji'.
+This allows you to enter Emoji using short strings, eg ':face_palm:'
+or ':scream:'.
+
+** Help
+
+---
+*** Variable values displayed by 'C-h v' in "*Help*" are now fontified.
+
++++
+*** New user option 'help-clean-buttons'.
+If non-nil, link buttons in "*Help*" buffers will have any surrounding
+quotes removed.
+
+---
+*** 'M-x apropos-variable' output now includes values of variables.
+
++++
+*** New docstring syntax to indicate that symbols shouldn't be links.
+When displaying docstrings in "*Help*" buffers, strings that are
+"`like-this'" are made into links (if they point to a bound
+function/variable). This can lead to false positives when talking
+about values that are symbols that happen to have the same names as
+functions/variables. To inhibit this buttonification, use the new
+"\\+`like-this'" syntax.
+
++++
+*** New user option 'help-window-keep-selected'.
+If non-nil, commands to show the info manual and the source will reuse
+the same window in which the "*Help*" buffer is shown.
+
+---
+*** Commands like 'C-h f' have changed how they describe menu bindings.
+For instance, previously a command might be described as having the
+following bindings:
+
+ It is bound to <open>, C-x C-f, <menu-bar> <file> <new-file>.
+
+This has been changed to:
+
+ It is bound to <open> and C-x C-f.
+ It can also be invoked from the menu: File → Visit New File...
+
++++
+*** The 'C-h .' command now accepts a prefix argument.
+'C-u C-h .' would previously inhibit displaying a warning message if
+there's no local help at point. This has been changed to call
+'button-describe'/'widget-describe' and display button/widget help
+instead.
+
+---
+*** New user option 'help-enable-variable-value-editing'.
+If enabled, 'e' on a value in "*Help*" will pop you to a new buffer
+where you can edit the value. This is not enabled by default, because
+it's easy to make an edit that yields an invalid result.
+
+---
+*** 'C-h b' uses outlining by default.
+Set 'describe-bindings-outline' to nil to get back the old behavior.
+
+---
+*** Jumping to function/variable source now saves mark before moving point.
+Jumping to source from a "*Help*" buffer moves point when the source
+buffer is already open. Now, the old point is pushed onto mark ring.
+
++++
+*** New key bindings in "*Help*" buffers: 'n' and 'p'.
+These will take you (respectively) to the next and previous "page".
+
+---
+*** 'describe-char' now also outputs the name of Emoji sequences.
+
++++
+*** New key binding in "*Help*" buffer: 'I'.
+This will take you to the Emacs Lisp manual entry for the item
+displayed, if any.
+
+---
+*** The 'C-h m' ('describe-mode') "*Help*" buffer has been reformatted.
+It now only includes local minor modes at the start, and the global
+minor modes are listed after the major mode.
+
++++
+*** The user option 'help-window-select' now affects apropos commands.
+The apropos commands will now select the apropos window if
+'help-window-select' is non-nil.
+
+---
+*** 'describe-keymap' now considers the symbol at point.
+If the symbol at point is a keymap, 'describe-keymap' suggests it as
+the default candidate.
+
+---
+*** New command 'help-quick' displays an overview of common commands.
+The command pops up a buffer at the bottom of the screen with a few
+helpful commands for various tasks. You can toggle the display using
+'C-h C-q'.
+
+** Emacs now comes with Org v9.6.
+See the file ORG-NEWS for user-visible changes in Org.
+
+** Outline Mode
+
++++
+*** Support for customizing the default visibility state of headings.
+Customize the user option 'outline-default-state' to define what
+headings will be visible initially, after Outline mode is turned on.
+When the value is a number, the user option 'outline-default-rules'
+determines the visibility of the subtree starting at the corresponding
+level. Values are provided to control showing a heading subtree
+depending on whether the heading matches a regexp, or on whether its
+subtree has long lines or is itself too long.
+
+** Outline Minor Mode
+
++++
+*** New user option 'outline-minor-mode-use-buttons'.
+If non-nil, Outline Minor Mode will use buttons to hide/show outlines
+in addition to the ellipsis. The default is nil, but in 'help-mode'
+it has the value 'insert' that inserts the buttons directly into the
+buffer, and you can use 'RET' to cycle outline visibility. When
+the value is 'in-margins', Outline Minor Mode uses the window margins
+for buttons that hide/show outlines.
+
+** Windows
+
++++
+*** New commands 'split-root-window-below' and 'split-root-window-right'.
+These commands split the root window in two, and are bound to 'C-x w 2'
+and 'C-x w 3', respectively. A number of other useful window-related
+commands are now available with key sequences that start with the
+'C-x w' prefix.
+
++++
+*** New user option 'display-buffer-avoid-small-windows'.
+If non-nil, this should be a window height in lines, a number.
+Windows smaller than this will be avoided by 'display-buffer', if
+possible.
+
++++
+*** New display action 'display-buffer-full-frame'.
+This action removes other windows from the frame when displaying a
+buffer on that frame.
+
++++
+*** 'display-buffer' now can set up the body size of the chosen window.
+For example, a 'display-buffer-alist' entry of
+
+ '(window-width . (body-columns . 40))'
+
+will make the body of the chosen window 40 columns wide. For the
+height use 'window-height' and 'body-lines', respectively.
+
+---
+*** You can customize on which window 'scroll-other-window' operates.
+This is controlled by the new 'other-window-scroll-default' user option.
+
+** Frames
+
++++
+*** Deleted frames can now be undeleted.
+The 16 most recently deleted frames can be undeleted with 'C-x 5 u' when
+'undelete-frame-mode' is enabled. Without a prefix argument, undelete
+the most recently deleted frame. With a numerical prefix argument
+between 1 and 16, where 1 is the most recently deleted frame, undelete
+the corresponding deleted frame.
+
+** Tab Bars and Tab Lines
+
+---
+*** New user option 'tab-bar-auto-width' to automatically determine tab width.
+This option is non-nil by default, which resizes tab-bar tabs so that
+their width is evenly distributed across the tab bar. A companion
+option 'tab-bar-auto-width-max' controls the maximum width of a tab
+before its name on display is truncated.
+
+---
+*** 'C-x t RET' creates a new tab when the provided tab name doesn't exist.
+It prompts for the name of a tab and switches to it, creating a new
+tab if no tab exists by that name.
+
+---
+*** New keymap 'tab-bar-history-mode-map'.
+By default, it contains 'C-c <left>' and 'C-c <right>' to browse
+the history of tab window configurations back and forward.
+
+---
+** Better detection of text suspiciously reordered on display.
+The function 'bidi-find-overridden-directionality' has been extended
+to detect reordering effects produced by embeddings and isolates
+(started by directional formatting control characters such as RLO and
+LRI). The new command 'highlight-confusing-reorderings' finds and
+highlights segments of buffer text whose reordering for display is
+suspicious and could be malicious.
+
+** Emacs server and client changes
+
++++
+*** New command-line option '-r'/'--reuse-frame' for emacsclient.
+With this command-line option, Emacs reuses an existing graphical client
+frame if one exists; otherwise it creates a new frame.
+
++++
+*** New command-line option '-w N'/'--timeout=N' for emacsclient.
+With this command-line option, emacsclient will exit if Emacs does not
+respond within N seconds. The default is to wait forever.
+
++++
+*** 'server-stop-automatically' can be used to automatically stop the server.
+The Emacs server will be automatically stopped when certain conditions
+are met. The conditions are given by the argument, which can be
+'empty', 'delete-frame' or 'kill-terminal'.
+
+** Rcirc
+
++++
+*** New command 'rcirc-when'.
+
++++
+*** New user option 'rcirc-cycle-completion-flag'.
+Rcirc will use the default 'completion-at-point' mechanism. The
+conventional IRC behavior of completing by cycling through the
+available options can be restored by enabling this option.
+
++++
+*** New user option 'rcirc-bridge-bot-alist'.
+If you are in a channel where a bot is responsible for bridging
+between networks, you can use this variable to make these messages
+appear more native. For example you might set the option to:
+
+ (setq rcirc-bridge-bot-alist '(("bridge" . "{\\(.+?\\)}[[:space:]]+")))
+
+for messages like
+
+ 09:47 <bridge> {john} I am not on IRC
+
+to be reformatted into
+
+ 09:47 <john> I am not on IRC
+
+---
+*** New formatting commands.
+Most IRC clients (including rcirc) support basic formatting using
+control codes. Under the 'C-c C-f' prefix a few commands have been
+added to insert these automatically. For example, if a region is
+active and 'C-c C-f C-b' is invoked, markup is inserted for the region
+to be highlighted in bold.
+
+** Imenu
+
++++
+*** 'imenu' is now bound to 'M-g i' globally.
+
+---
+*** New function 'imenu-flush-cache'.
+Use it if you want Imenu to forget the buffer's index alist and
+recreate it anew next time 'imenu' is invoked.
+
+---
+** Emacs is now capable of abandoning a window's redisplay that takes too long.
+This is controlled by the new variable 'max-redisplay-ticks'. If that
+variable is set to a non-zero value, display of a window will be
+aborted after that many low-level redisplay operations, thus
+preventing Emacs from becoming wedged when visiting files with very
+long lines. The default is zero, which disables the feature: Emacs
+will wait forever for redisplay to finish. (We believe you won't need
+this feature, given the ability to display buffers with very long
+lines.)
+
+* Editing Changes in Emacs 29.1
+
++++
+** 'M-SPC' is now bound to 'cycle-spacing'.
+Formerly it invoked 'just-one-space'. The actions performed by
+'cycle-spacing' and their order can now be customized via the user
+option 'cycle-spacing-actions'.
+
+---
+** 'zap-to-char' and 'zap-up-to-char' are case-sensitive for upper-case chars.
+These commands now behave as case-sensitive for interactive calls when
+they are invoked with an uppercase character, regardless of the value
+of 'case-fold-search'.
+
+---
+** 'scroll-other-window' and 'scroll-other-window-down' now respect remapping.
+These commands (bound to 'C-M-v' and 'C-M-V') used to scroll the other
+windows without looking at customizations in that other window. These
+functions now check whether they have been rebound in the buffer shown
+in that other window, and then call the remapped function instead. In
+addition, these commands now also respect the
+'scroll-error-top-bottom' user option.
+
+---
+** Indentation of 'cl-flet' and 'cl-labels' has changed.
+These forms now indent like this:
+
+ (cl-flet ((bla (x)
+ (* x x)))
+ (bla 42))
+
+This change also affects 'cl-macrolet', 'cl-flet*' and
+'cl-symbol-macrolet'.
+
++++
+** New user option 'translate-upper-case-key-bindings'.
+Set this option to nil to inhibit the default translation of upper
+case keys to their lower case variants.
+
++++
+** New command 'ensure-empty-lines'.
+This command increases (or decreases) the number of empty lines before
+point.
+
+---
+** Improved mouse behavior with auto-scrolling modes.
+When clicking inside the 'scroll-margin' or 'hscroll-margin' region,
+point is now moved only when releasing the mouse button. This no
+longer results in a bogus selection, unless the mouse has also been
+dragged.
+
++++
+** 'kill-ring-max' now defaults to 120.
+
+---
+** New user option 'yank-menu-max-items'.
+Customize this option to limit the number of entries in the menu
+"Edit->Paste from Kill Menu". The default is 60.
+
++++
+** Performing a pinch gesture on a touchpad now increases the text scale.
+
+** show-paren-mode
+
++++
+*** New user option 'show-paren-context-when-offscreen'.
+When non-nil, if the point is in a closing delimiter and the opening
+delimiter is offscreen, shows some context around the opening
+delimiter in the echo area. The default is nil.
+
+This option can also be set to the symbols 'overlay' or 'child-frame',
+in which case the context is shown in an overlay or child-frame at the
+top-left of the current window. The latter option requires a
+graphical frame. On non-graphical frames, the context is shown in the
+echo area.
+
+** Comint
+
++++
+*** 'comint-term-environment' is now aware of connection-local variables.
+The user option 'comint-terminfo-terminal' and the variable
+'system-uses-terminfo' can now be set as connection-local variables to
+change the terminal used on a remote host.
+
+---
+*** New user option 'comint-delete-old-input'.
+When nil, this prevents comint from deleting the current input when
+inserting previous input using '<mouse-2>'. The default is t, to
+preserve previous behavior.
+
+---
+*** New minor mode 'comint-fontify-input-mode'.
+This minor mode is enabled by default in "*shell*" and "*ielm*"
+buffers. It fontifies input text according to 'shell-mode' or
+'emacs-lisp-mode' font-lock rules. Customize the user options
+'shell-fontify-input-enable' and 'ielm-fontify-input-enable' to nil if
+you don't want to enable input fontification by default.
+
+** Mwheel
+
+---
+*** New user options for alternate wheel events.
+The options 'mouse-wheel-down-alternate-event',
+'mouse-wheel-up-alternate-event', 'mouse-wheel-left-alternate-event',
+and 'mouse-wheel-right-alternate-event' have been added to better
+support systems where two kinds of wheel events can be received.
+
+** Internationalization changes
+
+---
+*** The <Delete> function key now allows deleting the entire composed sequence.
+For the details, see the item about the 'delete-forward-char' command
+above.
+
+---
+*** New user option 'composition-break-at-point'.
+Setting it to a non-nil value temporarily disables automatic
+composition of character sequences at point, and thus makes it easier
+to edit such sequences by allowing point to "enter" the composed
+sequence.
+
+---
+*** Support for many old scripts and writing systems.
+Emacs now supports, and has language-environments and input methods,
+for several dozens of old scripts that were used in the past for
+various languages. For each such script Emacs now has font-selection
+and character composition rules, a language environment, and an input
+method. The newly-added scripts and the corresponding language
+environments are:
+
+ Tai Tham script and the Northern Thai language environment
+
+ Brahmi script and language environment
+
+ Kaithi script and language environment
+
+ Tirhuta script and language environment
+
+ Sharada script and language environment
+
+ Siddham script and language environment
+
+ Syloti Nagri script and language environment
+
+ Modi script and language environment
+
+ Baybayin script and Tagalog language environment
+
+ Hanunoo script and language environment
+
+ Buhid script and language environment
+
+ Tagbanwa script and language environment
+
+ Limbu script and language environment
+
+ Balinese script and language environment
+
+ Javanese script and language environment
+
+ Sundanese script and language environment
+
+ Batak script and language environment
+
+ Rejang script and language environment
+
+ Makasar script and language environment
+
+ Lontara script and language environment
+
+ Hanifi Rohingya script and language environment
+
+ Grantha script and language environment
+
+ Kharoshthi script and language environment
+
+ Lepcha script and language environment
+
+ Meetei Mayek script and language environment
+
+ Adlam script and language environment
+
+ Mende Kikakui script and language environment
+
+ Wancho script and language environment
+
+ Toto script and language environment
+
+ Gothic script and language environment
+
+ Coptic script and language environment
+
+---
+*** The "Oriya" language environment was renamed to "Odia".
+This is to follow the change in the official name of the script. The
+'oriya' input method was also renamed to 'odia'. However, the old
+name of the language environment and the input method are still
+supported.
+
+---
+*** New Greek translation of the Emacs tutorial.
+Type 'C-u C-h t' to select it in case your language setup does not do
+so automatically.
+
+---
+*** New Ukrainian translation of the Emacs Tutorial.
+
+---
+*** New default phonetic input method for the Tamil language environment.
+The default input method for the Tamil language environment is now
+"tamil-phonetic" which is a customizable phonetic input method. To
+change the input method's translation rules, customize the user option
+'tamil-translation-rules'.
+
+---
+*** New tamil99 input method for the Tamil language.
+This supports the keyboard layout specifically designed for the Tamil
+language.
+
+---
+*** New input method 'slovak-qwerty'.
+This is a variant of the 'slovak' input method, which corresponds to
+the QWERTY Slovak keyboards.
+
+---
+*** New input method 'cyrillic-chuvash'.
+This input method is based on the russian-computer input method, and
+is intended for typing in the Chuvash language written in the Cyrillic
+script.
+
+
+* Changes in Specialized Modes and Packages in Emacs 29.1
+
+** Ecomplete
+
+---
+*** New commands 'ecomplete-edit' and 'ecomplete-remove'.
+These allow you to (respectively) edit and bulk-remove entries from
+the ecomplete database.
+
+---
+*** New user option 'ecomplete-auto-select'.
+If non-nil and there's only one matching option, auto-select that.
+
+---
+*** New user option 'ecomplete-filter-regexp'.
+If non-nil, this user option describes what entries not to add to the
+database stored on disk.
+
+** Auth-Source
+
++++
+*** New user option 'auth-source-pass-extra-query-keywords'.
+Whether to recognize additional keyword params, like ':max' and
+':require', as well as accept lists of query terms paired with
+applicable keywords. This disables most known behavioral quirks
+unique to auth-source-pass, such as wildcard subdomain matching.
+
+** Dired
+
++++
+*** 'dired-guess-shell-command' moved from dired-x to dired.
+This means that 'dired-do-shell-command' will now provide smarter
+defaults without first having to require 'dired-x'. See the node
+"(emacs) Shell Command Guessing" in the Emacs manual for more details.
+
+---
+*** 'dired-clean-up-buffers-too' moved from dired-x to dired.
+This means that Dired now offers to kill buffers visiting files and
+dirs when they are deleted in Dired. Before, you had to require
+'dired-x' to enable this behavior. To disable this behavior,
+customize the user option 'dired-clean-up-buffers-too' to nil. The
+related user option 'dired-clean-confirm-killing-deleted-buffers'
+(which see) has also been moved to 'dired'.
+
++++
+*** 'dired-do-relsymlink' moved from dired-x to dired.
+The corresponding key 'Y' is now bound by default in Dired.
+
++++
+*** 'dired-do-relsymlink-regexp' moved from dired-x to dired.
+The corresponding key '% Y' is now bound by default in Dired.
+
+---
+*** 'M-G' is now bound to 'dired-goto-subdir'.
+Before, that binding was only available if the dired-x package was
+loaded.
+
++++
+*** 'dired-info' and 'dired-man' moved from dired-x to dired.
+The 'dired-info' and 'dired-man' commands have been moved from the
+dired-x package to dired. They have also been renamed to
+'dired-do-info' and 'dired-do-man'; the old command names are obsolete
+aliases.
+
+The keys 'I' ('dired-do-info') and 'N' ('dired-do-man') are now bound
+in Dired mode by default. The user options 'dired-bind-man' and
+'dired-bind-info' no longer have any effect and are obsolete.
+
+To get the old behavior back and unbind these keys in Dired mode, add
+the following to your Init file:
+
+ (with-eval-after-load 'dired
+ (keymap-set dired-mode-map "N" nil)
+ (keymap-set dired-mode-map "I" nil))
+
+---
+*** New command 'dired-do-eww'.
+This command visits the file on the current line with EWW.
+
+---
+*** New user option 'dired-omit-lines'.
+This is used by 'dired-omit-mode', and now allows you to hide based on
+other things than just the file names.
+
++++
+*** New user option 'dired-mouse-drag-files'.
+If non-nil, dragging file names with the mouse in a Dired buffer will
+initiate a drag-and-drop session allowing them to be opened in other
+programs.
+
++++
+*** New user option 'dired-free-space'.
+Dired will now, by default, include the free space in the first line
+instead of having it on a separate line. To get the previous behavior
+back, say:
+
+ (setq dired-free-space 'separate)
+
+---
+*** New user option 'dired-make-directory-clickable'.
+If non-nil (which is the default), hitting 'RET' or 'mouse-1' on
+the directory components at the directory displayed at the start of
+the buffer will take you to that directory.
+
+---
+*** Search and replace in Dired/Wdired supports more regexps.
+For example, the regexp ".*" will match only characters that are part
+of the file name. Also "^.*$" can be used to match at the beginning
+of the file name and at the end of the file name. This is used only
+when searching on file names. In Wdired this can be used when the new
+user option 'wdired-search-replace-filenames' is non-nil (which is the
+default).
+
+** Elisp
+
+---
+*** New command 'elisp-eval-region-or-buffer' (bound to 'C-c C-e').
+This command evals the forms in the active region or in the whole buffer.
+
+---
+*** New commands 'elisp-byte-compile-file' and 'elisp-byte-compile-buffer'.
+These commands (bound to 'C-c C-f' and 'C-c C-b', respectively)
+byte-compile the visited file and the current buffer, respectively.
+
+** Games
+
+---
+*** New user option 'tetris-allow-repetitions'.
+This controls how randomness is implemented (whether to use pure
+randomness as before, or to use a bag).
+
+** Battery
+
++++
+*** New user option 'battery-update-functions'.
+This can be used to trigger actions based on the battery status.
+
+** Enriched Mode
+
++++
+*** New command 'enriched-toggle-markup'.
+This allows you to see the markup in 'enriched-mode' buffers (e.g.,
+the "HELLO" file).
+
+** Shell Script Mode
+
+---
+*** New user option 'sh-indent-statement-after-and'.
+This controls how statements like the following are indented:
+
+ foo &&
+ bar
+
+*** New Flymake backend using the ShellCheck program.
+It is enabled by default, but requires that the external "shellcheck"
+command is installed.
+
+** CC Mode
+
+---
+*** C++ Mode now supports most of the new features in the C++20 Standard.
+
+** Cperl Mode
+
+---
+*** New user option 'cperl-file-style'.
+This option determines the indentation style to be used. It can also
+be used as a file-local variable.
+
+** Gud
+
+---
+*** 'gud-go' is now bound to 'C-c C-v'.
+If given a prefix, it will prompt for an argument to use for the
+run/continue command.
+
+---
+*** 'perldb' now recognizes '-E'.
+As of Perl 5.10, 'perl -E 0' behaves like 'perl -e 0' but also activates
+all optional features of the Perl version in use. 'perldb' now uses
+this invocation as its default.
+
+** Customize
+
+---
+*** New command 'custom-toggle-hide-all-widgets'.
+This is bound to 'H' and toggles whether to hide or show the widget
+contents.
+
+** Diff mode
+
+---
+*** New user option 'diff-whitespace-style'.
+Sets the value of the buffer-local variable 'whitespace-style' in
+'diff-mode' buffers. By default, this variable is '(face trailing)',
+which preserves behavior of previous Emacs versions.
+
++++
+*** New user option 'diff-add-log-use-relative-names'.
+If non-nil insert file names in ChangeLog skeletons relative to the
+VC root directory.
+
+** Ispell
+
+---
+*** 'ispell-region' and 'ispell-buffer' now push the mark.
+These commands push onto the mark ring the location of the last
+misspelled word where corrections were offered, so that you can then
+skip back to that location with 'C-x C-x'.
+
+** Dabbrev
+
+---
+*** New function 'dabbrev-capf' for use on 'completion-at-point-functions'.
+
++++
+*** New user option 'dabbrev-ignored-buffer-modes'.
+Buffers with major modes in this list will be ignored. By default,
+this includes "binary" buffers like 'archive-mode' and 'image-mode'.
+
+** Package
+
++++
+*** New command 'package-update'.
+This command allows you to upgrade packages without using 'M-x
+list-packages'.
+
++++
+*** New command 'package-update-all'.
+This command allows updating all packages without any queries.
+
++++
+*** New commands 'package-recompile' and 'package-recompile-all'.
+These commands can be useful if the ".elc" files are out of date
+(invalid byte code and macros).
+
++++
+*** New DWIM action on 'x' in "*Packages*" buffer.
+If no packages are marked, 'x' will install the package under point if
+it isn't already, and remove it if it is installed.
+
++++
+*** New command 'package-vc-install'.
+Packages can now be installed directly from source by cloning from
+their repository.
+
++++
+*** New command 'package-vc-install-from-checkout'.
+An existing checkout can now be loaded via package.el, by creating a
+symbolic link from the usual package directory to the checkout.
+
++++
+*** New command 'package-vc-checkout'.
+Used to fetch the source of a package by cloning a repository without
+activating the package.
+
++++
+*** New command 'package-vc-prepare-patch'.
+This command allows you to send patches to package maintainers, for
+packages checked out using 'package-vc-install'.
+
++++
+*** New command 'package-report-bug'.
+This command helps you compose an email for sending bug reports to
+package maintainers.
+
++++
+*** New user option 'package-vc-selected-packages'.
+By customizing this user option you can specify specific packages to
+install.
+
+** Emacs Sessions (Desktop)
+
++++
+*** New user option to load a locked desktop if locking Emacs is not running.
+The option 'desktop-load-locked-desktop' can now be set to the value
+'check-pid', which means to allow loading a locked ".emacs.desktop"
+file if the Emacs process which locked it is no longer running on the
+local machine. This allows avoiding questions about locked desktop
+files when the Emacs session which locked it crashes, or was otherwise
+interrupted and didn't exit gracefully. See the "(emacs) Saving
+Emacs Sessions" node in the Emacs manual for more details.
+
+** Miscellaneous
+
++++
+*** New command 'scratch-buffer'.
+This command switches to the "*scratch*" buffer. If "*scratch*" doesn't
+exist, the command creates it first. You can use this command if you
+inadvertently delete the "*scratch*" buffer.
+
+** Debugging
+
+---
+*** 'q' in a "*Backtrace*" buffer no longer clears the buffer.
+Instead it just buries the buffer and switches the mode from
+'debugger-mode' to 'backtrace-mode', since commands like 'e' are no
+longer available after exiting the recursive edit.
+
++++
+*** New user option 'debug-allow-recursive-debug'.
+This user option controls whether the 'e' (in a "*Backtrace*"
+buffer or while edebugging) and 'C-x C-e' (while edebugging) commands
+lead to a (further) backtrace. By default, this variable is nil,
+which is a change in behavior from previous Emacs versions.
+
++++
+*** 'e' in edebug can now take a prefix arg to pretty-print the results.
+When invoked with a prefix argument, as in 'C-u e', this command will
+pop up a new buffer and show the full pretty-printed value there.
+
++++
+*** 'C-x C-e' now interprets a non-zero prefix arg to pretty-print the results.
+When invoked with a non-zero prefix argument, as in 'C-u C-x C-e',
+this command will pop up a new buffer and show the full pretty-printed
+value there.
+
++++
+*** You can now generate a backtrace from Lisp errors in redisplay.
+To do this, set the new variable 'backtrace-on-redisplay-error' to a
+non-nil value. The backtrace will be written to a special buffer
+named "*Redisplay-trace*". This buffer will not be automatically
+displayed in a window.
+
+** Compile
+
++++
+*** New user option 'compilation-hidden-output'.
+This can be used to make specific parts of compilation output
+invisible.
+
++++
+*** The 'compilation-auto-jump-to-first-error' user option has been extended.
+It can now have the additional values 'if-location-known' (which will
+only jump if the location of the first error is known), and
+'first-known' (which will jump to the first known error location).
+
++++
+*** New user option 'compilation-max-output-line-length'.
+Lines longer than the value of this variable will have their ends
+hidden, with a button to reveal the hidden text. This speeds up
+operations like grepping on files that have few newlines. The default
+value is 400; set to nil to disable hiding.
+
+** Flymake
+
++++
+*** New user option 'flymake-mode-line-lighter'.
+
++++
+** New minor mode 'word-wrap-whitespace-mode' for extending 'word-wrap'.
+This mode switches 'word-wrap' on, and breaks on all the whitespace
+characters instead of just 'SPC' and 'TAB'.
+
+---
+** New mode, 'emacs-news-mode', for editing the NEWS file.
+This mode adds some highlighting, makes the 'M-q' command aware of the
+format of NEWS entries, and has special commands for doing maintenance
+of the Emacs NEWS files. In addition, this mode turns on
+'outline-minor-mode', and thus displays customizable icons (see
+'icon-preference') in the margins. To disable these icons, set
+'outline-minor-mode-use-buttons' to a nil value.
+
+---
+** Kmacro
+Kmacros are now OClosures and have a new constructor 'kmacro' which
+uses the 'key-parse' syntax. It replaces the old 'kmacro-lambda-form'
+(which is now declared obsolete).
+
+---
+** savehist.el can now truncate variables that are too long.
+An element of 'savehist-additional-variables' can now be of the form
+'(VARIABLE . MAX-ELTS)', which means to truncate the VARIABLE's value to
+at most MAX-ELTS elements (if the value is a list) before saving the
+value.
+
+** Minibuffer and Completions
+
++++
+*** New commands for navigating completions from the minibuffer.
+When the minibuffer is the current buffer, typing 'M-<up>' or
+'M-<down>' selects a previous/next completion candidate from the
+"*Completions*" buffer and inserts it to the minibuffer.
+When the user option 'minibuffer-completion-auto-choose' is nil,
+'M-<up>' and 'M-<down>' do the same, but without inserting
+a completion candidate to the minibuffer, then 'M-RET' can be used
+to choose the currently active candidate from the "*Completions*"
+buffer and exit the minibuffer. With a prefix argument, 'C-u M-RET'
+inserts the currently active candidate to the minibuffer, but doesn't
+exit the minibuffer. These keys are also available for in-buffer
+completion, but they don't insert candidates automatically, you need
+to type 'M-RET' to insert the selected candidate to the buffer.
+
++++
+*** Choosing a completion with a prefix argument doesn't exit the minibuffer.
+This means that typing 'C-u RET' on a completion candidate in the
+"*Completions*" buffer inserts the completion into the minibuffer,
+but doesn't exit the minibuffer.
+
++++
+*** The "*Completions*" buffer can now be automatically selected.
+To enable this behavior, customize the user option
+'completion-auto-select' to t, then pressing 'TAB' will switch to the
+"*Completions*" buffer when it pops up that buffer. If the value is
+'second-tab', then the first 'TAB' will display "*Completions*", and
+the second one will switch to the "*Completions*" buffer.
+
+---
+*** New user option 'completion-auto-wrap'.
+When non-nil, the commands 'next-completion' and 'previous-completion'
+automatically wrap around on reaching the beginning or the end of
+the "*Completions*" buffer.
+
++++
+*** New values for the 'completion-auto-help' user option.
+There are two new values to control the way the "*Completions*" buffer
+behaves after pressing a 'TAB' if completion is not unique. The value
+'always' updates or shows the "*Completions*" buffer after any attempt
+to complete. The value 'visual' is like 'always', but only updates
+the completions if they are already visible. The default value t
+always hides the completion buffer after some completion is made.
+
+---
+*** New commands to complete the minibuffer history.
+'minibuffer-complete-history' ('C-x <up>') is like 'minibuffer-complete'
+but completes on the history items instead of the default completion
+table. 'minibuffer-complete-defaults' ('C-x <down>') completes
+on the list of default items.
+
++++
+*** User option 'minibuffer-eldef-shorten-default' is now obsolete.
+Customize the user option 'minibuffer-default-prompt-format' instead.
+
++++
+*** New user option 'completions-sort'.
+This option controls the sorting of the completion candidates in
+the "*Completions*" buffer. Available styles are no sorting,
+alphabetical (the default), or a custom sort function.
+
++++
+*** New user option 'completions-max-height'.
+This option limits the height of the "*Completions*" buffer.
+
++++
+*** New user option 'completions-header-format'.
+This is a string to control the header line to show in the
+"*Completions*" buffer before the list of completions.
+If it contains "%s", that is replaced with the number of completions.
+If nil, the header line is not shown.
+
++++
+*** New user option 'completions-highlight-face'.
+When this user option names a face, the current
+candidate in the "*Completions*" buffer is highlighted with that face.
+The nil value disables this highlighting. The default is to highlight
+using the 'completions-highlight' face.
+
++++
+*** You can now define abbrevs for the minibuffer modes.
+'minibuffer-mode-abbrev-table' and
+'minibuffer-inactive-mode-abbrev-table' are now defined.
+
+** Isearch and Replace
+
++++
+*** Changes in how Isearch responds to 'mouse-yank-at-point'.
+If a user does 'C-s' and then uses '<mouse-2>' ('mouse-yank-primary')
+outside the echo area, Emacs will, by default, end the Isearch and
+yank the text at mouse cursor. But if 'mouse-yank-at-point' is
+non-nil, the text will now be added to the Isearch instead.
+
++++
+*** Changes for values 'no' and 'no-ding' of 'isearch-wrap-pause'.
+Now with these values the search will wrap around not only on repeating
+with 'C-s C-s', but also after typing a character.
+
++++
+*** New user option 'char-fold-override'.
+Non-nil means that the default definitions of equivalent characters
+are overridden.
+
+*** New command 'describe-char-fold-equivalences'.
+It displays character equivalences used by 'char-fold-to-regexp'.
+
++++
+*** New command 'isearch-emoji-by-name'.
+It is bound to 'C-x 8 e RET' during an incremental search. The
+command accepts the Unicode name of an Emoji (for example, "smiling
+face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
+completion, and adds the Emoji into the search string.
+
+** Glyphless characters
+
++++
+*** New minor mode 'glyphless-display-mode'.
+This allows an easy way to toggle seeing all glyphless characters in
+the current buffer.
+
+---
+*** The extra slot of 'glyphless-char-display' can now have cons values.
+The extra slot of the 'glyphless-char-display' char-table can now have
+values that are cons cells, specifying separate values for text-mode
+and GUI terminals.
+
++++
+*** "Replacement character" feature for undisplayable characters on TTYs.
+The 'acronym' method of displaying glyphless characters on text-mode
+frames treats single-character acronyms specially: they are displayed
+without the surrounding [..] "box", thus in effect treating such
+"acronyms" as replacement characters.
+
+** Registers
+
++++
+*** Buffer names can now be stored in registers.
+For instance, to enable jumping to the "*Messages*" buffer with
+'C-x r j m':
+
+ (set-register ?m '(buffer . "*Messages*"))
+
+** Pixel-fill
+
++++
+*** This is a new package that deals with filling variable-pitch text.
+
++++
+*** New function 'pixel-fill-region'.
+This fills the region to be no wider than a specified pixel width.
+
+** Info
+
++++
+*** 'M-x info-apropos' now takes a prefix argument to search for regexps.
+
+---
+*** New command 'Info-goto-node-web' and key binding 'G'.
+This will take you to the gnu.org web server's version of the current
+info node. This command only works for the Emacs and Emacs Lisp manuals.
+
+** Shortdoc
+
+---
+*** New command 'shortdoc-copy-function-as-kill' bound to 'w'.
+It copies the name of the function near point into the kill ring.
+
+---
+*** 'N' and 'P' are now bound to 'shortdoc-{next,previous}-section'.
+This is in addition to the old keybindings 'C-c C-n' and 'C-c C-p'.
+
+** VC
+
+---
+*** New command 'vc-pull-and-push'.
+This commands first does a "pull" command, and if that is successful,
+does a "push" command afterwards.
+
++++
+*** 'C-x v b' prefix key is used now for branch commands.
+'vc-print-branch-log' is bound to 'C-x v b l', and new commands are
+'vc-create-branch' ('C-x v b c') and 'vc-switch-branch' ('C-x v b s').
+The VC Directory buffer now uses the prefix 'b' for these branch-related
+commands.
+
++++
+*** New command '%' ('vc-dir-mark-by-regexp').
+This command marks files based on a regexp. If given a prefix
+argument, unmark instead.
+
++++
+*** New command 'C-x v !' ('vc-edit-next-command').
+This prefix command requests editing of the next VC shell command
+before execution. For example, in a Git repository, you can produce a
+log of more than one branch by typing 'C-x v ! C-x v b l' and then
+appending additional branch names to the 'git log' command.
+
+---
+*** 'C-x v v' in a diffs buffer allows to commit only some of the changes.
+This command is intended to allow you to commit only some of the
+changes you have in your working tree. Begin by creating a buffer
+with the changes against the last commit, e.g. with 'C-x v D'
+('vc-root-diff'). Then edit the diffs to remove the hunks you don't
+want to commit. Finally, type 'C-x v v' in that diff buffer to commit
+only part of your changes, those whose hunks were left in the buffer.
+
+---
+*** 'C-x v v' on an unregistered file will now use the most specific backend.
+Previously, if you had an SVN-covered "~/" directory, and a Git-covered
+directory in "~/foo/bar", using 'C-x v v' on a new, unregistered file
+"~/foo/bar/zot" would register it in the SVN repository in "~/" instead of
+in the Git repository in "~/foo/bar". This makes this command
+consistent with 'vc-responsible-backend'.
+
+---
+*** Log Edit now fontifies long Git commit summary lines.
+Writing shorter summary lines avoids truncation in contexts in which
+Git commands display summary lines. See the two new user options
+'vc-git-log-edit-summary-target-len' and 'vc-git-log-edit-summary-max-len'.
+
+---
+*** New 'log-edit-headers-separator' face.
+It is used to style the line that separates the 'log-edit' headers
+from the 'log-edit' summary.
+
+---
+*** The function 'vc-read-revision' accepts a new MULTIPLE argument.
+If non-nil, multiple revisions can be queried. This is done using
+'completing-read-multiple'.
+
+---
+*** New function 'vc-read-multiple-revisions'.
+This function invokes 'vc-read-revision' with a non-nil value for
+MULTIPLE.
+
++++
+*** New command 'vc-prepare-patch'.
+Patches for any version control system can be prepared using VC. The
+command will query what commits to send and will compose messages for
+your mail user agent. The behavior of 'vc-prepare-patch' can be
+modified by the user options 'vc-prepare-patches-separately' and
+'vc-default-patch-addressee'.
+
+** Message
+
+---
+*** New user option 'mml-attach-file-at-the-end'.
+If non-nil, 'C-c C-a' will put attached files at the end of the message.
+
+---
+*** Message Mode now supports image yanking.
+
++++
+*** New user option 'message-server-alist'.
+This controls automatic insertion of the "X-Message-SMTP-Method"
+header before sending a message.
+
+** HTML Mode
+
+---
+*** HTML Mode now supports "text/html" and "image/*" yanking.
+
+** Texinfo Mode
+
+---
+*** 'texinfo-mode' now has a specialized 'narrow-to-defun' definition.
+It narrows to the current node.
+
+** EUDC
+
++++
+*** Deprecations planned for next release.
+After Emacs 29.1, some aspects of EUDC will be deprecated. The goal
+of these deprecations is to simplify EUDC server configuration by
+making 'eudc-server-hotlist' the only place to add servers. There
+will not be a need to set the server using the 'eudc-set-server'
+command. Instead, the 'eudc-server-hotlist' user option should be
+customized to have an entry for the server. The plan is to obsolete
+the 'eudc-hotlist' package since Customize is sufficient for changing
+'eudc-server-hotlist'. How the 'eudc-server' user option works in this
+context is to-be-determined; it can't be removed, because that would
+break compatibility, but it may become synchronized with
+'eudc-server-hotlist' so that 'eudc-server' is always equal to '(car
+eudc-server-hotlist)'. The first entry in 'eudc-server-hotlist' is the
+first server tried by 'eudc-expand-try-all'. The hotlist
+simplification will allow 'eudc-query-form' to show a drop down of
+possible servers, instead of requiring a call to 'eudc-set-server'
+like it does in this release. The default value of
+'eudc-ignore-options-file' will be changed from nil to t.
+
++++
+*** New user option 'eudc-ignore-options-file' that defaults to nil.
+The 'eudc-ignore-options-file' user option can be configured to ignore
+the 'eudc-options-file' (typically "~/.emacs.d/eudc-options"). Most
+users should configure this to t and put EUDC configuration in the
+main Emacs initialization file ("~/.emacs" or "~/.emacs.d/init.el").
+
++++
+*** 'eudc-expansion-overwrites-query' to 'eudc-expansion-save-query-as-kill'.
+'eudc-expansion-overwrites-query' is renamed to
+'eudc-expansion-save-query-as-kill' to reflect the actual behavior of
+the user option.
+
++++
+*** New command 'eudc-expand-try-all'.
+This command can be used in place of 'eudc-expand-inline'. It takes a
+prefix argument that causes 'eudc-expand-try-all' to return matches
+from all servers instead of just the matches from the first server to
+return any. This is useful for example, if one wants to search LDAP
+for a name that happens to match a contact in one's BBDB.
+
++++
+*** New behavior and default for user option 'eudc-inline-expansion-format'.
+EUDC inline expansion result formatting defaulted to
+
+ '("%s %s <%s>" firstname name email)
+
+Since email address specifications need to comply with RFC 5322 in
+order to be useful in messages, there was a risk to produce syntax
+which was standard with RFC 822, but is marked as obsolete syntax by
+its successor RFC 5322. Also, the first and last name part was never
+enclosed in double quotes, potentially producing invalid address
+specifications, which may be rejected by a receiving MTA. Thus, this
+variable can now additionally be set to nil (the new default), or a
+function. In both cases, the formatted result will be in compliance
+with RFC 5322. When set to nil, a default format very similar to the
+old default will be produced. When set to a function, that function
+is called, and the returned values are used to populate the phrase and
+comment parts (see RFC 5322 for definitions). In both cases, the
+phrase part will be automatically quoted if necessary.
+
++++
+*** New function 'eudc-capf-complete' with 'message-mode' integration.
+EUDC can now contribute email addresses to 'completion-at-point' by
+adding the new function 'eudc-capf-complete' to
+'completion-at-point-functions' in 'message-mode'.
+
++++
+*** Additional attributes of query and results in eudcb-macos-contacts.el.
+The EUDC back-end for the macOS Contacts app now provides a wider set
+of attributes to use for queries, and delivers more attributes in
+query results.
+
++++
+*** New back-end for ecomplete.
+A new back-end for ecomplete allows information from that database to
+be queried by EUDC, too. The attributes present in the EUDC query are
+used to select the entry type in the ecomplete database.
+
++++
+*** New back-end for mailabbrev.
+A new back-end for mailabbrev allows information from that database to
+be queried by EUDC, too. The attributes 'email', 'name', and 'firstname'
+are supported only.
+
+** EWW/SHR
+
++++
+*** New user option to automatically rename EWW buffers.
+The 'eww-auto-rename-buffer' user option can be configured to rename
+rendered web pages by using their title, URL, or a user-defined
+function which returns a string. For the first two cases, the length
+of the resulting name is controlled by 'eww-buffer-name-length'. By
+default, no automatic renaming is performed.
+
++++
+*** New user option 'shr-allowed-images'.
+This complements 'shr-blocked-images', but allows specifying just the
+allowed images.
+
++++
+*** New user option 'shr-use-xwidgets-for-media'.
+If non-nil (and Emacs has been built with support for xwidgets),
+display <video> elements with an xwidget. Note that this is
+experimental; it is known to crash Emacs on some systems, and just
+doesn't work on other systems. Also see etc/PROBLEMS.
+
++++
+*** New user option 'eww-url-transformers'.
+These are used to alter an URL before using it. By default it removes
+the common "utm_" trackers from URLs.
+
+** Find-Dired
+
+---
+*** New command 'find-dired-with-command'.
+This enables users to run 'find-dired' with an arbitrary command,
+enabling running commands previously unsupported and also enabling new
+commands to be built on top.
+
+** Gnus
+
++++
+*** Tool bar changes in Gnus/Message.
+There were previously two styles of tool bars available in Gnus and
+Message, referred to as 'gnus-summary-tool-bar-retro',
+'gnus-group-tool-bar-retro' and 'message-tool-bar-retro', and
+'gnus-summary-tool-bar-gnome', 'gnus-group-tool-bar-gnome' and
+'message-tool-bar-gnome'. The "retro" tool bars have been removed (as
+well as the icons used), and the "Gnome" tool bars are now the only
+pre-defined toolbars.
+
+---
+*** 'gnus-summary-up-thread' and 'gnus-summary-down-thread' bindings removed.
+The 'gnus-summary-down-thread' binding to "M-C-d" was shadowed by
+'gnus-summary-read-document', and these commands are also available on
+"T-u" and "T-d" respectively.
+
+---
+*** Gnus now uses a variable-pitch font in the headers by default.
+To get the monospace font back, you can put something like the
+following in your ".gnus" file:
+
+ (set-face-attribute 'gnus-header nil :inherit 'unspecified)
+
+---
+*** The default value of 'gnus-treat-fold-headers' is now 'head'.
+
+---
+*** New face 'gnus-header'.
+All other 'gnus-header-*' faces inherit from this face now.
+
++++
+*** New user option 'gnus-treat-emojize-symbols'.
+If non-nil, symbols that have an Emoji representation will be
+displayed as emojis. The default is nil.
+
++++
+*** New command 'gnus-article-emojize-symbols'.
+This is bound to 'W D e' and will display symbols that have Emoji
+representation as Emoji.
+
++++
+*** New mu backend for gnus-search.
+Configuration is very similar to the notmuch and namazu backends. It
+supports the unified search syntax.
+
+---
+*** 'gnus-html-image-cache-ttl' is now a seconds count.
+Formerly it was a pair of numbers '(A B)' that represented 65536*A + B,
+to cater to older Emacs implementations that lacked bignums.
+The older form still works but is undocumented.
+
+** Rmail
+
+---
+*** Rmail partial summaries can now be applied one on top of the other.
+You can now narrow the set of messages selected by Rmail summary's
+criteria (recipients, topic, senders, etc.) by making a summary of the
+already summarized messages. For example, invoking
+'rmail-summary-by-senders', followed by 'rmail-summary-by-topic' will
+produce a summary where both the senders and the topic are according
+to your selection. The new user option
+'rmail-summary-progressively-narrow' controls whether the stacking of
+the filters is in effect; customize it to a non-nil value to enable
+this feature.
+
+---
+*** New Rmail summary: by thread.
+The new command 'rmail-summary-by-thread' produces a summary of
+messages that belong to a single thread of discussion.
+
+** EIEIO
+
++++
+*** 'slot-value' can now be used to access slots of 'cl-defstruct' objects.
+
+** Align
+
+---
+*** Alignment in 'text-mode' has changed.
+Previously, 'M-x align' didn't do anything, and you had to say 'C-u
+M-x align' for it to work. This has now been changed. The default
+regexp for 'C-u M-x align-regexp' has also been changed to be easier
+for inexperienced users to use.
+
+** Help
+
+---
+*** New mode, 'emacs-news-view-mode', for viewing the NEWS file.
+This mode is used by the 'C-h N' command, and adds buttons to manual
+entries and symbol references.
+
+---
+*** New user option 'help-link-key-to-documentation'.
+When this option is non-nil (which is the default), key bindings
+displayed in the "*Help*" buffer will be linked to the documentation
+for the command they are bound to. This does not affect listings of
+key bindings and functions (such as 'C-h b').
+
+** Info-look
+
+---
+*** info-look specs can now be expanded at run time instead of a load time.
+The new ':doc-spec-function' element can be used to compute the
+':doc-spec' element when the user asks for info on that particular
+mode (instead of at load time).
+
+** Ansi-color
+
+---
+*** Support for ANSI 256-color and 24-bit colors.
+256-color and 24-bit color codes are now handled by ANSI color
+filters and displayed with the specified color.
+
+** Term-mode
+
+---
+*** New user option 'term-bind-function-keys'.
+If non-nil, 'term-mode' will pass the function keys on to the
+underlying shell instead of using the normal Emacs bindings.
+
+---
+*** Support for ANSI 256-color and 24-bit colors, italic and other fonts.
+'term-mode' can now display 256-color and 24-bit color codes. It can
+also handle ANSI codes for faint, italic and blinking text, displaying
+it with new 'term-{faint,italic,slow-blink,fast-blink}' faces.
+
+** Project
+
++++
+*** 'project-find-file' and 'project-or-external-find-file' can include all.
+The commands 'project-find-file' and 'project-or-external-find-file'
+now accept a prefix argument, which is interpreted to mean "include
+all files".
+
++++
+*** New command 'project-list-buffers' bound to 'C-x p C-b'.
+This command displays a list of buffers from the current project.
+
++++
+*** 'project-kill-buffers' can display the list of buffers to kill.
+Customize the user option 'project-kill-buffers-display-buffer-list'
+to enable the display of the buffer list.
+
+*** New user option 'project-vc-extra-root-markers'.
+Use it to add detection of nested projects (inside a VCS repository),
+or projects outside of VCS repositories.
+
+As a consequence, the 'VC project backend' is formally renamed to
+'VC-aware project backend'.
+
++++
+*** New user option 'project-vc-include-untracked'.
+If non-nil, files untracked by a VCS are considered to be part of
+the project by a VC project based on that VCS.
+
+** Xref
+
++++
+*** New command 'xref-go-forward'.
+It is bound to 'C-M-,' and jumps to the location where 'xref-go-back'
+('M-,', also known as 'xref-pop-marker-stack') was invoked previously.
+
++++
+*** 'xref-query-replace-in-results' prompting change.
+This command no longer prompts for FROM when called without prefix
+argument. This makes the most common case faster: replacing entire
+matches.
+
++++
+*** New command 'xref-find-references-and-replace' to rename one identifier.
+
+---
+*** New variable 'xref-current-item' (renamed from a private version).
+
+---
+*** New function 'xref-show-xrefs'.
+
+** File notifications
+
++++
+*** The new command 'file-notify-rm-all-watches' removes all file notifications.
+
+** Sql
+
+---
+*** Sql now supports sending of passwords in-process.
+To improve security, if an sql product has ':password-in-comint' set
+to t, a password supplied via the minibuffer will be sent in-process,
+as opposed to via the command-line.
+
+** Image Mode
+
++++
+*** New command 'image-transform-fit-to-window'.
+This command fits the image to the current window by scaling down or
+up as necessary. Unlike 'image-transform-fit-both', this does not
+only scale the image down, but up as well. It is bound to 's w' in
+Image Mode by default.
+
+---
+*** New command 'image-mode-wallpaper-set'.
+This command sets the desktop background to the current image. It is
+bound to 'W' by default.
+
++++
+*** 'image-transform-fit-to-{height,width}' are now obsolete.
+Use the new command 'image-transform-fit-to-window' instead.
+The keybinding for 'image-transform-fit-to-width' is now 's i'.
+
+---
+*** User option 'image-auto-resize' can now be set to 'fit-window'.
+This works like 'image-transform-fit-to-window'.
+
+---
+*** New user option 'image-auto-resize-max-scale-percent'.
+The new 'fit-window' option will never scale an image more than this
+much (in percent). It is nil by default, which means no limit.
+
+---
+*** New user option 'image-text-based-formats'.
+This controls whether or not to show a message when opening certain
+image formats saying how to edit it as text. The default is to show
+this message for SVG and XPM.
+
++++
+*** New commands: 'image-flip-horizontally' and 'image-flip-vertically'.
+These commands horizontally and vertically flip the image under point,
+and are bound to 'i h' and 'i v', respectively.
+
++++
+*** New command 'image-transform-set-percent'.
+It allows setting the image size to a percentage of its original size,
+and is bound to 's p' in Image mode.
+
++++
+*** 'image-transform-original' renamed to 'image-transform-reset-to-original'.
+The old name was confusing, and is now an obsolete function alias.
+
++++
+*** 'image-transform-reset' renamed to 'image-transform-reset-to-initial'.
+The old name was confusing, and is now an obsolete function alias.
+
+** Images
+
++++
+*** Users can now add special image conversion functions.
+This is done via 'image-converter-add-handler'.
+
+** Image-Dired
+
++++
+*** 'image-dired-image-mode' is now based on 'image-mode'.
+This avoids converting images in the background, and makes Image-Dired
+noticeably faster. New keybindings from 'image-mode' are now
+available in the "*image-dired-display-image*" buffer; press '?' or
+'h' in that buffer to see the full list.
+
+---
+*** Navigation and marking commands now work in image display buffer.
+The following new bindings have been added:
+- 'n', 'SPC' => 'image-dired-display-next'
+- 'p', 'DEL' => 'image-dired-display-previous'
+- 'm' => 'image-dired-mark-thumb-original-file'
+- 'd' => 'image-dired-flag-thumb-original-file'
+- 'u' => 'image-dired-unmark-thumb-original-file'
+
+---
+*** New command 'image-dired-unmark-all-marks'.
+It removes all marks from all files in the thumbnail and the
+associated Dired buffer, and is bound to 'U' in the thumbnail and
+display buffer.
+
+---
+*** New command 'image-dired-do-flagged-delete'.
+It deletes all flagged files, and is bound to 'x' in the thumbnail
+buffer. It replaces the command 'image-dired-delete-marked', which is
+now an obsolete alias.
+
+---
+*** New command 'image-dired-copy-filename-as-kill'.
+It copies the name of the marked or current image to the kill ring,
+and is bound to 'w' in the thumbnail buffer.
+
+---
+*** New command 'image-dired-wallpaper-set'.
+This command sets the desktop background to the image at point in the
+thumbnail buffer. It is bound to 'W' by default.
+
+---
+*** 'image-dired-slideshow-start' is now bound to 'S'.
+It is bound in both the thumbnail and display buffer, and no longer
+prompts for a timeout; use a numerical prefix (e.g. 'C-u 8 S') to set
+the timeout.
+
+---
+*** New user option 'image-dired-marking-shows-next'.
+If this option is non-nil (the default), marking, unmarking or
+flagging an image in either the thumbnail or display buffer shows the
+next image.
+
+---
+*** New face 'image-dired-thumb-flagged'.
+If 'image-dired-thumb-mark' is non-nil (the default), this face is
+used for images that are flagged for deletion in the Dired buffer
+associated with Image-Dired.
+
+---
+*** Image information is now shown in the header line of the thumbnail buffer.
+This replaces the message that most navigation commands in the
+thumbnail buffer used to show at the bottom of the screen.
+
+---
+*** New specifiers for 'image-dired-display-properties-format'.
+This is used to format the new header line. The new specifiers are:
+"%d" for the name of the directory that the file is in, "%n" for
+file's number in the thumbnail buffer, and "%s" for the file size.
+
+The default format has been updated to use this. If you prefer the
+old format, add this to your Init file:
+
+ (setopt image-dired-display-properties-format "%b: %f (%t): %c")
+
+---
+*** New faces for the header line of the thumbnail buffer.
+These faces correspond to different parts of the header line, as
+specified in 'image-dired-display-properties-format':
+- 'image-dired-thumb-header-directory-name'
+- 'image-dired-thumb-header-file-name'
+- 'image-dired-thumb-header-file-size'
+- 'image-dired-thumb-header-image-count'
+
+---
+*** PDF support.
+Image-Dired now displays thumbnails for PDF files. Type 'RET' on a
+PDF file in the thumbnail buffer to visit the corresponding PDF.
+
+---
+*** Support GraphicsMagick command line tools.
+Support for the GraphicsMagick command line tool ("gm") has been
+added, and is used when it is available instead of ImageMagick.
+
+---
+*** Support Thumbnail Managing Standard v0.9.0 (Dec 2020).
+This standard allows sharing generated thumbnails across different
+programs. Version 0.9.0 adds two larger thumbnail sizes: 512x512 and
+1024x1024 pixels. See the user option 'image-dired-thumbnail-storage'
+to use it; it is not enabled by default.
+
+---
+*** Reduce dependency on external "exiftool" command.
+The 'image-dired-copy-with-exif-file-name' no longer requires an
+external "exiftool" command to be available. The user options
+'image-dired-cmd-read-exif-data-program' and
+'image-dired-cmd-read-exif-data-options' are now obsolete.
+
+---
+*** Support for bookmark.el.
+The command 'bookmark-set' (bound to 'C-x r m') is now supported in
+the thumbnail view, and will create a bookmark that opens the current
+directory in Image-Dired.
+
+---
+*** The 'image-dired-slideshow-start' command no longer prompts.
+It no longer inconveniently prompts for a number of images and a
+delay: it runs indefinitely, but stops automatically on any command.
+You can set the delay with a prefix argument, or a negative prefix
+argument to prompt for a delay. Customize the user option
+'image-dired-slideshow-delay' to change the default from 5 seconds.
+
++++
+*** 'image-dired-show-all-from-dir-max-files' increased to 1000.
+This user option controls asking for confirmation when starting
+Image-Dired in a directory with many files. Since Image-Dired creates
+thumbnails in the background in recent versions, this is not as
+important as it used to be. You can now also customize this option to
+nil to disable this confirmation completely.
+
+---
+*** 'image-dired-thumb-size' increased to 128.
+
++++
+*** 'image-dired-db-file' renamed to 'image-dired-tags-db-file'.
+
+---
+*** 'image-dired-display-image-mode' renamed to 'image-dired-image-mode'.
+The corresponding keymap is now named 'image-dired-image-mode-map'.
+
++++
+*** Some commands have been renamed to be shorter.
+- 'image-dired-display-thumbnail-original-image' has been renamed to
+ 'image-dired-display-this'.
+- 'image-dired-display-next-thumbnail-original' has been renamed to
+ 'image-dired-display-next'.
+- 'image-dired-display-previous-thumbnail-original' has been renamed
+ to 'image-dired-display-previous'.
+The old names are now obsolete aliases.
+
+---
+*** 'image-dired-thumb-{height,width}' are now obsolete.
+Customize 'image-dired-thumb-size' instead, which will set both the
+height and width.
+
+---
+*** HTML image gallery generation is now obsolete.
+The 'image-dired-gallery-generate' command and these user options are
+now obsolete: 'image-dired-gallery-thumb-image-root-url',
+'image-dired-gallery-hidden-tags', 'image-dired-gallery-dir',
+'image-dired-gallery-image-root-url'.
+
+---
+*** 'image-dired-rotate-thumbnail-{left,right}' are now obsolete.
+Instead, use commands 'image-dired-refresh-thumb' to generate a new
+thumbnail, or 'image-rotate' to rotate the thumbnail without updating
+the thumbnail file.
+
++++
+*** Some commands and user options are now obsolete.
+Since 'image-dired-display-image-mode' is now based on 'image-mode',
+some commands and user options are no longer needed and are now obsolete:
+'image-dired-cmd-create-temp-image-options',
+'image-dired-cmd-create-temp-image-program',
+'image-dired-display-current-image-full',
+'image-dired-display-current-image-sized',
+'image-dired-display-window-height-correction',
+'image-dired-display-window-width-correction',
+'image-dired-temp-image-file'.
+
+** Bookmarks
+
+---
+*** 'list-bookmarks' now includes a type column.
+Types are registered via a 'bookmark-handler-type' symbol property on
+the jumping function.
+
++++
+*** 'bookmark-sort-flag' can now be set to 'last-modified'.
+This will display bookmark list from most recently set to least
+recently set.
+
+---
+*** When editing a bookmark annotation, 'C-c C-k' will now cancel.
+It is bound to the new command 'bookmark-edit-annotation-cancel'.
+
+---
+*** New user option 'bookmark-fringe-mark'.
+This option controls the bitmap used to indicate bookmarks in the
+fringe (or nil to disable showing this marker).
+
+** Exif
+
+---
+*** New function 'exif-field'.
+This is a convenience function to extract the field data from
+'exif-parse-file' and 'exif-parse-buffer'.
+
+** Xwidgets
+
+---
+*** New user option 'xwidget-webkit-buffer-name-format'.
+This option controls how xwidget-webkit buffers are named.
+
+---
+*** New user option 'xwidget-webkit-cookie-file'.
+This option controls whether the xwidget-webkit buffers save cookies
+set by web pages, and if so, in which file to save them.
+
++++
+*** New minor mode 'xwidget-webkit-edit-mode'.
+When this mode is enabled, self-inserting characters and other common
+web browser shortcut keys are redefined to send themselves to the
+WebKit widget.
+
++++
+*** New minor mode 'xwidget-webkit-isearch-mode'.
+This mode acts similarly to incremental search, and allows searching
+the contents of a WebKit widget. In xwidget-webkit mode, it is bound
+to 'C-s' and 'C-r'.
+
++++
+*** New command 'xwidget-webkit-browse-history'.
+This command displays a buffer containing the page load history of
+the current WebKit widget, and allows you to navigate it.
+
+---
+*** On X, the WebKit inspector is now available inside xwidgets.
+To access the inspector, right click on the widget and select "Inspect
+Element".
+
+---
+*** "Open in New Window" in a WebKit widget's context menu now works.
+The newly created buffer will be displayed via 'display-buffer', which
+can be customized through the usual mechanism of 'display-buffer-alist'
+and friends.
+
+** Tramp
+
++++
+*** New connection methods "docker", "podman" and "kubernetes".
+They allow accessing environments provided by Docker and similar
+programs.
+
+---
+*** Tramp supports abbreviating remote home directories now.
+When calling 'abbreviate-file-name' on a Tramp file name, the result
+will abbreviate the user's home directory, for example by abbreviating
+"/ssh:user@host:/home/user" to "/ssh:user@host:~".
+
++++
+*** New user option 'tramp-use-scp-direct-remote-copying'.
+When set to non-nil, Tramp does not copy files between two remote
+hosts via a local copy in its temporary directory, but lets the 'scp'
+command do this job.
+
++++
+*** Proper password prompts for methods "doas", "sudo" and "sudoedit".
+The password prompts for these methods reflect now the credentials of
+the user requesting such a connection, and not of the user who is the
+target. This has always been needed, just the password prompt and the
+related 'auth-sources' entry were wrong.
+
++++
+*** New user option 'tramp-completion-use-cache'.
+During user and host name completion in the minibuffer, results from
+Tramp's connection cache are taken into account. This can be disabled
+by setting the user option 'tramp-completion-use-cache' to nil.
+
+** Browse URL
+
+---
+*** New user option 'browse-url-default-scheme'.
+This user option decides which URL scheme that 'browse-url' and
+related functions will use by default. For example, you could
+customize this to "https" to always prefer HTTPS URLs.
+
+---
+*** New user option 'browse-url-irc-function'.
+This option specifies a function for opening "irc://" links. It
+defaults to the new function 'browse-url-irc'.
+
+---
+*** New function 'browse-url-irc'.
+This multipurpose autoloaded function can be used for opening "irc://"
+and "ircs://" URLS by any caller that passes a URL string as an initial
+arg.
+
+---
+*** Support for the Netscape web browser has been removed.
+This support has been obsolete since Emacs 25.1. The final version of
+the Netscape web browser was released in February, 2008.
+
+---
+*** Support for the Galeon web browser has been removed.
+This support has been obsolete since Emacs 25.1. The final version of
+the Galeon web browser was released in September, 2008.
+
+---
+*** Support for the Mozilla web browser is now obsolete.
+Note that this historical web browser is different from Mozilla
+Firefox; it is its predecessor.
+
+** Python Mode
+
++++
+*** Project shells and a new user option 'python-shell-dedicated'.
+When called with a prefix argument, 'run-python' now offers the choice
+of creating a shell dedicated to the current project. This shell runs
+in the project root directory and is shared among all project buffers.
+
+Without a prefix argument, the kind of shell (buffer-dedicated,
+project-dedicated or global) is specified by the new
+'python-shell-dedicated' user option.
+
+** Ruby Mode
+
+---
+*** New user option 'ruby-toggle-block-space-before-parameters'.
+
+---
+*** Support for endless methods.
+
+---
+*** New user options that determine indentation logic.
+'ruby-method-params-indent', 'ruby-block-indent',
+'ruby-after-operator-indent', 'ruby-method-call-indent',
+'ruby-parenless-call-arguments-indent'. See the docstrings for
+explanations and examples.
+
+** Eshell
+
++++
+*** New feature to easily bypass Eshell's own pipelining.
+Prefixing '|', '<' or '>' with an asterisk, i.e. '*|', '*<' or '*>',
+will cause the whole command to be passed to the operating system
+shell. This is particularly useful to bypass Eshell's own pipelining
+support for pipelines which will move a lot of data. See section
+"Running Shell Pipelines Natively" in the Eshell manual, node
+"(eshell) Input/Output".
+
++++
+*** New module to help supplying absolute file names to remote commands.
+After enabling the new 'eshell-elecslash' module, typing a forward
+slash as the first character of a command line argument will
+automatically insert the Tramp prefix. The automatic insertion
+applies only when 'default-directory' is remote and the command is a
+Lisp function. This frees you from having to keep track of whether
+commands are Lisp function or external when supplying absolute file
+name arguments. See the "(eshell) Electric forward slash" node in the
+Eshell manual for details.
+
++++
+*** Improved support for redirection operators in Eshell.
+Eshell now supports a wider variety of redirection operators. For
+example, you can now redirect both stdout and stderr via '&>' or
+duplicate one output handle to another via 'NEW-FD>&OLD-FD'. For more
+information, see the "(eshell) Redirection" node in the Eshell manual.
+
++++
+*** New eshell built-in command 'doas'.
+The privilege-escalation program 'doas' has been added to the existing
+'su' and 'sudo' commands from the 'eshell-tramp' module. The external
+command may still be accessed by using '*doas'.
+
++++
+*** Double-quoting an Eshell expansion now treats the result as a single string.
+If an Eshell expansion like '$FOO' is surrounded by double quotes, the
+result will always be a single string, no matter the type that would
+otherwise be returned.
+
++++
+*** Concatenating Eshell expansions now works more similarly to other shells.
+When concatenating an Eshell expansion that returns a list, "adjacent"
+elements of each operand are now concatenated together,
+e.g. '$(list "a" "b")c' returns '("a" "bc")'. See the "(eshell)
+Expansion" node in the Eshell manual for more details.
+
++++
+*** Eshell subcommands with multiline numeric output return lists of numbers.
+If every line of the output of an Eshell subcommand like '${COMMAND}'
+is numeric, the result will be a list of numbers (or a single number
+if only one line of output). Previously, this only converted numbers
+when there was a single line of output.
+
+---
+*** Built-in Eshell commands now follow Posix/GNU argument syntax conventions.
+Built-in commands in Eshell now accept command-line options with
+values passed as a single token, such as '-oVALUE' or
+'--option=VALUE'. New commands can take advantage of this with the
+'eshell-eval-using-options' macro. See "Defining new built-in
+commands" in the "(eshell) Built-ins" node of the Eshell manual.
+
+---
+*** Eshell globs ending with '/' now match only directories.
+Additionally, globs ending with '**/' or '***/' no longer raise an
+error, and now expand to all directories recursively (following
+symlinks in the latter case).
+
++++
+*** Lisp forms in Eshell now treat a nil result as a failed exit status.
+When executing a command that looks like '(lisp form)' and returns
+nil, Eshell will set the exit status (available in the '$?'
+variable) to 2. This allows commands like that to be used in
+conditionals. To change this behavior, customize the new
+'eshell-lisp-form-nil-is-failure' user option.
+
+** Shell
+
+---
+*** New user option 'shell-kill-buffer-on-exit'.
+Enabling this will automatically kill a "*shell*" buffer as soon as
+the shell session terminates.
+
+---
+*** New minor mode 'shell-highlight-undef-mode'.
+Customize 'shell-highlight-undef-enable' to t if you want to enable
+this minor mode in "*shell*" buffers. It will highlight undefined
+commands with a warning face as you type.
+
+** Calc
+
++++
+*** New user option 'calc-kill-line-numbering'.
+Set it to nil to exclude line numbering from kills and copies.
+
+** Hierarchy
+
++++
+*** Tree Display can delay computation of children.
+'hierarchy-add-tree' and 'hierarchy-add-trees' have an optional
+argument which allows tree-widget display to be activated and computed
+only when the user expands the node.
+
+** Proced
+
+---
+*** proced.el shows system processes of remote hosts.
+When 'default-directory' is remote, and 'proced' is invoked with a
+negative argument like 'C-u - proced', the system processes of that
+remote host are shown. Alternatively, the user option
+'proced-show-remote-processes' can be set to non-nil.
+'proced-signal-function' has been marked obsolete.
+
+---
+*** Proced can now optionally show process details in color.
+New user option 'proced-enable-color-flag' enables coloring of Proced
+buffers. This option is disabled by default; customize it to a
+non-nil value to enable colors.
+
+** Miscellaneous
+
+---
+*** New user option 'webjump-use-internal-browser'.
+When non-nil, WebJump will use an internal browser to open web pages,
+instead of the default external browser.
+
++++
+*** New user option 'font-lock-ignore'.
+This option provides a mechanism to selectively disable font-lock
+keyword-driven fontifications.
+
+---
+*** New user option 'auto-save-visited-predicate'.
+This user option is a predicate function which is called by
+'auto-save-visited-mode' to decide whether or not to save a buffer.
+You can use it to automatically save only specific buffers, for
+example buffers using a particular mode or in some directory.
+
+---
+*** New user option 'remote-file-name-inhibit-auto-save-visited'.
+If this user option is non-nil, 'auto-save-visited-mode' will not
+auto-save remote buffers. The default is nil.
+
++++
+*** New package vtable.el for formatting tabular data.
+This package allows formatting data using variable-pitch fonts.
+The resulting tables can display text in variable pitch fonts, text
+using fonts of different sizes, and images. See the "(vtable) Top"
+manual for more details.
+
+---
+*** New minor mode 'elide-head-mode'.
+Enabling this minor mode turns on hiding header material, like
+'elide-head' does; disabling it shows the header. The commands
+'elide-head' and 'elide-head-show' are now obsolete.
+
+*** New package ansi-osc.el.
+Support for OSC ("Operating System Command") escape sequences has been
+extracted from comint.el in order to provide interpretation of OSC
+sequences in compilation buffers.
+
+Adding the new function 'ansi-osc-compilation-filter' to
+'compilation-filter-hook' enables interpretation of OSC escape
+sequences in compilation buffers. By default, all sequences are
+filtered out.
+
+The list of handlers (already covering OSC 7 and 8) has been extended
+with a handler for OSC 2, the command to set a window title.
+
+---
+*** 'recentf-mode' now uses abbreviated file names by default.
+This means that e.g. "/home/foo/bar" is now displayed as "~/bar".
+Customize the user option 'recentf-filename-handlers' to nil to get
+back the old behavior.
+
+---
+*** New command 'recentf-open'.
+This command prompts for a recently opened file in the minibuffer, and
+visits it.
+
+---
+*** 'ffap-machine-at-point' no longer pings hosts by default.
+It will now simply look at a hostname to determine if it is valid,
+instead of also trying to ping it. Customize the user option
+'ffap-machine-p-known' to 'ping' to get the old behavior back.
+
+---
+*** The 'run-dig' command is now obsolete; use 'dig' instead.
+
+---
+*** Some 'bib-mode' commands and variables have been renamed.
+To respect Emacs naming conventions, the variable 'unread-bib-file'
+has been renamed to 'bib-unread-file'. The following commands have
+also been renamed:
+ 'addbib' to 'bib-add'
+ 'return-key-bib' to 'bib-return-key'
+ 'mark-bib' to 'bib-mark'
+ 'unread-bib' to 'bib-unread'
+
+---
+*** 'outlineify-sticky' command is renamed to 'allout-outlinify-sticky'.
+The old name is still available as an obsolete function alias.
+
+---
+*** The url-irc library now understands "ircs://" links.
+
+---
+*** New command 'world-clock-copy-time-as-kill' for 'M-x world-clock'.
+It copies the current line into the kill ring.
+
+---
+*** 'edit-abbrevs' now uses font-locking.
+The new face 'abbrev-table-name' is used to display the abbrev table
+name.
+
+---
+*** New key binding 'O' in 'M-x list-buffers'.
+This key is now bound to 'Buffer-menu-view-other-window', which will
+view this line's buffer in View mode in another window.
+
+** Scheme mode
+
+---
+*** Auto-detection of Scheme library files.
+Emacs now automatically enables the Scheme mode when opening R6RS
+Scheme Library Source ('.sls') files and R7RS Scheme Library
+Definition ('.sld') files.
+
+---
+*** Imenu members for R6RS and R7RS library members.
+Imenu now lists the members directly nested in R6RS Scheme libraries
+('library') and R7RS libraries ('define-library').
+
+
+* New Modes and Packages in Emacs 29.1
+
++++
+** Eglot: Emacs Client for the Language Server Protocol.
+Emacs now comes with the Eglot package, which enhances various Emacs
+features, such as completion, documentation, error detection, etc.,
+based on data provided by language servers using the Language Server
+Protocol (LSP).
+
++++
+*** use-package: Declarative package configuration.
+use-package is now shipped with Emacs. It provides the 'use-package'
+macro, which allows you to isolate package configuration in your init
+file in a way that is declarative, tidy, and performance-oriented.
+See the new Info manual "(use-package) Top" for more.
+
++++
+** New commands 'image-crop' and 'image-cut'.
+These commands allow interactively cropping/cutting the image at
+point. The commands are bound to keys 'i c' and 'i x' (respectively)
+in the local keymap over images. They rely on external programs, by
+default "convert" from ImageMagick, to do the actual cropping/eliding
+of the image file.
+
+---
+** New package 'wallpaper'.
+This package provides the command 'wallpaper-set', which sets the
+desktop background image. Depending on the system and the desktop,
+this may require an external program (such as "swaybg", "gm",
+"display" or "xloadimage"). If so, a suitable command should be
+detected automatically in most cases. It can also be customized
+manually if needed, using the new user options 'wallpaper-command' and
+'wallpaper-command-args'.
+
++++
+** New package 'oclosure'.
+This allows the creation of "functions with slots" or "function
+objects" via the macros 'oclosure-define' and 'oclosure-lambda'.
+
++++
+*** New generic function 'oclosure-interactive-form'.
+Used by 'interactive-form' when called on an OClosure.
+This allows specific OClosure types to compute their interactive specs
+on demand rather than precompute them when created.
+
+---
+** New theme 'leuven-dark'.
+This is a dark version of the 'leuven' theme.
+
++++
+** New mode 'erts-mode'.
+This mode is used to edit files geared towards testing actions in
+Emacs buffers, like indentation and the like. The new ert function
+'ert-test-erts-file' is used to parse these files.
+
+---
+** New major mode 'js-json-mode'.
+This is a lightweight variant of 'js-mode' that is used by default
+when visiting JSON files.
+
++++
+** New major mode 'csharp-mode'.
+A major mode based on CC Mode for editing programs in the C# language.
+This mode is auto-enabled for files with the ".cs" extension.
+
++++
+** New major modes based on the tree-sitter library.
+These new major modes are available if Emacs was built with the
+tree-sitter library. They provide support for font-locking,
+indentation, and navigation by defuns based on parsing the buffer text
+by a tree-sitter parser. Some major modes also offer support for
+Imenu and 'which-func'.
+
+Where major modes already exist in Emacs for editing certain kinds of
+files, the new modes based on tree-sitter are for now entirely
+optional, and you must turn them on manually, or customize
+'auto-mode-alist' to turn them on automatically.
+
+Each major mode based on tree-sitter needs a language grammar library,
+usually named "libtree-sitter-LANG.so" ("libtree-sitter-LANG.dll" on
+MS-Windows), where LANG is the corresponding language name. Emacs
+looks for these libraries in the following places:
+
+ . in the directories mentioned in the list 'treesit-extra-load-path'
+ . in the "tree-sitter" subdirectory of your 'user-emacs-directory'
+ (by default, "~/.emacs.d/tree-sitter")
+ . in the standard system directories where other shared libraries are
+ usually installed
+
+We recommend to install these libraries in one of the standard system
+locations (the last place in the above list).
+
+If a language grammar library required by a mode is not found in any
+of the above places, the mode will signal an error when you try to
+turn it on.
+
++++
+*** New major mode 'typescript-ts-mode'.
+A major mode based on the tree-sitter library for editing programs
+in the TypeScript language. This mode is auto-enabled for files with
+the ".ts" extension.
+
++++
+*** New major mode 'tsx-ts-mode'.
+A major mode based on the tree-sitter library for editing programs
+in the TypeScript language, with support for TSX. This mode is
+auto-enabled for files with the ".tsx" extension.
+
++++
+*** New major mode 'c-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the C language.
+
++++
+*** New major mode 'c++-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the C++ language.
+
++++
+*** New major mode 'java-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the Java language.
+
++++
+*** New major mode 'python-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the Python language.
+
++++
+*** New major mode 'css-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+CSS (Cascading Style Sheets).
+
++++
+*** New major mode 'json-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the JSON language.
+
++++
+*** New major mode 'csharp-ts-mode'.
+An optional major mode based on the tree-sitter library for editing
+programs in the C# language.
+
++++
+*** New major mode 'bash-ts-mode'.
+Am optional major mode based on the tree-sitter library for editing
+Bash shell scripts.
+
++++
+*** New major mode 'dockerfile-ts-mode'.
+A major mode based on the tree-sitter library for editing
+Dockerfiles. This mode is auto-enabled for files which are named
+"Dockerfile", have the "Dockerfile." prefix, or have the ".dockerfile"
+extension.
+
++++
+*** New major mode 'cmake-ts-mode'.
+A major mode based on the tree-sitter library for editing CMake files.
+It is auto-enabled for files whose name is "CMakeLists.txt" or whose
+extension is ".cmake".
+
++++
+*** New major mode 'toml-ts-mode'.
+A major mode based on the tree-sitter library for editing files
+written in TOML, a format for writing configuration files. It is
+auto-enabled for files with the ".toml" extension.
+
++++
+*** New major mode 'go-ts-mode'.
+A major mode based on the tree-sitter library for editing programs in
+the Go language. It is auto-enabled for files with the ".go" extension.
+
++++
+*** New major mode 'go-mod-ts-mode'.
+A major mode based on the tree-sitter library for editing "go.mod"
+files. It is auto-enabled for files which are named "go.mod".
+
++++
+*** New major mode 'yaml-ts-mode'.
+A major mode based on the tree-sitter library for editing files
+written in YAML. It is auto-enabled for files with the ".yaml" or
+".yml" extensions.
+
++++
+*** New major mode 'rust-ts-mode'.
+A major mode based on the tree-sitter library for editing programs in
+the Rust language. It is auto-enabled for files with the ".rs" extension.
+
+
+* Incompatible Lisp Changes in Emacs 29.1
+
++++
+** The implementation of overlays has changed.
+Emacs now uses an implementation of overlays that is much more
+efficient than the original one, and should speed up all the
+operations that involve overlays, especially when there are lots of
+them in a buffer.
+
+As result of this, some minor incompatibilities in behavior could be
+observed, as described below. Except those minor incompatibilities,
+no other changes in behavior of overlays should be visible on the Lisp
+or user level, with the exception of better performance and the order
+of overlays returned by functions that don't promise any particular
+order.
+
+---
+*** The function 'overlay-recenter' is now a no-op.
+This function does nothing, and in particular has no effect on the
+value returned by 'overlay-lists'. The purpose of 'overlay-recenter'
+was to allow more efficient lookup of overlays around a certain buffer
+position; however with the new implementation the lookup of overlays
+is efficient regardless of their position, and there's no longer any
+need to "optimize" the lookup, nor any notion of a "center" of the
+overlays.
+
+---
+*** The function 'overlay-lists' returns one unified list of overlays.
+This function used to return a cons of two lists, one with overlays
+before the "center" position, the other after that "center". It now
+returns a list whose 'car' is the list of all the buffer overlays, and
+whose 'cdr' is always nil.
+
++++
+** 'format-prompt' now uses 'substitute-command-keys'.
+This means that both the prompt and 'minibuffer-default-prompt-format'
+will have key definitions and single quotes handled specially.
+
++++
+** New function 'substitute-quotes'.
+This function works like 'substitute-command-keys' but only
+substitutes quote characters.
+
+---
+** 'find-image' now uses 'create-image'.
+This means that images found through 'find-image' also have
+auto-scaling applied. (This only makes a difference on HiDPI
+displays.)
+
++++
+** Changes in how "raw" in-memory xbm images are specified.
+Some years back Emacs gained the ability to scale images, and you
+could then specify ':width' and ':height' when using 'create-image' on all
+image types -- except xbm images, because this format already used the
+':width' and ':height' arguments to specify the width/height of the "raw"
+in-memory format. This meant that if you used these specifications
+on, for instance, xbm files, Emacs would refuse to display them. This
+has been changed, and ':width'/':height' now works as with all other image
+formats, and the way to specify the width/height of the "raw"
+in-memory format is now by using ':data-width' and ':data-height'.
+
++++
+** "loaddefs.el" generation has been reimplemented.
+The various "loaddefs.el" files in the Emacs tree (which contain
+information about autoloads, built-in packages and package prefixes)
+used to be generated by functions in autoloads.el. These are now
+generated by loaddefs-gen.el instead. This leads to functionally
+equivalent "loaddef.el" files, but they do not use exactly the same
+syntax, so using 'M-x update-file-autoloads' no longer works. (This
+didn't work well in most files in the past, either, but it will now
+signal an error in any file.)
+
+In addition, files are scanned in a slightly different way.
+Previously, ';;;###' specs inside a top-level form (i.e., something
+like '(when ... ;;;### ...)' would be ignored. They are now parsed as
+usual.
+
+---
+** Themes have special autoload cookies.
+All built-in themes are scraped for ';;;###theme-autoload' cookies
+that are loaded along with the regular auto-loaded code.
+
++++
+** 'buffer-modified-p' has been extended.
+This function was previously documented to return only nil or t. This
+has been changed to nil/'autosaved'/non-nil. The new 'autosaved'
+value means that the buffer is modified, but that it hasn't been
+modified since the time of last auto-save.
+
+---
+** 'with-silent-modifications' also restores buffer autosave status.
+'with-silent-modifications' is a macro meant to be used by the font
+locking machinery to allow applying text properties without changing
+the modification status of the buffer. However, it didn't restore the
+buffer autosave status, so applying font locking to a modified buffer
+that had already been auto-saved would trigger another auto-saving.
+This is no longer the case.
+
+---
+** 'prin1' doesn't always escape "." and "?" in symbols any more.
+Previously, symbols like 'foo.bar' would be printed by 'prin1' as
+"foo\.bar". This now prints as "foo.bar" instead. The Emacs Lisp
+reader interprets these strings as referring to the same symbol, so
+this is virtually always backwards-compatible, but there may
+theoretically be code out there that expects a specific printed
+representation.
+
+The same is the case with the "?" character: The 'foo?' symbol is now
+printed as "foo?" instead of "foo\?".
+
+If the "." and "?" characters are the first character in the symbol,
+they will still be escaped, so the '.foo' symbol is still printed as
+"\.foo" and the '?bar' symbol is still printed as "\?bar".
+
++++
+** Remapping 'mode-line' face no longer works as expected.
+'mode-line' is now the parent face of the new 'mode-line-active' face,
+and remapping parent of basic faces does not work reliably.
+Instead of remapping 'mode-line', you have to remap 'mode-line-active'.
+
++++
+** 'make-process' has been extended to support ptys when ':stderr' is set.
+Previously, setting ':stderr' to a non-nil value would force the
+process's connection to use pipes. Now, Emacs will use a pty for
+stdin and stdout if requested no matter the value of ':stderr'.
+
+---
+** User option 'mail-source-ignore-errors' is now obsolete.
+The whole mechanism for prompting users to continue in case of
+mail-source errors has been removed, so this option is no longer
+needed.
+
+** Fonts
+
+---
+*** Emacs now supports 'medium' fonts.
+Emacs previously didn't distinguish between the 'regular'/'normal'
+weight and the 'medium' weight, but it now also supports the (heavier)
+'medium' weight. However, this means that if you specify a weight of
+'normal' and the font doesn't have this weight, Emacs won't find the
+font spec. In these cases, replacing ":weight 'normal" with ":weight
+'medium" should fix the issue.
+
+---
+** Keymap descriptions have changed.
+'help--describe-command', 'C-h b' and associated functions that output
+keymap descriptions have changed. In particular, prefix commands are
+not output at all, and instead of "??" for closures/functions,
+"[closure]"/"[lambda]" is output.
+
+---
+** 'downcase' details have changed slightly.
+In certain locales, changing the case of an ASCII-range character may
+turn it into a multibyte character, most notably with "I" in Turkish
+(the lowercase is "ı", 0x0131). Previously, 'downcase' on a unibyte
+string was buggy, and would mistakenly just return the lower byte of
+this, 0x31 (the digit "1"). 'downcase' on a unibyte string has now
+been changed to downcase such characters as if they were ASCII. To
+get proper locale-dependent downcasing, the string has to be converted
+to multibyte first. (This goes for the other case-changing functions,
+too.)
+
+---
+** Functions in 'tramp-foreign-file-name-handler-alist' have changed.
+Functions to determine which Tramp file name handler to use are now
+passed a file name in dissected form (via 'tramp-dissect-file-name')
+instead of in string form.
+
+---
+** 'def' indentation changes.
+In 'emacs-lisp-mode', forms with a symbol with a name that start with
+"def" have been automatically indented as if they were 'defun'-like
+forms, for instance:
+
+ (defzot 1
+ 2 3)
+
+This heuristic has now been removed, and all functions/macros that
+want to be indented this way have to be marked with
+
+ (declare (indent defun))
+
+or the like. If the function/macro definition itself can't be
+changed, the indentation can also be adjusted by saying something
+like:
+
+ (put 'defzot 'lisp-indent-function 'defun)
+
+---
+** The 'inhibit-changing-match-data' variable is now obsolete.
+Instead, functions like 'string-match' and 'looking-at' now take an
+optional INHIBIT-MODIFY argument.
+
+---
+** 'gnus-define-keys' is now obsolete.
+Use 'define-keymap' instead.
+
+---
+** MozRepl has been removed from js.el.
+MozRepl was removed from Firefox in 2017, so this code doesn't work
+with recent versions of Firefox.
+
+---
+** The function 'image-dired-get-exif-data' is now obsolete.
+Use 'exif-parse-file' and 'exif-field' instead.
+
+---
+** 'insert-directory' alternatives should not change the free disk space line.
+This change is now applied in 'dired-insert-directory'.
+
+---
+** 'compilation-last-buffer' is (finally) declared obsolete.
+It's been obsolete since Emacs-22.1, actually.
+
+---
+** Calling 'lsh' now elicits a byte-compiler warning.
+'lsh' behaves in somewhat surprising and platform-dependent ways for
+negative arguments, and is generally slower than 'ash', which should be
+used instead. This warning can be suppressed by surrounding calls to
+'lsh' with the construct '(with-suppressed-warnings ((suspicious lsh)) ...)',
+but switching to 'ash' is generally much preferable.
+
+---
+** Some functions and variables obsolete since Emacs 24 have been removed:
+'Buffer-menu-buffer+size-width', 'Electric-buffer-menu-mode',
+'Info-edit-map', 'allout-abbreviate-flattened-numbering',
+'allout-exposure-change-hook', 'allout-mode-deactivate-hook',
+'allout-structure-added-hook', 'allout-structure-deleted-hook',
+'allout-structure-shifted-hook', 'ansi-color-unfontify-region',
+'archive-extract-hooks', 'auth-source-forget-user-or-password',
+'auth-source-hide-passwords', 'auth-source-user-or-password',
+'automatic-hscrolling', 'automount-dir-prefix', 'bibtex-complete',
+'bibtex-entry-field-alist', 'buffer-has-markers-at',
+'buffer-substring-filters', 'byte-compile-disable-print-circle',
+'c-prepare-bug-report-hooks', 'cfengine-mode-abbrevs',
+'change-log-acknowledgement', 'chart-map',
+'checkdoc-comment-style-hooks', 'comint--unquote&expand-filename',
+'comint-dynamic-complete', 'comint-dynamic-complete-as-filename',
+'comint-dynamic-simple-complete', 'comint-unquote-filename',
+'command-history-map', 'compilation-parse-errors-function',
+'completion-annotate-function', 'condition-case-no-debug',
+'count-lines-region', 'crisp-mode-modeline-string',
+'custom-print-functions', 'custom-print-functions',
+'cvs-string-prefix-p', 'data-debug-map', 'deferred-action-function',
+'deferred-action-list', 'dired-pop-to-buffer', 'dired-shrink-to-fit',
+'dired-sort-set-modeline', 'dired-x-submit-report',
+'display-buffer-function',
+'ediff-choose-window-setup-function-automatically',
+'eieio-defgeneric', 'eieio-defmethod', 'emacs-lock-from-exiting',
+'erc-complete-word', 'erc-dcc-chat-filter-hook',
+'eshell-add-to-window-buffer-names', 'eshell-cmpl-suffix-list',
+'eshell-for', 'eshell-remove-from-window-buffer-names',
+'eshell-status-in-modeline', 'filesets-cache-fill-content-hooks',
+'font-list-limit', 'font-lock-maximum-size',
+'font-lock-reference-face', 'gnus-carpal',
+'gnus-debug-exclude-variables', 'gnus-debug-files',
+'gnus-local-domain', 'gnus-outgoing-message-group',
+'gnus-registry-user-format-function-M', 'gnus-secondary-servers',
+'gnus-subscribe-newsgroup-hooks', 'gud-inhibit-global-bindings',
+'hangul-input-method-inactivate', 'hfy-post-html-hooks',
+'image-extension-data', 'image-library-alist',
+'inactivate-current-input-method-function', 'inactivate-input-method',
+'inhibit-first-line-modes-regexps',
+'inhibit-first-line-modes-suffixes', 'input-method-inactivate-hook',
+'intdos', 'javascript-generic-mode', 'javascript-generic-mode-hook',
+'latex-string-prefix-p', 'macro-declaration-function' (function),
+'macro-declaration-function' (variable), 'mail-complete-function',
+'mail-completion-at-point-function',
+'mail-mailer-swallows-blank-line', 'mail-sent-via', 'make-register',
+'makefile-complete', 'menu-bar-kill-ring-save',
+'meta-complete-symbol', 'meta-mode-map',
+'mh-kill-folder-suppress-prompt-hooks',
+'minibuffer-completing-symbol',
+'minibuffer-local-filename-must-match-map', 'mode25', 'mode4350',
+'mpc-string-prefix-p', 'msb-after-load-hooks',
+'nndiary-request-accept-article-hooks',
+'nndiary-request-create-group-hooks',
+'nndiary-request-update-info-hooks', 'nnimap-split-rule',
+'nntp-authinfo-file', 'ns-alternatives-map',
+'ns-store-cut-buffer-internal', 'package-menu-view-commentary',
+'pascal-last-completions', 'pascal-show-completions',
+'pascal-toggle-completions', 'pcomplete-arg-quote-list',
+'pcomplete-quote-argument', 'prolog-char-quote-workaround',
+'python-buffer', 'python-guess-indent', 'python-indent',
+'python-info-ppss-comment-or-string-p', 'python-info-ppss-context',
+'python-info-ppss-context-type', 'python-preoutput-result',
+'python-proc', 'python-send-receive', 'python-send-string',
+'python-use-skeletons', 'quail-inactivate', 'quail-inactivate-hook',
+'query-replace-interactive', 'rcirc-activity-hooks',
+'rcirc-print-hooks', 'rcirc-receive-message-hooks',
+'rcirc-sentinel-hooks', 'read-filename-at-point', 'redraw-modeline',
+'reftex-index-map', 'reftex-index-phrases-map',
+'reftex-select-bib-map', 'reftex-select-label-map', 'reftex-toc-map',
+'register-name-alist', 'register-value', 'report-emacs-bug-info',
+'report-emacs-bug-pretest-address',
+'rmail-default-dont-reply-to-names', 'rmail-dont-reply-to',
+'rmail-dont-reply-to-names', 'robin-inactivate',
+'robin-inactivate-hook', 'rst-block-face', 'rst-comment-face',
+'rst-definition-face', 'rst-directive-face', 'rst-emphasis1-face',
+'rst-emphasis2-face', 'rst-external-face', 'rst-literal-face',
+'rst-reference-face', 'semantic-change-hooks',
+'semantic-edits-delete-change-hooks',
+'semantic-edits-new-change-hooks',
+'semantic-edits-reparse-change-hooks', 'semantic-grammar-map',
+'semantic-grammar-syntax-table', 'semantic-lex-reset-hooks',
+'semanticdb-elisp-sym-function-arglist',
+'semanticdb-save-database-hooks', 'set-face-underline-p',
+'set-register-value', 'sh-maybe-here-document', 'speedbar-key-map',
+'speedbar-syntax-table', 'starttls-any-program-available',
+'strokes-modeline-string', 'strokes-report-bug',
+'term-default-bg-color', 'term-default-fg-color',
+'tex-string-prefix-p', 'timeclock-modeline-display',
+'timeclock-modeline-display', 'timeclock-update-modeline',
+'toggle-emacs-lock', 'tooltip-use-echo-area', 'turn-on-cwarn-mode',
+'turn-on-iimage-mode', 'ucs-input-inactivate', 'ucs-insert',
+'url-recreate-url-attributes', 'user-variable-p',
+'vc-string-prefix-p', 'vc-toggle-read-only', 'view-return-to-alist',
+'view-return-to-alist-update', 'w32-default-color-map' (function),
+'which-func-mode' (function), 'window-system-version',
+'winner-mode-leave-hook', 'x-cut-buffer-or-selection-value'.
+
+---
+** Some functions and variables obsolete since Emacs 23 have been removed:
+'find-emacs-lisp-shadows', 'newsticker-cache-filename',
+'process-filter-multibyte-p', 'redisplay-end-trigger-functions',
+'set-process-filter-multibyte', 'set-window-redisplay-end-trigger',
+'unify-8859-on-decoding-mode', 'unify-8859-on-encoding-mode',
+'vc-arch-command', 'window-redisplay-end-trigger', 'x-selection'.
+
+---
+** Some functions and variables obsolete since Emacs 21 or 22 have been removed:
+'c-toggle-auto-state', 'find-file-not-found-hooks',
+'ls-lisp-dired-ignore-case', 'query-replace-regexp-eval'.
+
++++
+** New generic function 'function-documentation'.
+It can dynamically generate a raw docstring depending on the type of a
+function. Used mainly for docstrings of OClosures.
+
++++
+** Base64 encoding no longer tolerates latin-1 input.
+The functions 'base64-encode-string', 'base64url-encode-string',
+'base64-encode-region' and 'base64url-encode-region' no longer accept
+characters in the range U+0080..U+00FF as substitutes for single bytes
+in the range 128..255, but signal an error for all multibyte characters.
+The input must be unibyte encoded text.
+
++++
+** The 'clone-indirect-buffer-hook' is now run by 'make-indirect-buffer'.
+It was previously only run by 'clone-indirect-buffer' and
+'clone-indirect-buffer-other-window'. Since 'make-indirect-buffer' is
+called by both of these, the hook is now run by all 3 of these
+functions.
+
+---
+** '?\' at the end of a line now signals an error.
+Previously, it produced a nonsense value, -1, that was never intended.
+
+---
+** Some libraries obsolete since Emacs 24.1 and 24.3 have been removed:
+abbrevlist.el, assoc.el, complete.el, cust-print.el,
+erc-hecomplete.el, mailpost.el, mouse-sel.el, old-emacs-lock.el,
+patcomp.el, pc-mode.el, pc-select.el, s-region.el, and sregex.el.
+
++++
+** Many seldom-used generalized variables have been made obsolete.
+Emacs has a number of rather obscure generalized variables defined,
+that, for instance, allowed you to say things like:
+
+ (setf (point-min) 4)
+
+These never caught on and have been made obsolete. The form above,
+for instance, is the same as saying
+
+ (narrow-to-region 4 (point-max))
+
+The following generalized variables have been made obsolete:
+'buffer-file-name', 'buffer-local-value', 'buffer-modified-p',
+'buffer-name', 'buffer-string', 'buffer-substring', 'current-buffer',
+'current-column', 'current-global-map', 'current-input-mode',
+'current-local-map', 'current-window-configuration',
+'default-file-modes', 'documentation-property', 'eq', 'frame-height',
+'frame-width', 'frame-visible-p', 'global-key-binding',
+'local-key-binding', 'mark', 'mark-marker', 'marker-position',
+'mouse-position', 'point', 'point-marker', 'point-max', 'point-min',
+'read-mouse-position', 'screen-height', 'screen-width',
+'selected-frame', 'selected-screen', 'selected-window',
+'standard-case-table', 'syntax-table', 'visited-file-modtime',
+'window-height', 'window-width', and 'x-get-secondary-selection'.
+
+
+* Lisp Changes in Emacs 29.1
+
++++
+** Interpreted closures are "safe for space".
+As was already the case for byte-compiled closures, instead of capturing
+the whole current lexical environment, interpreted closures now only
+capture the part of the environment that they need.
+The previous behavior could occasionally lead to memory leaks or
+to problems where a printed closure would not be 'read'able because
+of an un'read'able value in an unrelated lexical variable.
+
++++
+** New accessor function 'file-attribute-file-identifier'.
+It returns the list of the inode number and device identifier
+retrieved by 'file-attributes'. This value can be used to identify a
+file uniquely. The device identifier can be a single number or (for
+remote files) a cons of 2 numbers.
+
++++
+** New macro 'while-let'.
+This is like 'when-let', but repeats until a binding form is nil.
+
++++
+** New function 'make-obsolete-generalized-variable'.
+This can be used to mark setters used by 'setf' as obsolete, and the
+byte-compiler will then warn about using them.
+
++++
+** New functions 'pos-eol' and 'pos-bol'.
+These are like 'line-end-position' and 'line-beginning-position'
+(respectively), but ignore fields (and are more efficient).
+
++++
+** New function 'compiled-function-p'.
+This returns non-nil if its argument is either a built-in, or a
+byte-compiled, or a natively-compiled function object, or a function
+loaded from a dynamic module.
+
+---
+** 'deactivate-mark' can have new value 'dont-save'.
+This value means that Emacs should deactivate the mark as usual, but
+without setting the primary selection, if 'select-active-regions' is
+enabled.
+
++++
+** New 'declare' form 'interactive-args'.
+This can be used to specify what forms to put into 'command-history'
+when executing commands interactively.
+
++++
+** The FORM arg of 'time-convert' is mandatory.
+'time-convert' can still be called without it, as before, but the
+compiler now emits a warning about this deprecated usage.
+
++++
+** Emacs now supports user-customizable and themable icons.
+These can be used for buttons in buffers and the like. See the
+"(elisp) Icons" and "(emacs) Icons" nodes in the manuals for details.
+
++++
+** New arguments MESSAGE and TIMEOUT of 'set-transient-map'.
+MESSAGE specifies a message to display after activating the transient
+map, including a special formatting spec to list available keys.
+TIMEOUT is the idle time after which to deactivate the transient map.
+The default timeout value can be defined by the new variable
+'set-transient-map-timeout'.
+
+** Connection-local variables
+
++++
+*** Some connection-local variables are now user options.
+The variables 'connection-local-profile-alist' and
+'connection-local-criteria-alist' are now user options, in order to
+make it more convenient to inspect and modify them.
+
++++
+*** New function 'connection-local-update-profile-variables'.
+This function allows to modify the settings of an existing
+connection-local profile.
+
++++
+*** New macro 'with-connection-local-application-variables'.
+This macro works like 'with-connection-local-variables', but it allows
+to use another application but 'tramp'. This is useful when running
+code in a buffer where Tramp has already set some connection-local
+variables.
+
++++
+*** New macro 'setq-connection-local'.
+This allows dynamically setting variable values for a particular
+connection within the body of 'with-connection-local-{application-}variables'.
+See the "(elisp) Connection Local Variables" node in the Lisp
+Reference manual for more information.
+
++++
+** 'plist-get', 'plist-put' and 'plist-member' are no longer limited to 'eq'.
+These function now take an optional comparison predicate argument.
+
++++
+** 'read-multiple-choice' can now use long-form answers.
+
++++
+** 'M-c' in 'read-regexp' now toggles case folding.
+
++++
+** 'completing-read' now allows a function as its REQUIRE-MATCH argument.
+This function is called to see whether what the user has typed is a
+match. This is also available from functions that call
+'completing-read', like 'read-file-name'.
+
++++
+** 'posn-col-row' can now give position data based on windows.
+Previously, it reported data only based on the frame.
+
++++
+** 'file-expand-wildcards' can now also take a regexp as PATTERN argument.
+
+---
+** vc-mtn (the VC backend for Monotone) has been made obsolete.
+
++++
+** 'gui-set-selection' can specify different values for different data types.
+If DATA is a string, then its text properties are searched for values
+for each specific data type while the selection is being converted.
+
+---
+** New eldoc function 'elisp-eldoc-var-docstring-with-value'.
+This function includes the current value of the variable in eldoc display
+and can be used as a more detailed alternative to 'elisp-eldoc-var-docstring'.
+
++++
+** 'save-some-buffers' can now be extended to save other things.
+Traditionally, 'save-some-buffers' saved buffers, and also saved
+abbrevs. This has been generalized via the
+'save-some-buffers-functions' variable, and packages can now register
+things to be saved.
+
++++
+** New function 'string-equal-ignore-case'.
+This compares strings ignoring case differences.
+
++++
+** 'symbol-file' can now report natively-compiled ".eln" files.
+If Emacs was built with native-compilation enabled, Lisp programs can
+now call 'symbol-file' with the new optional 3rd argument non-nil to
+request the name of the ".eln" file which defined a given symbol.
+
++++
+** New macro 'with-memoization' provides a very primitive form of memoization.
+
++++
+** 'max-char' can now report the maximum codepoint according to Unicode.
+When called with a new optional argument UNICODE non-nil, 'max-char'
+will now report the maximum valid codepoint defined by the Unicode
+Standard.
+
+** seq
+
++++
+** New function 'seq-split'.
+This returns a list of sub-sequences of the specified sequence.
+
++++
+** New function 'seq-remove-at-position'.
+This function returns a copy of the specified sequence where the
+element at a given (zero-based) index got removed.
+
++++
+** New function 'seq-positions'.
+This returns a list of the (zero-based) indices of elements matching a
+given predicate in the specified sequence.
+
++++
+** New function 'seq-keep'.
+This is like 'seq-map', but removes all nil results from the returned
+list.
+
+** Themes
+
+---
+*** New hooks 'enable-theme-functions' and 'disable-theme-functions'.
+These are run after enabling and disabling a theme, respectively.
+
+---
+*** Themes can now be made obsolete.
+Using 'make-obsolete' on a theme is now supported. This will make
+'load-theme' issue a warning when loading the theme.
+
++++
+** New hook 'display-monitors-changed-functions'.
+It is called whenever the configuration of different monitors on a
+display changes.
+
++++
+** 'prin1' and 'prin1-to-string' now take an optional OVERRIDES parameter.
+This parameter can be used to override values of print-related settings.
+
++++
+** New minor mode 'header-line-indent-mode'.
+This is meant to be used in modes that have a header line that should
+be kept aligned with the buffer contents when the user switches
+'display-line-numbers-mode' on or off.
+
++++
+** New minor mode 'lost-selection-mode'.
+This minor mode makes Emacs deactivate the mark in all buffers when
+the primary selection is obtained by another program.
+
+---
+** On X, Emacs will try to preserve selection ownership when a frame is deleted.
+This means that if you make Emacs the owner of a selection, such as by
+selecting some text into the clipboard or primary selection, and then
+delete the current frame, you will still be able to insert the
+contents of that selection into other programs as long as another
+frame is open on the same display. This behavior can be disabled by
+setting the user option 'x-auto-preserve-selections' to nil.
+
++++
+** New predicate 'char-uppercase-p'.
+This returns non-nil if its argument its an uppercase character.
+
+** Byte compilation
+
+---
+*** Byte compilation will now warn about some quoting mistakes in docstrings.
+When writing code snippets that contains the "'" character (APOSTROPHE),
+that quote character has to be escaped to avoid Emacs displaying it as
+"’" (LEFT SINGLE QUOTATION MARK), which would make code examples like
+
+ (setq foo '(1 2 3))
+
+invalid. Emacs will now warn during byte compilation if it seems
+something like that, and also warn about when using RIGHT/LEFT SINGLE
+QUOTATION MARK directly. In both these cases, if these characters
+should really be present in the docstring, they should be quoted with
+"\=".
+
+---
+*** Byte compilation will now warn about some malformed 'defcustom' types.
+It's very common to write 'defcustom' types on the form:
+
+ :type '(choice (const :tag "foo" 'bar))
+
+I.e., double-quoting the 'bar', which is almost never the correct
+value. The byte compiler will now issue a warning if it encounters
+these forms.
+
++++
+** 'restore-buffer-modified-p' can now alter buffer auto-save state.
+With a FLAG value of 'autosaved', it will mark the buffer as having
+been auto-saved since the time of last modification.
+
+---
+** New minor mode 'isearch-fold-quotes-mode'.
+This sets up 'search-default-mode' so that quote characters are
+char-folded into each other. It is used, by default, in "*Help*" and
+"*info*" buffers.
+
++++
+** New macro 'buffer-local-set-state'.
+This is a helper macro to be used by minor modes that wish to restore
+buffer-local variables back to their original states when the mode is
+switched off.
+
+---
+** New macro 'with-buffer-unmodified-if-unchanged'.
+If the buffer is marked as unmodified, and code does modifications
+that, in total, means that the buffer is identical to the buffer
+before, mark the buffer as unmodified again.
+
+---
+** New function 'malloc-trim'.
+This function allows returning unused memory back to the operating
+system, and is mainly meant as a debugging tool. It is currently
+available only when Emacs was built with glibc as the C library.
+
+---
+** 'x-show-tip' no longer hard-codes a timeout default.
+The new variable 'x-show-tooltip-timeout' allows the user to alter
+this for packages that don't use 'tooltip-show', but instead call the
+lower level function directly.
+
+---
+** New function 'current-cpu-time'.
+It gives access to the CPU time used by the Emacs process, for
+example for benchmarking purposes.
+
+---
+** New function 'string-edit'.
+This is meant to be used when the user has to edit a (potentially)
+long string. It pops up a new buffer where you can edit the string,
+and a callback is called when the user types 'C-c C-c'.
+
++++
+** New function 'read-string-from-buffer'.
+This is a modal version of 'string-edit', and can be used as an
+alternative to 'read-string'.
+
++++
+** The return value of 'clear-message-function' is not ignored anymore.
+If the function returns 'dont-clear-message', then the message is not
+cleared, with the assumption that the function cleared it itself.
+
++++
+** The local variables section now supports defining fallback modes.
+This was previously only available when using a property line (i.e.,
+putting the modes on the first line of a file).
+
++++
+** New function 'flush-standard-output'.
+This enables display of lines that don't end in a newline from
+batch-based Emacs scripts.
+
++++
+** New convenience function 'buttonize-region'.
+This works like 'buttonize', but for a region instead of a string.
+
++++
+** 'macroexp-let2*' can omit TEST arg and use single-var bindings.
+
++++
+** New macro-writing macros, 'cl-with-gensyms' and 'cl-once-only'.
+See the "(cl) Macro-Writing Macros" manual section for descriptions.
+
++++
+** New variable 'last-event-device' and new function 'device-class'.
+On X Windows, 'last-event-device' specifies the input extension device
+from which the last input event originated, and 'device-class' can be
+used to determine the type of an input device.
+
++++
+** 'track-mouse' can have a new value 'drag-source'.
+This means the same as 'dropping', but modifies the mouse position
+list in reported motion events if there is no frame underneath the
+mouse pointer.
+
++++
+** New functions for dragging items from Emacs to other programs.
+The new functions 'x-begin-drag', 'dnd-begin-file-drag',
+'dnd-begin-drag-files', and 'dnd-direct-save' allow dragging contents
+(such as files and text) from Emacs to other programs.
+
+---
+** New function 'ietf-drums-parse-date-string'.
+This function parses RFC5322 (and RFC822) date strings, and should be
+used instead of 'parse-time-string' when parsing data that's standards
+compliant.
+
++++
+** New macro 'setopt'.
+This is like 'setq', but is meant to be used for user options instead
+of plain variables, and uses 'custom-set'/'set-default' to set them.
+
++++
+** New utility predicate 'mode-line-window-selected-p'.
+This is meant to be used from ':eval' mode line constructs to create
+different mode line looks for selected and unselected windows.
+
++++
+** New variable 'messages-buffer-name'.
+This variable (defaulting to "*Messages*") allows packages to override
+where messages are logged.
+
++++
+** New function 'readablep'.
+This function says whether an object can be written out and then
+read back by the Emacs Lisp reader.
+
++++
+** New variable 'print-unreadable-function'.
+This variable allows changing how Emacs prints unreadable objects.
+
+---
+** The user option 'polling-period' now accepts floating point values.
+This means Emacs can now poll for input during Lisp execution more
+frequently than once in a second.
+
+---
+** New function 'bidi-string-strip-control-characters'.
+This utility function is meant for displaying strings when it's
+essential that there's no bidirectional context. It removes all the
+bidirectional formatting control characters (such as RLM, LRO, PDF,
+etc.) from its argument string. The characters it removes are listed
+in the value of 'bidi-control-characters'.
+
+---
+** The Gnus range functions have been moved to a new library, range.el.
+All the old names have been made obsolete.
+
++++
+** New function 'function-alias-p'.
+This predicate says whether an object is a function alias, and if it
+is, the alias chain is returned.
+
++++
+** New variable 'lisp-directory' holds the directory of Emacs's own Lisp files.
+
++++
+** New facility for handling session state: 'multisession-value'.
+This can be used as a convenient way to store (simple) application
+state, and the command 'list-multisession-values' allows users to list
+(and edit) this data.
+
++++
+** New function 'get-display-property'.
+This is like 'get-text-property', but works on the 'display' text
+property.
+
++++
+** New function 'add-display-text-property'.
+This is like 'put-text-property', but works on the 'display' text
+property.
+
++++
+** New 'min-width' 'display' property.
+This allows setting a minimum display width for a region of text.
+
++++
+** New 'cursor-face' text property.
+This uses 'cursor-face' instead of the default face when cursor is on or
+near the character and 'cursor-face-highlight-mode' is enabled. The
+user option 'cursor-face-highlight-nonselected-window' is similar to
+'highlight-nonselected-windows', but for this property.
+
++++
+** New event type 'touch-end'.
+This event is sent whenever the user's finger moves off the mouse
+wheel on some mice, or when the user's finger moves off the touchpad.
+
++++
+** New event type 'pinch'.
+This event is sent when a user performs a pinch gesture on a touchpad,
+which is comprised of placing two fingers on the touchpad and moving
+them towards or away from each other.
+
++++
+** New hook 'x-pre-popup-menu-hook'.
+This hook is run before 'x-popup-menu' is about to display a
+deck-of-cards menu on screen.
+
+---
+** New hook 'post-select-region-hook'.
+This hook is run immediately after 'select-active-regions' causes the
+region to be set as the primary selection.
+
++++
+** New function 'buffer-match-p'.
+Check if a buffer satisfies some condition. Some examples for
+conditions can be regular expressions that match a buffer name, a
+cons-cell like '(major-mode . shell-mode)' that matches any buffer
+where 'major-mode' is 'shell-mode' or a combined with a condition like
+'(and "\\`\\*.+\\*\\'" (major-mode . special-mode))'.
+
++++
+** New function 'match-buffers'.
+Use 'buffer-match-p' to gather a list of buffers that match a
+condition.
+
+---
+** New optional arguments 'text-face' and 'default-face' for 'tooltip-show'.
+They allow changing the faces used for the tooltip text and frame
+colors of the resulting tooltip frame from the default 'tooltip' face.
+
+** Text security and suspiciousness
+
++++
+*** New library textsec.el.
+This library contains a number of checks for whether a string is
+"suspicious". This usually means that the string contains characters
+that have glyphs that can be confused with other, more commonly used
+glyphs, or contain bidirectional (or other) formatting characters that
+may be used to confuse a user.
+
++++
+*** New user option 'textsec-check'.
+If non-nil (which is the default), Emacs packages that are vulnerable
+to attackers trying to confuse the users will use the textsec library
+to mark suspicious text. For instance shr/eww will mark suspicious
+URLs and links, Gnus will mark suspicious From addresses, and
+Message mode will query the user if the user is sending mail to a
+suspicious address. If this variable is nil, these checks are
+disabled.
+
++++
+*** New function 'textsec-suspicious-p'.
+This is the main function Emacs applications should be using to check
+whether a string is suspicious. It heeds the 'textsec-check' user
+option.
+
+** Keymaps and key definitions
+
++++
+*** 'where-is-internal' can now filter events marked as non key events.
+If a command maps to a key binding like '[some-event]', and 'some-event'
+has a symbol plist containing a non-nil 'non-key-event' property, then
+that binding is ignored by 'where-is-internal'.
+
++++
+*** New functions for defining and manipulating keystrokes.
+These all take the syntax defined by 'key-valid-p'. None of the older
+functions have been deprecated or altered, but they are now
+de-emphasized in the documentation.
+
++++
+*** Use 'keymap-set' instead of 'define-key'.
+
++++
+*** Use 'keymap-global-set' instead of 'global-set-key'.
+
++++
+*** Use 'keymap-local-set' instead of 'local-set-key'.
+
++++
+*** Use 'keymap-global-unset' instead of 'global-unset-key'.
+
++++
+*** Use 'keymap-local-unset' instead of 'local-unset-key'.
+
++++
+*** Use 'keymap-substitute' instead of 'substitute-key-definition'.
+
++++
+*** Use 'keymap-set-after' instead of 'define-key-after'.
+
++++
+*** Use 'keymap-lookup' instead of 'lookup-keymap' and 'key-binding'.
+
++++
+*** Use 'keymap-local-lookup' instead of 'local-key-binding'.
+
++++
+*** Use 'keymap-global-lookup' instead of 'global-key-binding'.
+
++++
+*** 'define-key' now takes an optional REMOVE argument.
+If non-nil, remove the definition from the keymap. This is subtly
+different from setting a definition to nil (when the keymap has a
+parent).
+
++++
+*** 'read-multiple-choice' now takes an optional SHOW-HELP argument.
+If non-nil, show the help buffer immediately, before any user input.
+
++++
+*** New function 'key-valid-p'.
+The 'kbd' function is quite permissive, and will try to return
+something usable even if the syntax of the argument isn't completely
+correct. The 'key-valid-p' predicate does a stricter check of the
+syntax.
+
+---
+*** New function 'key-parse'.
+This is like 'kbd', but only returns vectors instead of a mix of
+vectors and strings.
+
++++
+*** New ':type' for 'defcustom' for keys.
+The new 'key' type can be used for options that should be a valid key
+according to 'key-valid-p'. The type 'key-sequence' is now obsolete.
+
++++
+** New substitution in docstrings and 'substitute-command-keys'.
+Use \\`KEYSEQ' to insert a literal key sequence "KEYSEQ" (for example
+\\`C-k') in a docstring or when calling 'substitute-command-keys',
+which will use the same face as a command substitution. This should
+be used only when a key sequence has no corresponding command, for
+example when it is read directly with 'read-key-sequence'. It must be
+a valid key sequence according to 'key-valid-p'.
+
++++
+** New function 'file-name-split'.
+This returns a list of all the components of a file name.
+
++++
+** New function 'file-name-parent-directory'.
+This returns the parent directory of a file name.
+
++++
+** New macro 'with-undo-amalgamate'.
+It records a particular sequence of operations as a single undo step.
+
++++
+** New command 'yank-media'.
+This command supports yanking non-plain-text media like images and
+HTML from other applications into Emacs. It is only supported in
+modes that have registered support for it, and only on capable
+platforms.
+
++++
+** New command 'yank-media-types'.
+This command lets you examine all data in the current selection and
+the clipboard, and insert it into the buffer.
+
++++
+** New variable 'yank-transform-functions'.
+This variable allows the user to alter the string to be inserted.
+
+---
+** New command 'yank-in-context'.
+This command tries to preserve string/comment syntax when yanking.
+
+---
+** New function 'minibuffer-lazy-highlight-setup'.
+This function allows setting up the minibuffer so that lazy
+highlighting of its content is applied in the original window.
+
++++
+** New text property 'inhibit-isearch'.
+If set, 'isearch' will skip these areas, which can be useful (for
+instance) when covering huge amounts of data (that has no meaningful
+searchable data, like image data) with a 'display' text property.
+
++++
+** 'insert-image' now takes an INHIBIT-ISEARCH optional parameter.
+It marks the image with the 'inhibit-isearch' text property, which
+inhibits 'isearch' matching the STRING parameter.
+
+---
+** New variable 'replace-regexp-function'.
+Function to call to convert the entered FROM string to an Emacs
+regexp in 'query-replace' and similar commands. It can be used to
+implement a different regexp syntax for search/replace.
+
+---
+** New variables to customize defaults of FROM for 'query-replace*' commands.
+The new variable 'query-replace-read-from-default' can be set to a
+function that returns the default value of FROM when 'query-replace'
+prompts for a string to be replaced. An example of such a function is
+'find-tag-default'.
+
+The new variable 'query-replace-read-from-regexp-default' can be set
+to a function (such as 'find-tag-default-as-regexp') that returns the
+default value of FROM when 'query-replace-regexp' prompts for a regexp
+whose matches are to be replaced. If these variables are nil (which
+is the default), 'query-replace' and 'query-replace-regexp' take the
+default value from the previous FROM-TO pair.
+
+---
+** New user option 'pp-use-max-width'.
+If non-nil, 'pp' will attempt to limit the line length when formatting
+long lists and vectors.
+
+---
+** New function 'pp-emacs-lisp-code'.
+'pp' formats general Lisp sexps. This function does much the same,
+but applies formatting rules appropriate for Emacs Lisp code.
+
++++
+** New function 'file-has-changed-p'.
+This convenience function is useful when writing code that parses
+files at run-time, and allows Lisp programs to re-parse files only
+when they have changed.
+
++++
+** 'abbreviate-file-name' now respects magic file name handlers.
+
+---
+** New function 'font-has-char-p'.
+This can be used to check whether a specific font has a glyph for a
+character.
+
++++
+** 'window-text-pixel-size' now accepts a new argument IGNORE-LINE-AT-END.
+This controls whether or not the last screen line of the text being
+measured will be counted for the purpose of calculating the text
+dimensions.
+
++++
+** 'window-text-pixel-size' understands a new meaning of FROM.
+Specifying a cons as the FROM argument allows to start measuring text
+from a specified amount of pixels above or below a position.
+
++++
+** 'window-body-width' and 'window-body-height' can use remapped faces.
+Specifying 'remap' as the PIXELWISE argument now checks if the default
+face was remapped, and if so, uses the remapped face to determine the
+character width/height.
+
++++
+** 'set-window-vscroll' now accepts a new argument PRESERVE-VSCROLL-P.
+This means the vscroll will not be reset when set on a window that is
+"frozen" due to a mini-window being resized.
+
+** XDG support
+
+---
+*** New function 'xdg-state-home'.
+It returns the new 'XDG_STATE_HOME' environment variable. It should
+point to a file name that "contains state data that should persist
+between (application) restarts, but that is not important or portable
+enough to the user that it should be stored in $XDG_DATA_HOME".
+(This variable was introduced in the XDG Base Directory Specification
+version 0.8 released on May 8, 2021.)
+
+---
+*** New function 'xdg-current-desktop'.
+It returns a list of strings, corresponding to the colon-separated
+list of names in the 'XDG_CURRENT_DESKTOP' environment variable, which
+identify the current desktop environment.
+(This variable was introduced in XDG Desktop Entry Specification
+version 1.2.)
+
+---
+*** New function 'xdg-session-type'.
+It returns the 'XDG_SESSION_TYPE' environment variable. (This is not
+part of any official standard; see the man page pam_systemd(8) for
+more information.)
+
++++
+** New macro 'with-delayed-message'.
+This macro is like 'progn', but will output the specified message if
+the body takes longer to execute than the specified timeout.
+
+---
+** New function 'funcall-with-delayed-message'.
+This function is like 'funcall', but will output the specified message
+if the function takes longer to execute than the specified timeout.
+
+** Locale
+
+---
+*** New variable 'current-locale-environment'.
+This holds the value of the previous call to 'set-locale-environment'.
+
+---
+*** New macro 'with-locale-environment'.
+This macro can be used to change the locale temporarily while
+executing code.
+
+** table.el
+
+---
+*** New user option 'table-latex-environment'.
+This allows switching between "table" and "tabular".
+
+** Tabulated List Mode
+
++++
+*** A column can now be set to an image descriptor.
+The 'tabulated-list-entries' variable now supports using an image
+descriptor, which means to insert an image in that column instead of
+text. See the documentation string of that variable for details.
+
++++
+** ':keys' in 'menu-item' can now be a function.
+If so, it is called whenever the menu is computed, and can be used to
+calculate the keys dynamically.
+
++++
+** New major mode 'clean-mode'.
+This is a new major mode meant for debugging. It kills absolutely all
+local variables and removes overlays and text properties.
+
++++
+** 'kill-all-local-variables' can now kill all local variables.
+If given the new optional KILL-PERMANENT argument, also kill permanent
+local variables.
+
++++
+** Third 'mapconcat' argument SEPARATOR is now optional.
+An explicit nil always meant the empty string, now it can be left out.
+
++++
+** New function 'define-keymap'.
+This function allows defining a number of keystrokes with one form.
+
++++
+** New macro 'defvar-keymap'.
+This macro allows defining keymap variables more conveniently.
+
+** 'defvar-keymap' can specify 'repeat-mode' behavior for the keymap.
+Use ':repeat t' to have all bindings be repeatable or for more
+advanced usage:
+
+ ':repeat (:enter (commands ...) :exit (commands ...))'
+
+---
+** 'kbd' can now be used in built-in, preloaded libraries.
+It no longer depends on edmacro.el and cl-lib.el.
+
++++
+** New function 'image-at-point-p'.
+This function returns t if point is on a valid image, and nil
+otherwise.
+
++++
+** New function 'buffer-text-pixel-size'.
+This is similar to 'window-text-pixel-size', but can be used when the
+buffer isn't displayed.
+
++++
+** New function 'string-pixel-width'.
+This returns the width of a string in pixels. This can be useful when
+dealing with variable pitch fonts and glyphs that have widths that
+aren't integer multiples of the default font.
+
++++
+** New function 'string-glyph-split'.
+This function splits a string into a list of strings representing
+separate glyphs. This takes into account combining characters and
+grapheme clusters, by treating each sequence of characters composed on
+display as a single unit.
+
+---
+** 'lookup-key' is more permissive when searching for extended menu items.
+In Emacs 28.1, the behavior of 'lookup-key' was changed: when looking
+for a menu item '[menu-bar Foo-Bar]', first try to find an exact
+match, then look for the lowercased '[menu-bar foo-bar]'.
+
+This has been extended, so that when looking for a menu item with a
+symbol containing spaces, as in '[menu-bar Foo\ Bar]', first look for
+an exact match, then the lowercased '[menu-bar foo\ bar]' and finally
+'[menu-bar foo-bar]'. This further improves backwards-compatibility
+when converting menus to use 'easy-menu-define'.
+
+** xwidgets
+
++++
+*** The function 'make-xwidget' now accepts an optional RELATED argument.
+This argument is used as another widget for the newly created WebKit
+widget to share settings and subprocesses with. It must be another
+WebKit widget.
+
++++
+*** New function 'xwidget-perform-lispy-event'.
+This function allows you to send events to xwidgets. Usually, some
+equivalent of the event will be sent, but there is no guarantee of
+what the widget will actually receive.
+
+On GTK+, only key and function key events are implemented.
+
++++
+*** New function 'xwidget-webkit-load-html'.
+This function is used to load HTML text into WebKit xwidgets
+directly, in contrast to creating a temporary file to hold the
+markup, and passing the URI of the file as an argument to
+'xwidget-webkit-goto-uri'.
+
++++
+*** New functions for performing searches on WebKit xwidgets.
+Some new functions, such as 'xwidget-webkit-search', have been added
+for performing searches on WebKit xwidgets.
+
++++
+*** New function 'xwidget-webkit-back-forward-list'.
+This function returns the history of page-loads in a WebKit xwidget.
+
++++
+*** New function 'xwidget-webkit-estimated-load-progress'.
+This function returns the estimated progress of page loading in a
+WebKit xwidget.
+
++++
+*** New function 'xwidget-webkit-stop-loading'.
+This function terminates all data transfer during page loads in a
+WebKit xwidget.
+
++++
+*** 'load-changed' xwidget events are now more detailed.
+In particular, they can now have different arguments based on the
+state of the WebKit widget. 'load-finished' is sent when a load has
+completed, 'load-started' when a load first starts, 'load-redirected'
+after a redirect, and 'load-committed' when the WebKit widget first
+commits to the load.
+
++++
+*** New event type 'xwidget-display-event'.
+These events are sent whenever an xwidget requests that Emacs display
+another xwidget. The only arguments to this event are the xwidget
+that should be displayed, and the xwidget that asked to display it.
+
++++
+*** New function 'xwidget-webkit-set-cookie-storage-file'.
+This function is used to control where and if an xwidget stores
+cookies set by web pages on disk.
+
+---
+** New variable 'help-buffer-under-preparation'.
+This variable is bound to t during the preparation of a "*Help*" buffer.
+
++++
+** Timestamps like '(1 . 1000)' now work without warnings being generated.
+For example, '(time-add nil '(1 . 1000))' no longer warns that the
+'(1 . 1000)' acts like '(1000 . 1000000)'. This warning, which was a
+temporary transition aid for Emacs 27, has served its purpose.
+
++++
+** 'encode-time' now also accepts a 6-element list with just time and date.
+'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR))' is now short for
+'(encode-time (list SECOND MINUTE HOUR DAY MONTH YEAR nil -1 nil))'.
+
++++
+** 'date-to-time' now accepts arguments that lacks month, day, or time.
+The function now assumes the earliest possible values if its argument
+lacks month, day, or time. For example, (date-to-time "2021-12-04")
+now assumes a time of 00:00 instead of signaling an error.
+
++++
+** 'format-seconds' now allows suppressing zero-value trailing elements.
+The new "%x" non-printing control character will suppress zero-value
+elements that appear after "%x".
+
++++
+** New events for taking advantage of touchscreen devices.
+The events 'touchscreen-begin, 'touchscreen-update', and
+'touchscreen-end' have been added to take better advantage of
+touch-capable display panels.
+
++++
+** New error symbol 'permission-denied'.
+This is a subcategory of 'file-error', and is signaled when some file
+operation fails because the OS doesn't allow Emacs to access a file or
+a directory.
+
++++
+** The ':underline' face attribute now accepts a new property.
+The property ':position' now specifies the position of the underline
+when used as part of a property list specification for the
+':underline' attribute.
+
++++
+** 'defalias' records a more precise history of definitions.
+This is recorded in the 'function-history' symbol property.
+
+---
+** New hook 'save-place-after-find-file-hook'.
+This is called at the end of 'save-place-find-file-hook'.
+
+---
+** 'indian-tml-base-table' no longer translates digits.
+Use 'indian-tml-base-digits-table' if you want digits translation.
+
+---
+** 'indian-tml-itrans-v5-hash' no longer translates digits.
+Use 'indian-tml-itrans-digits-v5-hash' if you want digits
+translation.
+
++++
+** 'shell-quote-argument' has a new optional parameter POSIX.
+This is useful when quoting shell arguments for a remote shell
+invocation. Such shells are POSIX conformant by default.
+
++++
+** 'make-process' can set connection type independently for input and output.
+When calling 'make-process', communication via pty can be enabled
+selectively for just input or output by passing a cons cell for
+':connection-type', e.g. '(pipe . pty)'. When examining a process
+later, you can determine whether a particular stream for a process
+uses a pty by passing one of 'stdin', 'stdout', or 'stderr' as the
+second argument to 'process-tty-name'.
+
++++
+** 'signal-process' now consults the list 'signal-process-functions'.
+This is to determine which function has to be called in order to
+deliver the signal. This allows Tramp to send the signal to remote
+asynchronous processes. The hitherto existing implementation has been
+moved to 'internal-default-signal-process'.
+
++++
+** Some system information functions honor remote systems now.
+'list-system-processes' returns remote process IDs.
+'memory-info' returns memory information of remote systems.
+'process-attributes' expects a remote process ID.
+This happens only when the current buffer's 'default-directory' is
+remote. In order to preserve the old behavior, bind
+'default-directory' to a local directory, like
+
+ (let ((default-directory temporary-file-directory))
+ (list-system-processes))
+
++++
+** New functions 'take' and 'ntake'.
+'(take N LIST)' returns the first N elements of LIST; 'ntake' does
+the same but works by modifying LIST destructively.
+
+---
+** 'string-split' is now an alias for 'split-string'.
+
++++
+** 'format-spec' now accepts functions in the replacement.
+The function is called only when used in the format string. This is
+useful to avoid side-effects such as prompting, when the value is not
+actually being used for anything.
+
++++
+** The variable 'max-specpdl-size' has been made obsolete.
+Now 'max-lisp-eval-depth' alone is used for limiting Lisp recursion
+and stack usage. 'max-specpdl-size' is still present as a plain
+variable for compatibility but its limiting powers have been taken away.
+
+** New function 'external-completion-table'.
+This function returns a completion table designed to ease
+communication between Emacs's completion facilities and external tools
+offering completion services, particularly tools whose full working
+set is too big to transfer to Emacs every time a completion is
+needed. The table uses new 'external' completion style exclusively
+and cannot work with regular styles such as 'basic' or 'flex'.
+
++++
+** Magic file name handlers for 'make-directory-internal' are no longer needed.
+Instead, Emacs uses the already-existing 'make-directory' handlers.
+
++++
+** '(make-directory DIR t)' returns non-nil if DIR already exists.
+This can let a caller know whether it created DIR. Formerly,
+'make-directory's return value was unspecified.
+
+
+* Changes in Emacs 29.1 on Non-Free Operating Systems
+
+** MS-Windows
+
+---
+*** Emacs now supports double-buffering on MS-Windows to reduce display flicker.
+(This was supported on Free systems since Emacs 26.1.)
+
+To disable double-buffering (e.g., if it causes display problems), set
+the frame parameter 'inhibit-double-buffering' to a non-nil value.
+You can do that either by adding
+
+ '(inhibit-double-buffering . t)
+
+to 'default-frame-alist', or by modifying the frame parameters of the
+selected frame by evaluating
+
+ (modify-frame-parameters nil '((inhibit-double-buffering . t)))
+
++++
+*** Emacs now supports system dark mode.
+On Windows 10 (version 1809 and higher) and Windows 11, Emacs will now
+follow the system's dark mode: GUI frames use the appropriate light or
+dark title bar and scroll bars, based on the user's Windows-wide color
+settings.
+
+---
+*** Emacs now uses native image APIs to display some image formats.
+On Windows 2000 and later, Emacs now defaults to using the native
+image APIs for displaying the BMP, GIF, JPEG, PNG, and TIFF images.
+This means Emacs on MS-Windows needs no longer use external image
+support libraries to display those images. Other image types -- XPM,
+SVG, and WEBP -- still need support libraries for Emacs to be able to
+display them.
+
+The use of native image APIs is controlled by the variable
+'w32-use-native-image-API', whose value now defaults to t on systems
+where those APIs are available.
+
++++
+*** Emacs now supports display of BMP images using native image APIs.
+When 'w32-use-native-image-API' is non-nil, Emacs on MS-Windows now
+has built-in support for displaying BMP images.
+
+---
+*** GUI Yes/No dialogs now include a "Cancel" button.
+The "Cancel" button is in addition to "Yes" and "No", and is intended
+to allow users to quit the dialog, as an equivalent of C-g when Emacs
+asks a yes/no question via the echo area. This is controlled by the
+new variable 'w32-yes-no-dialog-show-cancel', by default t. Set it to
+nil to get back the old behavior of showing a modal dialog with only
+two buttons: "Yes" and "No".
+
+** Cygwin
+
+---
+*** 'process-attributes' is now implemented.
+
+
+----------------------------------------------------------------------
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+
+Local variables:
+coding: utf-8
+mode: outline
+mode: emacs-news
+paragraph-separate: "[ ]"
+end:
diff --git a/etc/PROBLEMS b/etc/PROBLEMS
index c560f9246dd..1e45887b868 100644
--- a/etc/PROBLEMS
+++ b/etc/PROBLEMS
@@ -1227,6 +1227,20 @@ you should use an Emacs input method instead.
* X runtime problems
+** X security problems
+
+*** Emacs faces trouble when running as an untrusted client.
+
+When Emacs is running as an untrusted client under X servers with the
+Security extension, it is unable to use some window manager features
+but reports them to the window manager anyway. This can lead to
+constant prompting by the window manager about Emacs being
+unresponsive. To resolve the problem, place:
+
+ (setq x-detect-server-trust t)
+
+in your early-init.el.
+
** X keyboard problems
*** `x-focus-frame' fails to activate the frame.
@@ -1698,8 +1712,8 @@ which can be carried out at the same time:
7) If selecting text with the mouse is slow, the main culprit is
likely `select-active-regions', coupled with a program monitoring
- the clipboard on the X server you are connected to. Try turning
- that off.
+ the clipboard or primary selection on the X server you are
+ connected to. Try turning that off.
However, over networks with moderate to high latency, with no
clipboard monitor running, the bottleneck is likely to be
@@ -1709,6 +1723,12 @@ which can be carried out at the same time:
cause Emacs features that relies on accurate mouse position
reporting to stop working reliably.
+8) If creating or resizing frames is slow, turn off
+ `frame-resize-pixelwise' (this will not take effect until you
+ create a new frame); then, enable `x-lax-frame-positioning'. This
+ means frame placement will be less accurate, but makes frame
+ creation, movement, and resize visibly faster.
+
*** Emacs gives the error, Couldn't find per display information.
This can result if the X server runs out of memory because Emacs uses
diff --git a/etc/publicsuffix.txt b/etc/publicsuffix.txt
index 60d72fd0d53..54988c7187c 100644
--- a/etc/publicsuffix.txt
+++ b/etc/publicsuffix.txt
@@ -7171,7 +7171,7 @@ org.zw
// newGTLDs
-// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-11-29T15:14:18Z
+// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2022-12-07T15:13:11Z
// This list is auto-generated, don't edit it manually.
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa
@@ -10461,9 +10461,6 @@ xin
// xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc.
亚马逊
-// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation
-诺基亚
-
// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc.
食品
diff --git a/etc/refcards/ru-refcard.tex b/etc/refcards/ru-refcard.tex
index 40af6414680..50a22891a6b 100644
--- a/etc/refcards/ru-refcard.tex
+++ b/etc/refcards/ru-refcard.tex
@@ -40,7 +40,7 @@
\newlength{\ColThreeWidth}
\setlength{\ColThreeWidth}{25mm}
-\newcommand{\versionemacs}[0]{29} % version of Emacs this is for
+\newcommand{\versionemacs}[0]{30} % version of Emacs this is for
\newcommand{\cyear}[0]{2022} % copyright year
\newcommand\shortcopyrightnotice[0]{\vskip 1ex plus 2 fill
diff --git a/lib-src/etags.c b/lib-src/etags.c
index a06c236140f..280b5b9df22 100644
--- a/lib-src/etags.c
+++ b/lib-src/etags.c
@@ -7772,7 +7772,7 @@ escape_shell_arg_string (char *str)
#endif
static void
-do_move_file(const char *src_file, const char *dst_file)
+do_move_file (const char *src_file, const char *dst_file)
{
if (rename (src_file, dst_file) == 0)
return;
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c
deleted file mode 100644
index ad0bfd170ca..00000000000
--- a/lib/explicit_bzero.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* Erasure of sensitive data, generic implementation.
- Copyright (C) 2016-2022 Free Software Foundation, Inc.
- This file is part of the GNU C Library.
-
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The GNU C Library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <https://www.gnu.org/licenses/>. */
-
-/* An assembler implementation of explicit_bzero can be created as an
- assembler alias of an optimized bzero implementation.
- Architecture-specific implementations also need to define
- __explicit_bzero_chk. */
-
-#if !_LIBC
-# include <config.h>
-#endif
-
-/* memset_s need this define */
-#if HAVE_MEMSET_S
-# define __STDC_WANT_LIB_EXT1__ 1
-#endif
-
-#include <string.h>
-
-#if defined _WIN32 && !defined __CYGWIN__
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-#if _LIBC
-/* glibc-internal users use __explicit_bzero_chk, and explicit_bzero
- redirects to that. */
-# undef explicit_bzero
-#endif
-
-/* Set LEN bytes of S to 0. The compiler will not delete a call to
- this function, even if S is dead after the call. */
-void
-explicit_bzero (void *s, size_t len)
-{
-#if defined _WIN32 && !defined __CYGWIN__
- (void) SecureZeroMemory (s, len);
-#elif HAVE_EXPLICIT_MEMSET
- explicit_memset (s, '\0', len);
-#elif HAVE_MEMSET_S
- (void) memset_s (s, len, '\0', len);
-#elif defined __GNUC__ && !defined __clang__
- memset (s, '\0', len);
- /* Compiler barrier. */
- asm volatile ("" ::: "memory");
-#elif defined __clang__
- memset (s, '\0', len);
- /* Compiler barrier. */
- /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the
- whole thing is dead and eliminates it. Use 'g' to work around this
- problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */
- __asm__ volatile ("" : : "g"(s) : "memory");
-#else
- /* Invoke memset through a volatile function pointer. This defeats compiler
- optimizations. */
- void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
- (void) volatile_memset (s, '\0', len);
-#endif
-}
diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c
index e02f0626ad3..676523ba821 100644
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -29,9 +29,97 @@
#include "acl-internal.h"
-#if GETXATTR_WITH_POSIX_ACLS
+#if USE_ACL && GETXATTR_WITH_POSIX_ACLS
+# include <string.h>
+# include <arpa/inet.h>
# include <sys/xattr.h>
# include <linux/xattr.h>
+# ifndef XATTR_NAME_NFSV4_ACL
+# define XATTR_NAME_NFSV4_ACL "system.nfs4_acl"
+# endif
+
+enum {
+ /* ACE4_ACCESS_ALLOWED_ACE_TYPE = 0x00000000, */
+ ACE4_ACCESS_DENIED_ACE_TYPE = 0x00000001,
+ ACE4_IDENTIFIER_GROUP = 0x00000040
+};
+
+/* Return 1 if given ACL in XDR format is non-trivial, 0 if it is trivial.
+ -1 upon failure to determine it. Possibly change errno. Assume that
+ the ACL is valid, except avoid undefined behavior even if invalid.
+
+ See <https://linux.die.net/man/5/nfs4_acl>. The NFSv4 acls are
+ defined in Internet RFC 7530 and as such, every NFSv4 server
+ supporting ACLs should support NFSv4 ACLs (they differ from from
+ POSIX draft ACLs). The ACLs can be obtained via the
+ nfsv4-acl-tools, e.g., the nfs4_getfacl command. Gnulib provides
+ only basic support of NFSv4 ACLs, i.e., recognize trivial vs
+ nontrivial ACLs. */
+
+static int
+acl_nfs4_nontrivial (uint32_t *xattr, ssize_t nbytes)
+{
+ enum { BYTES_PER_NETWORK_UINT = 4};
+
+ /* Grab the number of aces in the acl. */
+ nbytes -= BYTES_PER_NETWORK_UINT;
+ if (nbytes < 0)
+ return -1;
+ uint32_t num_aces = ntohl (*xattr++);
+ if (6 < num_aces)
+ return 1;
+ int ace_found = 0;
+
+ for (int ace_n = 0; ace_n < num_aces; ace_n++)
+ {
+ /* Get the acl type and flag. Skip the mask; it's too risky to
+ test it and it does not seem to be needed. Get the wholen. */
+ nbytes -= 4 * BYTES_PER_NETWORK_UINT;
+ if (nbytes < 0)
+ return -1;
+ uint32_t type = ntohl (xattr[0]);
+ uint32_t flag = ntohl (xattr[1]);
+ uint32_t wholen = ntohl (xattr[3]);
+ xattr += 4;
+ int64_t wholen4 = wholen;
+ wholen4 = ((wholen4 + (BYTES_PER_NETWORK_UINT))
+ & ~ (BYTES_PER_NETWORK_UINT - 1));
+
+ /* Trivial ACLs have only ACE4_ACCESS_ALLOWED_ACE_TYPE or
+ ACE4_ACCESS_DENIED_ACE_TYPE. */
+ if (ACE4_ACCESS_DENIED_ACE_TYPE < type)
+ return 1;
+
+ /* RFC 7530 says FLAG should be 0, but be generous to NetApp and
+ also accept the group flag. */
+ if (flag & ~ACE4_IDENTIFIER_GROUP)
+ return 1;
+
+ /* Get the who string. Check NBYTES - WHOLEN4 before storing
+ into NBYTES, to avoid truncation on conversion. */
+ if (nbytes - wholen4 < 0)
+ return -1;
+ nbytes -= wholen4;
+
+ /* For a trivial ACL, max 6 (typically 3) ACEs, 3 allow, 3 deny.
+ Check that there is at most one ACE of each TYPE and WHO. */
+ int who2
+ = (wholen == 6 && memcmp (xattr, "OWNER@", 6) == 0 ? 0
+ : wholen == 6 && memcmp (xattr, "GROUP@", 6) == 0 ? 2
+ : wholen == 9 && memcmp (xattr, "EVERYONE@", 9) == 0 ? 4
+ : -1);
+ if (who2 < 0)
+ return 1;
+ int ace_found_bit = 1 << (who2 | type);
+ if (ace_found & ace_found_bit)
+ return 1;
+ ace_found |= ace_found_bit;
+
+ xattr = (uint32_t *) ((char *) xattr + wholen4);
+ }
+
+ return 0;
+}
#endif
/* Return 1 if NAME has a nontrivial access control list,
@@ -51,6 +139,7 @@ file_has_acl (char const *name, struct stat const *sb)
# if GETXATTR_WITH_POSIX_ACLS
ssize_t ret;
+ int initial_errno = errno;
ret = getxattr (name, XATTR_NAME_POSIX_ACL_ACCESS, NULL, 0);
if (ret < 0 && errno == ENODATA)
@@ -68,6 +157,35 @@ file_has_acl (char const *name, struct stat const *sb)
}
if (ret < 0)
+ {
+ /* Check for NFSv4 ACLs. The max length of a trivial
+ ACL is 6 words for owner, 6 for group, 7 for everyone,
+ all times 2 because there are both allow and deny ACEs.
+ There are 6 words for owner because of type, flag, mask,
+ wholen, "OWNER@"+pad and similarly for group; everyone is
+ another word to hold "EVERYONE@". */
+ uint32_t xattr[2 * (6 + 6 + 7)];
+
+ ret = getxattr (name, XATTR_NAME_NFSV4_ACL, xattr, sizeof xattr);
+ if (ret < 0)
+ switch (errno)
+ {
+ case ENODATA: return 0;
+ case ERANGE : return 1; /* ACL must be nontrivial. */
+ }
+ else
+ {
+ /* It looks like a trivial ACL, but investigate further. */
+ ret = acl_nfs4_nontrivial (xattr, ret);
+ if (ret < 0)
+ {
+ errno = EINVAL;
+ return ret;
+ }
+ errno = initial_errno;
+ }
+ }
+ if (ret < 0)
return - acl_errno_valid (errno);
return ret;
diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in
index 9af8fd0c579..fcbf5bde2db 100644
--- a/lib/gnulib.mk.in
+++ b/lib/gnulib.mk.in
@@ -93,7 +93,6 @@
# dup2 \
# environ \
# execinfo \
-# explicit_bzero \
# faccessat \
# fchmodat \
# fcntl \
@@ -126,6 +125,7 @@
# memmem-simple \
# mempcpy \
# memrchr \
+# memset_explicit \
# minmax \
# mkostemp \
# mktime \
@@ -264,7 +264,6 @@ GL_COND_OBJ_DIRFD_CONDITION = @GL_COND_OBJ_DIRFD_CONDITION@
GL_COND_OBJ_DUP2_CONDITION = @GL_COND_OBJ_DUP2_CONDITION@
GL_COND_OBJ_EUIDACCESS_CONDITION = @GL_COND_OBJ_EUIDACCESS_CONDITION@
GL_COND_OBJ_EXECINFO_CONDITION = @GL_COND_OBJ_EXECINFO_CONDITION@
-GL_COND_OBJ_EXPLICIT_BZERO_CONDITION = @GL_COND_OBJ_EXPLICIT_BZERO_CONDITION@
GL_COND_OBJ_FACCESSAT_CONDITION = @GL_COND_OBJ_FACCESSAT_CONDITION@
GL_COND_OBJ_FCHMODAT_CONDITION = @GL_COND_OBJ_FCHMODAT_CONDITION@
GL_COND_OBJ_FCNTL_CONDITION = @GL_COND_OBJ_FCNTL_CONDITION@
@@ -286,6 +285,7 @@ GL_COND_OBJ_LCHMOD_CONDITION = @GL_COND_OBJ_LCHMOD_CONDITION@
GL_COND_OBJ_LSTAT_CONDITION = @GL_COND_OBJ_LSTAT_CONDITION@
GL_COND_OBJ_MEMPCPY_CONDITION = @GL_COND_OBJ_MEMPCPY_CONDITION@
GL_COND_OBJ_MEMRCHR_CONDITION = @GL_COND_OBJ_MEMRCHR_CONDITION@
+GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION = @GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION@
GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION = @GL_COND_OBJ_MINI_GMP_GNULIB_CONDITION@
GL_COND_OBJ_MKOSTEMP_CONDITION = @GL_COND_OBJ_MKOSTEMP_CONDITION@
GL_COND_OBJ_NANOSLEEP_CONDITION = @GL_COND_OBJ_NANOSLEEP_CONDITION@
@@ -485,6 +485,7 @@ GL_GNULIB_MEMCHR = @GL_GNULIB_MEMCHR@
GL_GNULIB_MEMMEM = @GL_GNULIB_MEMMEM@
GL_GNULIB_MEMPCPY = @GL_GNULIB_MEMPCPY@
GL_GNULIB_MEMRCHR = @GL_GNULIB_MEMRCHR@
+GL_GNULIB_MEMSET_EXPLICIT = @GL_GNULIB_MEMSET_EXPLICIT@
GL_GNULIB_MKDIR = @GL_GNULIB_MKDIR@
GL_GNULIB_MKDIRAT = @GL_GNULIB_MKDIRAT@
GL_GNULIB_MKDTEMP = @GL_GNULIB_MKDTEMP@
@@ -749,6 +750,7 @@ HAVE_MAX_ALIGN_T = @HAVE_MAX_ALIGN_T@
HAVE_MBSLEN = @HAVE_MBSLEN@
HAVE_MBTOWC = @HAVE_MBTOWC@
HAVE_MEMPCPY = @HAVE_MEMPCPY@
+HAVE_MEMSET_EXPLICIT = @HAVE_MEMSET_EXPLICIT@
HAVE_MKDIRAT = @HAVE_MKDIRAT@
HAVE_MKDTEMP = @HAVE_MKDTEMP@
HAVE_MKFIFO = @HAVE_MKFIFO@
@@ -1857,16 +1859,6 @@ EXTRA_DIST += execinfo.in.h
endif
## end gnulib module execinfo
-## begin gnulib module explicit_bzero
-ifeq (,$(OMIT_GNULIB_MODULE_explicit_bzero))
-
-ifneq (,$(GL_COND_OBJ_EXPLICIT_BZERO_CONDITION))
-libgnu_a_SOURCES += explicit_bzero.c
-endif
-
-endif
-## end gnulib module explicit_bzero
-
## begin gnulib module faccessat
ifeq (,$(OMIT_GNULIB_MODULE_faccessat))
@@ -2536,6 +2528,16 @@ endif
endif
## end gnulib module memrchr
+## begin gnulib module memset_explicit
+ifeq (,$(OMIT_GNULIB_MODULE_memset_explicit))
+
+ifneq (,$(GL_COND_OBJ_MEMSET_EXPLICIT_CONDITION))
+libgnu_a_SOURCES += memset_explicit.c
+endif
+
+endif
+## end gnulib module memset_explicit
+
## begin gnulib module minmax
ifeq (,$(OMIT_GNULIB_MODULE_minmax))
@@ -3362,6 +3364,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's/@''GNULIB_MEMMEM''@/$(GL_GNULIB_MEMMEM)/g' \
-e 's/@''GNULIB_MEMPCPY''@/$(GL_GNULIB_MEMPCPY)/g' \
-e 's/@''GNULIB_MEMRCHR''@/$(GL_GNULIB_MEMRCHR)/g' \
+ -e 's/@''GNULIB_MEMSET_EXPLICIT''@/$(GL_GNULIB_MEMSET_EXPLICIT)/g' \
-e 's/@''GNULIB_RAWMEMCHR''@/$(GL_GNULIB_RAWMEMCHR)/g' \
-e 's/@''GNULIB_STPCPY''@/$(GL_GNULIB_STPCPY)/g' \
-e 's/@''GNULIB_STPNCPY''@/$(GL_GNULIB_STPNCPY)/g' \
@@ -3393,6 +3396,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
-e 's|@''HAVE_DECL_MEMMEM''@|$(HAVE_DECL_MEMMEM)|g' \
-e 's|@''HAVE_MEMPCPY''@|$(HAVE_MEMPCPY)|g' \
-e 's|@''HAVE_DECL_MEMRCHR''@|$(HAVE_DECL_MEMRCHR)|g' \
+ -e 's|@''HAVE_MEMSET_EXPLICIT''@|$(HAVE_MEMSET_EXPLICIT)|g' \
-e 's|@''HAVE_RAWMEMCHR''@|$(HAVE_RAWMEMCHR)|g' \
-e 's|@''HAVE_STPCPY''@|$(HAVE_STPCPY)|g' \
-e 's|@''HAVE_STPNCPY''@|$(HAVE_STPNCPY)|g' \
diff --git a/lib/memset_explicit.c b/lib/memset_explicit.c
new file mode 100644
index 00000000000..eabeb3ec2b8
--- /dev/null
+++ b/lib/memset_explicit.c
@@ -0,0 +1,55 @@
+/* Erase sensitive data from memory.
+ Copyright 2022 Free Software Foundation, Inc.
+
+ This file is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ This file is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* memset_s need this define */
+#if HAVE_MEMSET_S
+# define __STDC_WANT_LIB_EXT1__ 1
+#endif
+
+#include <string.h>
+
+/* Set S's bytes to C, where S has LEN bytes. The compiler will not
+ optimize effects away, even if S is dead after the call. */
+void *
+memset_explicit (void *s, int c, size_t len)
+{
+#if HAVE_EXPLICIT_MEMSET
+ return explicit_memset (s, c, len);
+#elif HAVE_MEMSET_S
+ (void) memset_s (s, len, c, len);
+ return s;
+#elif defined __GNUC__ && !defined __clang__
+ memset (s, c, len);
+ /* Compiler barrier. */
+ __asm__ volatile ("" ::: "memory");
+ return s;
+#elif defined __clang__
+ memset (s, c, len);
+ /* Compiler barrier. */
+ /* With asm ("" ::: "memory") LLVM analyzes uses of 's' and finds that the
+ whole thing is dead and eliminates it. Use 'g' to work around this
+ problem. See <https://bugs.llvm.org/show_bug.cgi?id=15495#c11>. */
+ __asm__ volatile ("" : : "g"(s) : "memory");
+ return s;
+#else
+ /* Invoke memset through a volatile function pointer. This defeats compiler
+ optimizations. */
+ void * (* const volatile volatile_memset) (void *, int, size_t) = memset;
+ return volatile_memset (s, c, len);
+#endif
+}
diff --git a/lib/string.in.h b/lib/string.in.h
index e56f6db0c9c..21356914e21 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -347,6 +347,23 @@ _GL_WARN_ON_USE (memrchr, "memrchr is unportable - "
# endif
#endif
+/* Overwrite a block of memory. The compiler will not optimize
+ effects away, even if the block is dead after the call. */
+#if @GNULIB_MEMSET_EXPLICIT@
+# if ! @HAVE_MEMSET_EXPLICIT@
+_GL_FUNCDECL_SYS (memset_explicit, void *,
+ (void *__dest, int __c, size_t __n) _GL_ARG_NONNULL ((1)));
+# endif
+_GL_CXXALIAS_SYS (memset_explicit, void *, (void *__dest, int __c, size_t __n));
+_GL_CXXALIASWARN (memset_explicit);
+#elif defined GNULIB_POSIXCHECK
+# undef memset_explicit
+# if HAVE_RAW_DECL_MEMSET_EXPLICIT
+_GL_WARN_ON_USE (memset_explicit, "memset_explicit is unportable - "
+ "use gnulib module memset_explicit for portability");
+# endif
+#endif
+
/* Find the first occurrence of C in S. More efficient than
memchr(S,C,N), at the expense of undefined behavior if C does not
occur within N bytes. */
diff --git a/lib/time.in.h b/lib/time.in.h
index 6aa67498f57..aba2eda8759 100644
--- a/lib/time.in.h
+++ b/lib/time.in.h
@@ -315,6 +315,7 @@ _GL_CXXALIASWARN (strptime);
# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
# define ctime rpl_ctime
# endif
+_GL_ATTRIBUTE_DEPRECATED
_GL_FUNCDECL_RPL (ctime, char *, (time_t const *__tp)
_GL_ARG_NONNULL ((1)));
_GL_CXXALIAS_RPL (ctime, char *, (time_t const *__tp));
diff --git a/lib/verify.h b/lib/verify.h
index 99af802993e..5225a8e616d 100644
--- a/lib/verify.h
+++ b/lib/verify.h
@@ -37,7 +37,7 @@
&& (4 < __GNUC__ + (6 <= __GNUC_MINOR__) || 5 <= __clang_major__)))
# define _GL_HAVE__STATIC_ASSERT 1
# endif
-# if (202000 <= __STDC_VERSION__ \
+# if (202311 <= __STDC_VERSION__ \
|| (!defined __STRICT_ANSI__ && 9 <= __GNUC__))
# define _GL_HAVE__STATIC_ASSERT1 1
# endif
diff --git a/lisp/abbrev.el b/lisp/abbrev.el
index 2ca8e25dac7..26c2b097929 100644
--- a/lisp/abbrev.el
+++ b/lisp/abbrev.el
@@ -501,7 +501,7 @@ PROPS is a list of properties."
(defun abbrev-table-p (object)
"Return non-nil if OBJECT is an abbrev table."
(and (obarrayp object)
- (numberp (ignore-error 'wrong-type-argument
+ (numberp (ignore-error wrong-type-argument
(abbrev-table-get object :abbrev-table-modiff)))))
(defun abbrev-table-empty-p (object &optional ignore-system)
diff --git a/lisp/bindings.el b/lisp/bindings.el
index c298a43952f..f2e0799f72b 100644
--- a/lisp/bindings.el
+++ b/lisp/bindings.el
@@ -670,6 +670,8 @@ or not."
"Return the value of symbol VAR if it is bound, else nil.
Note that if `lexical-binding' is in effect, this function isn't
meaningful if it refers to a lexically bound variable."
+ (unless (symbolp var)
+ (signal 'wrong-type-argument (list 'symbolp var)))
`(and (boundp (quote ,var)) ,var))
;; Use mode-line-mode-menu for local minor-modes only.
diff --git a/lisp/bs.el b/lisp/bs.el
index d181511b035..d6df89138db 100644
--- a/lisp/bs.el
+++ b/lisp/bs.el
@@ -420,9 +420,6 @@ naming a sort behavior. Default is \"by nothing\" which means no sorting."
Non-nil means to show all buffers. Otherwise show buffers
defined by current configuration `bs-current-configuration'.")
-(defvar bs--window-config-coming-from nil
- "Window configuration before starting Buffer Selection Menu.")
-
(defvar bs--intern-show-never "^ \\|\\*buffer-selection\\*"
"Regular expression specifying which buffers never to show.
A buffer whose name matches this regular expression will never be
@@ -491,6 +488,23 @@ Used internally, only.")
"<mouse-2>" #'bs-mouse-select
"<mouse-3>" #'bs-mouse-select-other-frame)
+(defcustom bs-default-action-list '((display-buffer-reuse-window
+ display-buffer-below-selected)
+ (reusable-frames . nil)
+ (window-height . window-min-height))
+ "Default action list for showing the '*bs-selection*' buffer.
+
+This list will be passed to `pop-to-buffer' as its ACTION argument.
+It should be a cons cell (FUNCTIONS . ALIST), where FUNCTIONS is
+an action function or a list of action functions and ALIST is an
+action alist. Each such action function should accept two
+arguments: a buffer to display and an alist of the same form as
+ALIST. See `display-buffer' for details."
+ :type display-buffer--action-custom-type
+ :risky t
+ :version "30.1"
+ :group 'bs)
+
;; ----------------------------------------------------------------------
;; Functions
;; ----------------------------------------------------------------------
@@ -590,21 +604,6 @@ in `bs-string-current' or `bs-string-current-marked'."
(format "Show buffer by configuration %S"
bs-current-configuration)))
-(defun bs--track-window-changes (frame)
- "Track window changes to refresh the buffer list.
-Used from `window-size-change-functions'."
- (let ((win (get-buffer-window "*buffer-selection*" frame)))
- (when win
- (with-selected-window win
- (bs--set-window-height)))))
-
-(defun bs--remove-hooks ()
- "Remove `bs--track-window-changes' and auxiliary hooks."
- (remove-hook 'window-size-change-functions 'bs--track-window-changes)
- ;; Remove itself
- (remove-hook 'kill-buffer-hook 'bs--remove-hooks t)
- (remove-hook 'change-major-mode-hook 'bs--remove-hooks t))
-
(put 'bs-mode 'mode-class 'special)
(define-derived-mode bs-mode nil "Buffer-Selection-Menu"
@@ -663,25 +662,13 @@ apply it.
(setq-local font-lock-defaults '(bs-mode-font-lock-keywords t))
(setq-local font-lock-verbose nil)
(setq-local font-lock-global-modes '(not bs-mode))
- (setq-local revert-buffer-function 'bs-refresh)
- (add-hook 'window-size-change-functions 'bs--track-window-changes)
- (add-hook 'kill-buffer-hook 'bs--remove-hooks nil t)
- (add-hook 'change-major-mode-hook 'bs--remove-hooks nil t))
-
-(defun bs--restore-window-config ()
- "Restore window configuration on the current frame."
- (when bs--window-config-coming-from
- (let ((frame (selected-frame)))
- (unwind-protect
- (set-window-configuration bs--window-config-coming-from)
- (select-frame frame)))
- (setq bs--window-config-coming-from nil)))
+ (setq-local revert-buffer-function 'bs-refresh))
(defun bs-kill ()
"Let buffer disappear and reset window configuration."
(interactive)
(bury-buffer (current-buffer))
- (bs--restore-window-config))
+ (quit-window))
(defun bs-abort ()
"Ding and leave Buffer Selection Menu without a selection."
@@ -705,7 +692,9 @@ Arguments are IGNORED (for `revert-buffer')."
(defun bs--set-window-height ()
"Change the height of the selected window to suit the current buffer list."
(unless (one-window-p t)
- (fit-window-to-buffer (selected-window) bs-max-window-height)))
+ (fit-window-to-buffer (selected-window) bs-max-window-height nil nil nil
+ ;; preserve-size
+ t)))
(defun bs--current-buffer ()
"Return buffer on current line.
@@ -742,7 +731,7 @@ Leave Buffer Selection Menu."
(interactive)
(let ((buffer (bs--current-buffer)))
(bury-buffer (current-buffer))
- (bs--restore-window-config)
+ (quit-window)
(switch-to-buffer buffer)
(when bs--marked-buffers
;; Some marked buffers for selection
@@ -765,7 +754,7 @@ Leave Buffer Selection Menu."
(interactive)
(let ((buffer (bs--current-buffer)))
(bury-buffer (current-buffer))
- (bs--restore-window-config)
+ (quit-window)
(switch-to-buffer-other-window buffer)))
(defun bs-tmp-select-other-window ()
@@ -781,7 +770,7 @@ Leave Buffer Selection Menu."
(interactive)
(let ((buffer (bs--current-buffer)))
(bury-buffer (current-buffer))
- (bs--restore-window-config)
+ (quit-window)
(switch-to-buffer-other-frame buffer)))
(defun bs-mouse-select-other-frame (event)
@@ -1165,7 +1154,18 @@ Select buffer *buffer-selection* and display buffers according to current
configuration `bs-current-configuration'. Set window height, fontify buffer
and move point to current buffer."
(setq bs-current-list list)
- (switch-to-buffer (get-buffer-create "*buffer-selection*"))
+ (let* ((window-combination-limit 'window-size)
+ (bs-buf (get-buffer-create "*buffer-selection*"))
+ (bs-win (progn
+ (pop-to-buffer bs-buf bs-default-action-list)
+ (selected-window))))
+ ;; Delete other windows showing *buffer-selection*.
+ ;; Done after pop-to-buffer, instead of just calling delete-windows-on,
+ ;; to allow display-buffer-reuse(-mode)?-window to be used in ALIST.
+ (dolist (w (get-buffer-window-list bs-buf 'not t))
+ (unless (eq w bs-win)
+ (with-demoted-errors "Error deleting window: %S"
+ (delete-window w)))))
(bs-mode)
(let* ((inhibit-read-only t)
(map-fun (lambda (entry)
@@ -1346,11 +1346,11 @@ ALL-BUFFERS is the list of buffers appearing in Buffer Selection Menu."
'help-echo "mouse-2: select this buffer, mouse-3: select in other frame"
'mouse-face 'highlight))
-(defun bs--get-mode-name (start-buffer _all-buffers)
+(defun bs--get-mode-name (_start-buffer _all-buffers)
"Return the name of mode of current buffer for Buffer Selection Menu.
START-BUFFER is the buffer where we started buffer selection.
ALL-BUFFERS is the list of buffers appearing in Buffer Selection Menu."
- (format-mode-line mode-name nil nil start-buffer))
+ (format-mode-line mode-name nil nil nil))
(defun bs--get-file-name (_start-buffer _all-buffers)
"Return string for column `File' in Buffer Selection Menu.
@@ -1435,21 +1435,8 @@ for buffer selection."
;; Only when not in buffer *buffer-selection*
;; we have to set the buffer we started the command
(setq bs--buffer-coming-from (current-buffer)))
- (let ((liste (bs-buffer-list))
- (active-window (get-window-with-predicate
- (lambda (w)
- (string= (buffer-name (window-buffer w))
- "*buffer-selection*"))
- nil (selected-frame))))
- (if active-window
- (select-window active-window)
- (bs--restore-window-config)
- (setq bs--window-config-coming-from (current-window-configuration))
- (when (> (window-height) 7)
- ;; Errors would mess with the window configuration (bug#10882).
- (ignore-errors (select-window (split-window-below)))))
- (bs-show-in-buffer liste)
- (bs-message-without-log "%s" (bs--current-config-message)))))
+ (bs-show-in-buffer (bs-buffer-list))
+ (bs-message-without-log "%s" (bs--current-config-message))))
(defun bs--configuration-name-for-prefix-arg (prefix)
"Convert prefix argument PREFIX to a name of a buffer configuration.
diff --git a/lisp/calc/calc-units.el b/lisp/calc/calc-units.el
index 42156b94606..cc1f5085a7c 100644
--- a/lisp/calc/calc-units.el
+++ b/lisp/calc/calc-units.el
@@ -319,28 +319,28 @@ that the combined units table will be rebuilt.")
(defvar math-unit-prefixes
'( ( ?Q (^ 10 30) "quetta" )
( ?R (^ 10 27) "ronna" )
- ( ?Y (^ 10 24) "Yotta" )
- ( ?Z (^ 10 21) "Zetta" )
- ( ?E (^ 10 18) "Exa" )
- ( ?P (^ 10 15) "Peta" )
- ( ?T (^ 10 12) "Tera" )
- ( ?G (^ 10 9) "Giga" )
- ( ?M (^ 10 6) "Mega" )
- ( ?k (^ 10 3) "Kilo" )
- ( ?K (^ 10 3) "Kilo" )
- ( ?h (^ 10 2) "Hecto" )
- ( ?H (^ 10 2) "Hecto" )
- ( ?D (^ 10 1) "Deka" )
+ ( ?Y (^ 10 24) "yotta" )
+ ( ?Z (^ 10 21) "zetta" )
+ ( ?E (^ 10 18) "exa" )
+ ( ?P (^ 10 15) "peta" )
+ ( ?T (^ 10 12) "tera" )
+ ( ?G (^ 10 9) "giga" )
+ ( ?M (^ 10 6) "mega" )
+ ( ?k (^ 10 3) "kilo" )
+ ( ?K (^ 10 3) "kilo" )
+ ( ?h (^ 10 2) "hecto" )
+ ( ?H (^ 10 2) "hecto" )
+ ( ?D (^ 10 1) "deka" )
( 0 (^ 10 0) nil )
- ( ?d (^ 10 -1) "Deci" )
- ( ?c (^ 10 -2) "Centi" )
- ( ?m (^ 10 -3) "Milli" )
- ( ?u (^ 10 -6) "Micro" )
- ( ?μ (^ 10 -6) "Micro" )
- ( ?n (^ 10 -9) "Nano" )
- ( ?p (^ 10 -12) "Pico" )
- ( ?f (^ 10 -15) "Femto" )
- ( ?a (^ 10 -18) "Atto" )
+ ( ?d (^ 10 -1) "deci" )
+ ( ?c (^ 10 -2) "centi" )
+ ( ?m (^ 10 -3) "milli" )
+ ( ?u (^ 10 -6) "micro" )
+ ( ?μ (^ 10 -6) "micro" )
+ ( ?n (^ 10 -9) "nano" )
+ ( ?p (^ 10 -12) "pico" )
+ ( ?f (^ 10 -15) "femto" )
+ ( ?a (^ 10 -18) "atto" )
( ?z (^ 10 -21) "zepto" )
( ?y (^ 10 -24) "yocto" )
( ?r (^ 10 -27) "ronto" )
diff --git a/lisp/calendar/cal-dst.el b/lisp/calendar/cal-dst.el
index 5f601f24d24..c8a65126a49 100644
--- a/lisp/calendar/cal-dst.el
+++ b/lisp/calendar/cal-dst.el
@@ -354,10 +354,10 @@ If the locale never uses daylight saving time, set this to 0."
(if calendar-current-time-zone-cache
(format-time-string
"%z" 0 (* 60 (car calendar-current-time-zone-cache)))
- "+0000")
- (or (nth 2 calendar-current-time-zone-cache) "EST"))
+ "-0000")
+ (or (nth 2 calendar-current-time-zone-cache) "UTC"))
"Abbreviated name of standard time zone at `calendar-location-name'.
-For example, \"EST\" in New York City, \"PST\" for Los Angeles."
+For example, \"-0500\" or \"EST\" in New York City."
:type 'string
:version "28.1"
:set-after '(calendar-time-zone-style)
@@ -368,10 +368,10 @@ For example, \"EST\" in New York City, \"PST\" for Los Angeles."
(if calendar-current-time-zone-cache
(format-time-string
"%z" 0 (* 60 (cadr calendar-current-time-zone-cache)))
- "+0000")
- (or (nth 3 calendar-current-time-zone-cache) "EDT"))
+ "-0000")
+ (or (nth 3 calendar-current-time-zone-cache) "UTC"))
"Abbreviated name of daylight saving time zone at `calendar-location-name'.
-For example, \"EDT\" in New York City, \"PDT\" for Los Angeles."
+For example, \"-0400\" or \"EDT\" in New York City."
:type 'string
:version "28.1"
:set-after '(calendar-time-zone-style)
diff --git a/lisp/calendar/diary-lib.el b/lisp/calendar/diary-lib.el
index 9a2baf1e43c..cc1e7ec5f72 100644
--- a/lisp/calendar/diary-lib.el
+++ b/lisp/calendar/diary-lib.el
@@ -339,7 +339,7 @@ Returns a string using match elements 1-5, where:
(t "\\1 \\2 \\3"))) ; MDY
"\n \\4 %s, \\5")))
;; TODO Sometimes the time is in a different time-zone to the one you
-;; are in. Eg in PST, you might still get an email referring to:
+;; are in. E.g., in Los Angeles, you might still get an email referring to:
;; "7:00 PM-8:00 PM. Greenwich Standard Time".
;; Note that it doesn't use a standard abbreviation for the timezone,
;; or anything helpful like that.
diff --git a/lisp/calendar/solar.el b/lisp/calendar/solar.el
index 8f501824bb0..0b5bc166530 100644
--- a/lisp/calendar/solar.el
+++ b/lisp/calendar/solar.el
@@ -839,12 +839,10 @@ This function is suitable for execution in an init file."
"E" "W"))))))
(calendar-standard-time-zone-name
(if (< arg 16) calendar-standard-time-zone-name
- (cond ((zerop calendar-time-zone)
- (if (eq calendar-time-zone-style 'numeric)
- "+0000" "UTC"))
- ((< calendar-time-zone 0)
- (format "UTC%dmin" calendar-time-zone))
- (t (format "UTC+%dmin" calendar-time-zone)))))
+ (if (and (zerop calendar-time-zone)
+ (not (eq calendar-time-zone-style 'numeric)))
+ "UTC"
+ (format-time-string "%z" 0 (* 60 calendar-time-zone)))))
(calendar-daylight-savings-starts
(if (< arg 16) calendar-daylight-savings-starts))
(calendar-daylight-savings-ends
diff --git a/lisp/cedet/semantic/complete.el b/lisp/cedet/semantic/complete.el
index 00fe081acb5..1f372804dcc 100644
--- a/lisp/cedet/semantic/complete.el
+++ b/lisp/cedet/semantic/complete.el
@@ -1731,7 +1731,7 @@ Display mechanism using tooltip for a list of possible completions.")
;; Add any tail info.
(setq msg (concat msg msg-tail))
;; Display tooltip.
- (when (not (eq msg ""))
+ (when (not (equal msg ""))
(semantic-displayer-tooltip-show msg)))))
;;; Compatibility
diff --git a/lisp/cedet/semantic/decorate/include.el b/lisp/cedet/semantic/decorate/include.el
index fe510c371e3..26785298e6b 100644
--- a/lisp/cedet/semantic/decorate/include.el
+++ b/lisp/cedet/semantic/decorate/include.el
@@ -790,9 +790,7 @@ any decorated referring includes.")
;; This is a hack. Add in something better?
(semanticdb-notify-references
table (lambda (tab _me)
- (semantic-decoration-unparsed-include-refrence-reset tab)
- ))
- ))
+ (semantic-decoration-unparsed-include-reference-reset tab)))))
(cl-defmethod semanticdb-partial-synchronize ((cache semantic-decoration-unparsed-include-cache)
new-tags)
@@ -805,7 +803,7 @@ any decorated referring includes.")
"Synchronize a CACHE with some NEW-TAGS."
(semantic-reset cache))
-(defun semantic-decoration-unparsed-include-refrence-reset (table)
+(defun semantic-decoration-unparsed-include-reference-reset (table)
"Refresh any highlighting in buffers referred to by TABLE.
If TABLE is not in a buffer, do nothing."
;; This cache removal may seem odd in that we are "creating one", but
@@ -835,6 +833,8 @@ If TABLE is not in a buffer, do nothing."
(semantic-decorate-add-decorations allinc)
))))
+(define-obsolete-function-alias 'semantic-decoration-unparsed-include-refrence-reset
+ #'semantic-decoration-unparsed-include-reference-reset "30.1")
(provide 'semantic/decorate/include)
diff --git a/lisp/cedet/semantic/lex-spp.el b/lisp/cedet/semantic/lex-spp.el
index 390c13ec98b..f3704f9a4d4 100644
--- a/lisp/cedet/semantic/lex-spp.el
+++ b/lisp/cedet/semantic/lex-spp.el
@@ -1243,7 +1243,7 @@ Finds the header file belonging to NAME, gets the macros
from that file, and then merge the macros with our current
symbol table."
(when semantic-lex-spp-use-headers-flag
- ;; @todo - do this someday, ok?
+ nil ; @todo - do this someday, ok?
))
(defmacro define-lex-spp-include-analyzer (name doc regexp tokidx
diff --git a/lisp/cedet/semantic/lex.el b/lisp/cedet/semantic/lex.el
index 264b2027711..e4bce67c6f7 100644
--- a/lisp/cedet/semantic/lex.el
+++ b/lisp/cedet/semantic/lex.el
@@ -1108,7 +1108,7 @@ This can be done by using `semantic-lex-push-token'."
(semantic-lex-analysis-bounds (cons (point) (point-max)))
(semantic-lex-current-depth 0)
(semantic-lex-maximum-depth semantic-lex-depth))
- (when ,condition ,@forms)
+ (when ,condition nil ,@forms) ; `nil' avoids an empty-body warning.
semantic-lex-token-stream))))
(defmacro define-lex-regex-analyzer (name doc regexp &rest forms)
diff --git a/lisp/comint.el b/lisp/comint.el
index fd0e06a3612..77d213574f3 100644
--- a/lisp/comint.el
+++ b/lisp/comint.el
@@ -4119,9 +4119,15 @@ function called, or nil, if no function was called (if BEG = END)."
(save-restriction
(let ((beg2 beg1)
(end2 end1))
- (when (= beg2 beg)
+ (when (and (= beg2 beg)
+ (> beg2 (point-min))
+ (eq is-output
+ (eq (get-text-property (1- beg2) 'field) 'output)))
(setq beg2 (field-beginning beg2)))
- (when (= end2 end)
+ (when (and (= end2 end)
+ (< end2 (point-max))
+ (eq is-output
+ (eq (get-text-property (1+ end2) 'field) 'output)))
(setq end2 (field-end end2)))
;; Narrow to the whole field surrounding the region
(narrow-to-region beg2 end2))
diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el
index ab2f74dbb88..65eb066a554 100644
--- a/lisp/cus-edit.el
+++ b/lisp/cus-edit.el
@@ -903,9 +903,9 @@ This also shows the saved values in the buffer."
(defun custom-reset-standard-save-and-update ()
"Save settings and redraw after erasing customizations."
(when (or (and custom-reset-standard-variables-list
- (not (eq custom-reset-standard-variables-list '(t))))
+ (not (equal custom-reset-standard-variables-list '(t))))
(and custom-reset-standard-faces-list
- (not (eq custom-reset-standard-faces-list '(t)))))
+ (not (equal custom-reset-standard-faces-list '(t)))))
;; Save settings to file.
(custom-save-all)
;; Set state of and redraw variables.
@@ -1238,7 +1238,7 @@ Show the buffer in another window, but don't select it."
(unless (eq symbol basevar)
(message "`%s' is an alias for `%s'" symbol basevar))))
-(defvar customize-changed-options-previous-release "28.2"
+(defvar customize-changed-options-previous-release "29.1"
"Version for `customize-changed' to refer back to by default.")
;; Packages will update this variable, so make it available.
diff --git a/lisp/descr-text.el b/lisp/descr-text.el
index f2ffddcf702..f105f292448 100644
--- a/lisp/descr-text.el
+++ b/lisp/descr-text.el
@@ -366,7 +366,7 @@ This function is semi-obsolete. Use `get-char-code-property'."
;; description is added to the category name as a tooltip
(defsubst describe-char-categories (category-set)
(let ((mnemonics (category-set-mnemonics category-set)))
- (unless (eq mnemonics "")
+ (unless (equal mnemonics "")
(list (mapconcat
(lambda (x)
(let* ((c (category-docstring x))
diff --git a/lisp/desktop.el b/lisp/desktop.el
index ef73bc596df..d55739bb6f8 100644
--- a/lisp/desktop.el
+++ b/lisp/desktop.el
@@ -828,7 +828,7 @@ is nil, ask the user where to save the desktop."
;; If we own it, we don't anymore.
(when (eq (emacs-pid) (desktop-owner))
;; Allow exiting Emacs even if we can't delete the desktop file.
- (ignore-error 'file-error
+ (ignore-error file-error
(desktop-release-lock))))
;; ----------------------------------------------------------------------------
diff --git a/lisp/elide-head.el b/lisp/elide-head.el
index e79b582cb14..8a95082c15f 100644
--- a/lisp/elide-head.el
+++ b/lisp/elide-head.el
@@ -50,24 +50,41 @@
:group 'tools)
(defcustom elide-head-headers-to-hide
- `(;; GNU GPL
- ("is free software[:;] you can redistribute it" .
- ,(rx (or (seq "If not, see " (? "<")
- "http" (? "s") "://www.gnu.org/licenses"
- (? "/") (? ">") (? " "))
- (seq "Boston, MA " (? " ")
- "0211" (or "1-1307" "0-1301")
- (or " " ", ") "USA")
- "675 Mass Ave, Cambridge, MA 02139, USA")
- (? ".")))
- ;; FreeBSD license / Modified BSD license (3-clause)
- (,(rx (or "The Regents of the University of California. All rights reserved."
- "Redistribution and use in source and binary"))
- . "POSSIBILITY OF SUCH DAMAGE\\.")
- ;; X11 and Expat
- ("Permission is hereby granted, free of charge" .
- ,(rx (or "authorization from the X Consortium." ; X11
- "THE USE OR OTHER DEALINGS IN THE SOFTWARE.")))) ; Expat
+ (rx-let ((delim
+ ;; A line break could be in a non-standard place, and the
+ ;; license could be in a comment.
+ (or
+ ;; Either just some spaces:
+ (+ " ")
+ ;; Or a newline and some comment starter:
+ (: (* (in " \t"))
+ "\n"
+ (* (in " \t"))
+ (* (or (syntax comment-start) (in ";#*-")))
+ (* (in " \t"))))))
+ `(;; GNU GPL
+ ("is free software[:;] you can redistribute it" .
+ ,(rx (or (seq "If not, see " (? "<")
+ "http" (? "s") "://www.gnu.org/licenses"
+ (? "/") (? ">") (? " "))
+ (seq "Boston," delim "MA" delim
+ (or "02111-1307" "02110-1301" "02111-1301")
+ (? ",") delim
+ "USA")
+ "675 Mass Ave, Cambridge, MA 02139, USA")
+ (? ".")))
+ ;; FreeBSD license / Modified BSD license (3-clause)
+ (,(rx (or "The Regents of the University of California. All rights reserved."
+ "Redistribution and use in source and binary"))
+ . "POSSIBILITY OF SUCH DAMAGE\\.")
+ ;; X11 and Expat
+ ("Permission is hereby granted, free of charge" .
+ ,(rx (or "authorization from the X Consortium." ; X11
+ "THE USE OR OTHER DEALINGS IN THE SOFTWARE."))) ; Expat
+ ;; Apache
+ ("Licensed under the Apache License, Version 2.0" .
+ "limitations under the License.")
+ ))
"Alist of regexps defining start and end of text to elide.
The cars of elements of the list are searched for in order. Text is
@@ -78,7 +95,7 @@ cdr.
This affects `elide-head-mode'."
:type '(alist :key-type (regexp :tag "Start regexp")
:value-type (regexp :tag "End regexp"))
- :version "29.1")
+ :version "30.1")
(defvar-local elide-head-overlay nil)
diff --git a/lisp/emacs-lisp/byte-opt.el b/lisp/emacs-lisp/byte-opt.el
index a7e1df3622d..ab35b0dde8f 100644
--- a/lisp/emacs-lisp/byte-opt.el
+++ b/lisp/emacs-lisp/byte-opt.el
@@ -410,7 +410,10 @@ for speeding up processing.")
(`(condition-case ,var ,exp . ,clauses)
`(,fn ,var ;Not evaluated.
- ,(byte-optimize-form exp for-effect)
+ ,(byte-optimize-form exp
+ (if (assq :success clauses)
+ (null var)
+ for-effect))
,@(mapcar (lambda (clause)
(let ((byte-optimize--lexvars
(and lexical-binding
@@ -755,7 +758,8 @@ for speeding up processing.")
((eq head 'list) (cdr form))
((memq head
;; FIXME: Replace this list with a function property?
- '( length safe-length cons lambda
+ '( lambda internal-make-closure
+ length safe-length cons
string unibyte-string make-string concat
format format-message
substring substring-no-properties string-replace
@@ -1297,11 +1301,8 @@ See Info node `(elisp) Integer Basics'."
(if else
`(progn ,condition ,@else)
condition))
- ;; (if X nil t) -> (not X)
- ((and (eq then nil) (eq else '(t)))
- `(not ,condition))
- ;; (if X t [nil]) -> (not (not X))
- ((and (eq then t) (or (null else) (eq else '(nil))))
+ ;; (if X t) -> (not (not X))
+ ((and (eq then t) (null else))
`(not ,(byte-opt--negate condition)))
;; (if VAR VAR X...) -> (or VAR (progn X...))
((and (symbolp condition) (eq condition then))
diff --git a/lisp/emacs-lisp/byte-run.el b/lisp/emacs-lisp/byte-run.el
index 1babf3ec2c4..697d1d3ee74 100644
--- a/lisp/emacs-lisp/byte-run.el
+++ b/lisp/emacs-lisp/byte-run.el
@@ -649,11 +649,11 @@ in `byte-compile-warning-types'; see the variable
`byte-compile-warnings' for a fuller explanation of the warning
types. The types that can be suppressed with this macro are
`free-vars', `callargs', `redefine', `obsolete',
-`interactive-only', `lexical', `mapcar', `constants' and
-`suspicious'.
+`interactive-only', `lexical', `mapcar', `constants',
+`suspicious' and `empty-body'.
For the `mapcar' case, only the `mapcar' function can be used in
-the symbol list. For `suspicious', only `set-buffer' and `lsh' can be used."
+the symbol list."
;; Note: during compilation, this definition is overridden by the one in
;; byte-compile-initial-macro-environment.
(declare (debug (sexp body)) (indent 1))
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index f176e769bf5..e314976fc1a 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -295,7 +295,8 @@ The information is logged to `byte-compile-log-buffer'."
'(redefine callargs free-vars unresolved
obsolete noruntime interactive-only
make-local mapcar constants suspicious lexical lexical-dynamic
- docstrings docstrings-non-ascii-quotes not-unused)
+ docstrings docstrings-non-ascii-quotes not-unused
+ empty-body)
"The list of warning types used when `byte-compile-warnings' is t.")
(defcustom byte-compile-warnings t
"List of warnings that the byte-compiler should issue (t for almost all).
@@ -326,6 +327,7 @@ Elements of the list may be:
docstrings-non-ascii-quotes docstrings that have non-ASCII quotes.
This depends on the `docstrings' warning type.
suspicious constructs that usually don't do what the coder wanted.
+ empty-body body argument to a special form or macro is empty.
If the list begins with `not', then the remaining elements specify warnings to
suppress. For example, (not mapcar) will suppress warnings about mapcar.
@@ -541,15 +543,19 @@ Return the compile-time value of FORM."
;; Later `internal--with-suppressed-warnings' binds it again, this
;; time in order to affect warnings emitted during the
;; compilation itself.
- (let ((byte-compile--suppressed-warnings
- (append warnings byte-compile--suppressed-warnings)))
- ;; This function doesn't exist, but is just a placeholder
- ;; symbol to hook up with the
- ;; `byte-hunk-handler'/`byte-defop-compiler-1' machinery.
- `(internal--with-suppressed-warnings
- ',warnings
- ,(macroexpand-all `(progn ,@body)
- macroexpand-all-environment))))))
+ (if body
+ (let ((byte-compile--suppressed-warnings
+ (append warnings byte-compile--suppressed-warnings)))
+ ;; This function doesn't exist, but is just a placeholder
+ ;; symbol to hook up with the
+ ;; `byte-hunk-handler'/`byte-defop-compiler-1' machinery.
+ `(internal--with-suppressed-warnings
+ ',warnings
+ ,(macroexpand-all `(progn ,@body)
+ macroexpand-all-environment)))
+ (macroexp-warn-and-return
+ "`with-suppressed-warnings' with empty body"
+ nil '(empty-body with-suppressed-warnings) t warnings)))))
"The default macro-environment passed to macroexpand by the compiler.
Placing a macro here will cause a macro to have different semantics when
expanded by the compiler as when expanded by the interpreter.")
@@ -4835,6 +4841,11 @@ binding slots have been popped."
(dolist (clause (reverse clauses))
(let ((condition (nth 1 clause)))
+ (when (and (eq (car-safe condition) 'quote)
+ (cdr condition) (null (cddr condition)))
+ (byte-compile-warn-x
+ condition "`condition-case' condition should not be quoted: %S"
+ condition))
(unless (consp condition) (setq condition (list condition)))
(dolist (c condition)
(unless (and c (symbolp c))
@@ -5487,6 +5498,83 @@ and corresponding effects."
(eval form)
form)))
+;; Check for (in)comparable constant values in calls to `eq', `memq' etc.
+
+(defun bytecomp--dodgy-eq-arg-p (x number-ok)
+ "Whether X is a bad argument to `eq' (or `eql' if NUMBER-OK is non-nil)."
+ (pcase x
+ ((or `(quote ,(pred consp)) `(function (lambda . ,_))) t)
+ ((or (pred consp) (pred symbolp)) nil)
+ ((pred integerp)
+ (not (or (<= -536870912 x 536870911) number-ok)))
+ ((pred floatp) (not number-ok))
+ (_ t)))
+
+(defun bytecomp--value-type-description (x)
+ (cond
+ ((proper-list-p x) "list")
+ ((recordp x) "record")
+ (t (symbol-name (type-of x)))))
+
+(defun bytecomp--arg-type-description (x)
+ (pcase x
+ (`(function (lambda . ,_)) "function")
+ (`(quote . ,val) (bytecomp--value-type-description val))
+ (_ (bytecomp--value-type-description x))))
+
+(defun bytecomp--warn-dodgy-eq-arg (form type parenthesis)
+ (macroexp-warn-and-return
+ (format "`%s' called with literal %s that may never match (%s)"
+ (car form) type parenthesis)
+ form (list 'suspicious (car form)) t))
+
+(defun bytecomp--check-eq-args (form &optional a b &rest _ignore)
+ (let* ((number-ok (eq (car form) 'eql))
+ (bad-arg (cond ((bytecomp--dodgy-eq-arg-p a number-ok) 1)
+ ((bytecomp--dodgy-eq-arg-p b number-ok) 2))))
+ (if bad-arg
+ (bytecomp--warn-dodgy-eq-arg
+ form
+ (bytecomp--arg-type-description (nth bad-arg form))
+ (format "arg %d" bad-arg))
+ form)))
+
+(put 'eq 'compiler-macro #'bytecomp--check-eq-args)
+(put 'eql 'compiler-macro #'bytecomp--check-eq-args)
+
+(defun bytecomp--check-memq-args (form &optional elem list &rest _ignore)
+ (let* ((fn (car form))
+ (number-ok (eq fn 'memql)))
+ (cond
+ ((bytecomp--dodgy-eq-arg-p elem number-ok)
+ (bytecomp--warn-dodgy-eq-arg
+ form (bytecomp--arg-type-description elem) "arg 1"))
+ ((and (consp list) (eq (car list) 'quote)
+ (proper-list-p (cadr list)))
+ (named-let loop ((elts (cadr list)) (i 1))
+ (if elts
+ (let* ((elt (car elts))
+ (x (cond ((eq fn 'assq) (car-safe elt))
+ ((eq fn 'rassq) (cdr-safe elt))
+ (t elt))))
+ (if (or (symbolp x)
+ (and (integerp x)
+ (or (<= -536870912 x 536870911) number-ok))
+ (and (floatp x) number-ok))
+ (loop (cdr elts) (1+ i))
+ (bytecomp--warn-dodgy-eq-arg
+ form (bytecomp--value-type-description x)
+ (format "element %d of arg 2" i))))
+ form)))
+ (t form))))
+
+(put 'memq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'memql 'compiler-macro #'bytecomp--check-memq-args)
+(put 'assq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'rassq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'remq 'compiler-macro #'bytecomp--check-memq-args)
+(put 'delq 'compiler-macro #'bytecomp--check-memq-args)
+
(provide 'byte-compile)
(provide 'bytecomp)
diff --git a/lisp/emacs-lisp/cl-macs.el b/lisp/emacs-lisp/cl-macs.el
index 43a2ed92059..95e78ceab6a 100644
--- a/lisp/emacs-lisp/cl-macs.el
+++ b/lisp/emacs-lisp/cl-macs.el
@@ -2052,7 +2052,8 @@ info node `(cl) Function Bindings' for details.
(dolist (binding bindings)
(let ((var (make-symbol (format "--cl-%s--" (car binding))))
(args-and-body (cdr binding)))
- (if (and (= (length args-and-body) 1) (symbolp (car args-and-body)))
+ (if (and (= (length args-and-body) 1)
+ (macroexp-copyable-p (car args-and-body)))
;; Optimize (cl-flet ((fun var)) body).
(setq var (car args-and-body))
(push (list var (if (= (length args-and-body) 1)
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el
index 2df390ecbeb..7d54a84687b 100644
--- a/lisp/emacs-lisp/easy-mmode.el
+++ b/lisp/emacs-lisp/easy-mmode.el
@@ -417,6 +417,8 @@ No problems result if this variable is not bound.
`(defvar ,keymap-sym
(let ((m ,keymap))
(cond ((keymapp m) m)
+ ;; FIXME: `easy-mmode-define-keymap' is obsolete,
+ ;; so this form should also be obsolete somehow.
((listp m)
(with-suppressed-warnings ((obsolete
easy-mmode-define-keymap))
@@ -682,6 +684,7 @@ Valid keywords and arguments are:
:group Ignored.
:suppress Non-nil to call `suppress-keymap' on keymap,
`nodigits' to suppress digits as prefix arguments."
+ (declare (obsolete define-keymap "29.1"))
(let (inherit dense suppress)
(while args
(let ((key (pop args))
@@ -722,9 +725,7 @@ The M, BS, and ARGS arguments are as per that function. DOC is
the constant's documentation.
This macro is deprecated; use `defvar-keymap' instead."
- ;; FIXME: Declare obsolete in favor of `defvar-keymap'. It is still
- ;; used for `gud-menu-map' and `gud-minor-mode-map', so fix that first.
- (declare (doc-string 3) (indent 1))
+ (declare (doc-string 3) (indent 1) (obsolete defvar-keymap "29.1"))
`(defconst ,m
(easy-mmode-define-keymap ,bs nil (if (boundp ',m) ,m) ,(cons 'list args))
,doc))
diff --git a/lisp/emacs-lisp/gv.el b/lisp/emacs-lisp/gv.el
index 11251d7a963..48bc0269f36 100644
--- a/lisp/emacs-lisp/gv.el
+++ b/lisp/emacs-lisp/gv.el
@@ -417,9 +417,9 @@ The return value is the last VAL in the list.
(lambda (do key alist &optional default remove testfn)
(macroexp-let2 macroexp-copyable-p k key
(gv-letplace (getter setter) alist
- (macroexp-let2 nil p `(if (and ,testfn (not (eq ,testfn 'eq)))
- (assoc ,k ,getter ,testfn)
- (assq ,k ,getter))
+ (macroexp-let2 nil p (if (member testfn '(nil 'eq #'eq))
+ `(assq ,k ,getter)
+ `(assoc ,k ,getter ,testfn))
(funcall do (if (null default) `(cdr ,p)
`(if ,p (cdr ,p) ,default))
(lambda (v)
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index f4df40249de..d8c0cd5c7bd 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -367,8 +367,8 @@ Assumes the caller has bound `macroexpand-all-environment'."
(if (null body)
(macroexp-unprogn
(macroexp-warn-and-return
- (format "Empty %s body" fun)
- nil nil 'compile-only fun))
+ (format "`%s' with empty body" fun)
+ nil (list 'empty-body fun) 'compile-only fun))
(macroexp--all-forms body))
(cdr form))
form)))
@@ -486,7 +486,7 @@ Assumes the caller has bound `macroexpand-all-environment'."
(setq form (macroexp--compiler-macro handler newform))
(if (eq newform form)
newform
- (macroexp--expand-all newform)))
+ (macroexp--expand-all form)))
(macroexp--expand-all newform))))))
(_ form))))
(pop byte-compile-form-stack)))
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index 73c4f896a49..1ab70eb2fe9 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -4562,6 +4562,7 @@ will be signaled in that case."
(package--print-email-button maint)
(string-trim (substring-no-properties (buffer-string))))))))
+;;;###autoload
(defun package-report-bug (desc)
"Prepare a message to send to the maintainers of a package.
DESC must be a `package-desc' object."
diff --git a/lisp/emulation/viper-cmd.el b/lisp/emulation/viper-cmd.el
index 26793989d05..3b3caaf3e3c 100644
--- a/lisp/emulation/viper-cmd.el
+++ b/lisp/emulation/viper-cmd.el
@@ -194,9 +194,9 @@
viper-delete-backward-char
viper-join-lines
viper-delete-char))
- (memq (viper-event-key last-command-event)
- '(up down left right (meta f) (meta b)
- (control n) (control p) (control f) (control b)))))
+ (member (viper-event-key last-command-event)
+ '(up down left right (meta f) (meta b)
+ (control n) (control p) (control f) (control b)))))
(defsubst viper-insert-state-pre-command-sentinel ()
(or (viper-preserve-cursor-color)
diff --git a/lisp/eshell/em-alias.el b/lisp/eshell/em-alias.el
index 9ad218d5988..9b75c7a1237 100644
--- a/lisp/eshell/em-alias.el
+++ b/lisp/eshell/em-alias.el
@@ -183,7 +183,9 @@ file named by `eshell-aliases-file'.")
(pcomplete-here (eshell-alias-completions pcomplete-stub)))
(defun eshell-read-aliases-list ()
- "Read in an aliases list from `eshell-aliases-file'."
+ "Read in an aliases list from `eshell-aliases-file'.
+This is useful after manually editing the contents of the file."
+ (interactive)
(let ((file eshell-aliases-file))
(when (file-readable-p file)
(setq eshell-command-aliases-list
diff --git a/lisp/eshell/em-cmpl.el b/lisp/eshell/em-cmpl.el
index ac82e3f225c..2c721eb9e31 100644
--- a/lisp/eshell/em-cmpl.el
+++ b/lisp/eshell/em-cmpl.el
@@ -342,17 +342,23 @@ to writing a completion function."
(setq pos (1+ pos))))
(setq posns (cdr posns))
(cl-assert (= (length args) (length posns)))
- (let ((a args)
- (i 0)
- l)
+ (let ((a args) (i 0) new-start)
(while a
- (if (and (consp (car a))
- (eq (caar a) 'eshell-operator))
- (setq l i))
- (setq a (cdr a) i (1+ i)))
- (and l
- (setq args (nthcdr (1+ l) args)
- posns (nthcdr (1+ l) posns))))
+ ;; Remove any top-level `eshell-splice-args' sigils. These
+ ;; are meant to be rewritten and can't actually be called.
+ (when (and (consp (car a))
+ (eq (caar a) 'eshell-splice-args))
+ (setcar a (cadar a)))
+ ;; If there's an unreplaced `eshell-operator' sigil, consider
+ ;; the token after it the new start of our arguments.
+ (when (and (consp (car a))
+ (eq (caar a) 'eshell-operator))
+ (setq new-start i))
+ (setq a (cdr a)
+ i (1+ i)))
+ (when new-start
+ (setq args (nthcdr (1+ new-start) args)
+ posns (nthcdr (1+ new-start) posns))))
(cl-assert (= (length args) (length posns)))
(when (and args (eq (char-syntax (char-before end)) ? )
(not (eq (char-before (1- end)) ?\\)))
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index 4b5e4dd53ed..3f7ec618a33 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -786,10 +786,14 @@ external command."
(defun eshell-complete-host-reference ()
"If there is a host reference, complete it."
- (let ((arg (pcomplete-actual-arg))
- index)
- (when (setq index (string-match "@[a-z.]*\\'" arg))
- (setq pcomplete-stub (substring arg (1+ index))
+ (let ((arg (pcomplete-actual-arg)))
+ (when (string-match
+ (rx ;; Match an "@", but not immediately following a "$".
+ (or string-start (not "$")) "@"
+ (group (* (any "a-z.")))
+ string-end)
+ arg)
+ (setq pcomplete-stub (substring arg (match-beginning 1))
pcomplete-last-completion-raw t)
(throw 'pcomplete-completions (pcomplete-read-host-names)))))
diff --git a/lisp/eshell/esh-arg.el b/lisp/eshell/esh-arg.el
index 48ac3e2bd4d..87121196715 100644
--- a/lisp/eshell/esh-arg.el
+++ b/lisp/eshell/esh-arg.el
@@ -238,13 +238,53 @@ convert the result to a number as well."
(eshell-convert-to-number result)
result)))
+(defun eshell-concat-groups (quoted &rest args)
+ "Concatenate groups of arguments in ARGS and return the result.
+QUOTED is passed to `eshell-concat' (which see) and, if non-nil,
+allows values to be converted to numbers where appropriate.
+
+ARGS should be a list of lists of arguments, such as that
+produced by `eshell-prepare-slice'. \"Adjacent\" values of
+consecutive arguments will be passed to `eshell-concat'. For
+example, if ARGS is
+
+ ((list a) (list b) (list c d e) (list f g)),
+
+then the result will be:
+
+ ((eshell-concat QUOTED a b c)
+ d
+ (eshell-concat QUOTED e f)
+ g)."
+ (let (result current-arg)
+ (dolist (arg args)
+ (when arg
+ (push (car arg) current-arg)
+ (when (length> arg 1)
+ (push (apply #'eshell-concat quoted (nreverse current-arg))
+ result)
+ (dolist (inner (butlast (cdr arg)))
+ (push inner result))
+ (setq current-arg (list (car (last arg)))))))
+ (when current-arg
+ (push (apply #'eshell-concat quoted (nreverse current-arg))
+ result))
+ (nreverse result)))
+
(defun eshell-resolve-current-argument ()
"If there are pending modifications to be made, make them now."
(when eshell-current-argument
(when eshell-arg-listified
- (setq eshell-current-argument
- (append (list 'eshell-concat eshell-current-quoted)
- eshell-current-argument))
+ (if-let ((grouped-terms (eshell-prepare-splice
+ eshell-current-argument)))
+ (setq eshell-current-argument
+ `(eshell-splice-args
+ (eshell-concat-groups ,eshell-current-quoted
+ ,@grouped-terms)))
+ ;; If no terms are spliced, use a simpler command form.
+ (setq eshell-current-argument
+ (append (list 'eshell-concat eshell-current-quoted)
+ eshell-current-argument)))
(setq eshell-arg-listified nil))
(while eshell-current-modifiers
(setq eshell-current-argument
@@ -261,7 +301,8 @@ argument list in place of the value of the current argument."
(setq eshell-current-argument (car arguments))
(cl-assert (and (not eshell-arg-listified)
(not eshell-current-modifiers)))
- (setq eshell-current-argument (cons 'eshell-flatten-args arguments))))
+ (setq eshell-current-argument
+ (cons 'eshell-splice-immediately arguments))))
(throw 'eshell-arg-done t))
(defun eshell-quote-argument (string)
@@ -302,7 +343,8 @@ Point is left at the end of the arguments."
(buffer-substring here (point-max))))
(when arg
(nconc args
- (if (eq (car-safe arg) 'eshell-flatten-args)
+ (if (eq (car-safe arg)
+ 'eshell-splice-immediately)
(cdr arg)
(list arg))))))))
(throw 'eshell-incomplete (if (listp delim)
@@ -348,6 +390,10 @@ Point is left at the end of the arguments."
"A stub function that generates an error if a floating operator is found."
(error "Unhandled operator in input text"))
+(defsubst eshell-splice-args (&rest _args)
+ "A stub function that generates an error if a floating splice is found."
+ (error "Splice operator is not permitted in this context"))
+
(defsubst eshell-looking-at-backslash-return (pos)
"Test whether a backslash-return sequence occurs at POS."
(and (eq (char-after pos) ?\\)
@@ -377,20 +423,24 @@ after are both returned."
(when (eshell-looking-at-backslash-return (point))
(throw 'eshell-incomplete ?\\))
(forward-char 2) ; Move one char past the backslash.
- (if (eq (char-before) ?\n)
- ;; Escaped newlines are extra-special: they expand to an empty
- ;; token to allow for continuing Eshell commands across
- ;; multiple lines.
- 'eshell-empty-token
- ;; If the char is in a quote, backslash only has special meaning
- ;; if it is escaping a special char.
- (if eshell-current-quoted
- (if (memq (char-before) eshell-special-chars-inside-quoting)
- (list 'eshell-escape-arg (char-to-string (char-before)))
- (concat "\\" (char-to-string (char-before))))
- (if (memq (char-before) eshell-special-chars-outside-quoting)
- (list 'eshell-escape-arg (char-to-string (char-before)))
- (char-to-string (char-before)))))))
+ (let ((special-chars (if eshell-current-quoted
+ eshell-special-chars-inside-quoting
+ eshell-special-chars-outside-quoting)))
+ (cond
+ ;; Escaped newlines are extra-special: they expand to an empty
+ ;; token to allow for continuing Eshell commands across
+ ;; multiple lines.
+ ((eq (char-before) ?\n)
+ 'eshell-empty-token)
+ ((memq (char-before) special-chars)
+ (list 'eshell-escape-arg (char-to-string (char-before))))
+ ;; If the char is in a quote, backslash only has special
+ ;; meaning if it is escaping a special char. Otherwise, the
+ ;; result is the literal string "\c".
+ (eshell-current-quoted
+ (concat "\\" (char-to-string (char-before))))
+ (t
+ (char-to-string (char-before)))))))
(defun eshell-parse-literal-quote ()
"Parse a literally quoted string. Nothing has special meaning!"
@@ -496,5 +546,32 @@ If the form has no `type', the syntax is parsed as if `type' were
(char-to-string (char-after)))))
(goto-char end)))))))
+(defun eshell-prepare-splice (args)
+ "Prepare a list of ARGS for splicing, if any arg requested a splice.
+This looks for `eshell-splice-args' as the CAR of each argument,
+and if found, returns a grouped list like:
+
+ ((list arg-1) (list arg-2) spliced-arg-3 ...)
+
+This allows callers of this function to build the final spliced
+list by concatenating each element together, e.g. with (apply
+#'append grouped-list).
+
+If no argument requested a splice, return nil."
+ (let* ((splicep nil)
+ ;; Group each arg like ((list arg-1) (list arg-2) ...),
+ ;; splicing in `eshell-splice-args' args. This lets us
+ ;; apply spliced args correctly elsewhere.
+ (grouped-args
+ (mapcar (lambda (i)
+ (if (eq (car-safe i) 'eshell-splice-args)
+ (progn
+ (setq splicep t)
+ (cadr i))
+ `(list ,i)))
+ args)))
+ (when splicep
+ grouped-args)))
+
(provide 'esh-arg)
;;; esh-arg.el ends here
diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el
index 4a41bbe8fa1..39579335cf7 100644
--- a/lisp/eshell/esh-cmd.el
+++ b/lisp/eshell/esh-cmd.el
@@ -418,8 +418,11 @@ hooks should be run before and after the command."
(eshell-separate-commands terms "[&;]" nil 'eshell--sep-terms))))
(let ((cmd commands))
(while cmd
- (if (cdr cmd)
- (setcar cmd `(eshell-commands ,(car cmd))))
+ ;; Copy I/O handles so each full statement can manipulate them
+ ;; if they like. Steal the handles for the last command in
+ ;; the list; we won't use the originals again anyway.
+ (setcar cmd `(eshell-with-copied-handles
+ ,(car cmd) ,(not (cdr cmd))))
(setq cmd (cdr cmd))))
(if toplevel
`(eshell-commands (progn
@@ -480,11 +483,16 @@ hooks should be run before and after the command."
(let ((sym (if eshell-in-pipeline-p
'eshell-named-command*
'eshell-named-command))
- (cmd (car terms))
- (args (cdr terms)))
- (if args
- (list sym cmd `(list ,@(cdr terms)))
- (list sym cmd))))
+ (grouped-terms (eshell-prepare-splice terms)))
+ (cond
+ (grouped-terms
+ `(let ((terms (nconc ,@grouped-terms)))
+ (,sym (car terms) (cdr terms))))
+ ;; If no terms are spliced, use a simpler command form.
+ ((cdr terms)
+ (list sym (car terms) `(list ,@(cdr terms))))
+ (t
+ (list sym (car terms))))))
(defvar eshell-command-body)
(defvar eshell-test-body)
@@ -783,16 +791,17 @@ this grossness will be made to disappear by using `call/cc'..."
(defvar eshell-output-handle) ;Defined in esh-io.el.
(defvar eshell-error-handle) ;Defined in esh-io.el.
-(defmacro eshell-copy-handles (object)
- "Duplicate current I/O handles, so OBJECT works with its own copy."
+(defmacro eshell-with-copied-handles (object &optional steal-p)
+ "Duplicate current I/O handles, so OBJECT works with its own copy.
+If STEAL-P is non-nil, these new handles will be stolen from the
+current ones (see `eshell-duplicate-handles')."
`(let ((eshell-current-handles
- (eshell-create-handles
- (car (aref eshell-current-handles
- eshell-output-handle)) nil
- (car (aref eshell-current-handles
- eshell-error-handle)) nil)))
+ (eshell-duplicate-handles eshell-current-handles ,steal-p)))
,object))
+(define-obsolete-function-alias 'eshell-copy-handles
+ #'eshell-with-copied-handles "30.1")
+
(defmacro eshell-protect (object)
"Protect I/O handles, so they aren't get closed after eval'ing OBJECT."
`(progn
@@ -803,7 +812,7 @@ this grossness will be made to disappear by using `call/cc'..."
"Execute the commands in PIPELINE, connecting each to one another.
This macro calls itself recursively, with NOTFIRST non-nil."
(when (setq pipeline (cadr pipeline))
- `(eshell-copy-handles
+ `(eshell-with-copied-handles
(progn
,(when (cdr pipeline)
`(let ((nextproc
@@ -828,7 +837,9 @@ This macro calls itself recursively, with NOTFIRST non-nil."
(let ((proc ,(car pipeline)))
(set headproc (or proc (symbol-value headproc)))
(set tailproc (or (symbol-value tailproc) proc))
- proc))))))
+ proc)))
+ ;; Steal handles if this is the last item in the pipeline.
+ ,(null (cdr pipeline)))))
(defmacro eshell-do-pipelines-synchronously (pipeline)
"Execute the commands in PIPELINE in sequence synchronously.
@@ -875,11 +886,8 @@ This is used on systems where async subprocesses are not supported."
(progn
,(if (fboundp 'make-process)
`(eshell-do-pipelines ,pipeline)
- `(let ((tail-handles (eshell-create-handles
- (car (aref eshell-current-handles
- ,eshell-output-handle)) nil
- (car (aref eshell-current-handles
- ,eshell-error-handle)) nil)))
+ `(let ((tail-handles (eshell-duplicate-handles
+ eshell-current-handles)))
(eshell-do-pipelines-synchronously ,pipeline)))
(eshell-process-identity (cons (symbol-value headproc)
(symbol-value tailproc))))))
@@ -1019,7 +1027,9 @@ produced by `eshell-parse-command'."
;; We can just stick the new command at the end of the current
;; one, and everything will happen as it should.
(setcdr (last (cdr eshell-current-command))
- (list `(let ((here (and (eobp) (point))))
+ (list `(let ((here (and (eobp) (point)))
+ (eshell-command-body '(nil))
+ (eshell-test-body '(nil)))
,(and input
`(insert-and-inherit ,(concat input "\n")))
(if here
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el
index d223be680f9..90826a312b3 100644
--- a/lisp/eshell/esh-io.el
+++ b/lisp/eshell/esh-io.el
@@ -116,16 +116,22 @@ from executing while Emacs is redisplaying."
:group 'eshell-io)
(defcustom eshell-virtual-targets
- '(("/dev/eshell" eshell-interactive-print nil)
+ '(;; The literal string "/dev/null" is intentional here. It just
+ ;; provides compatibility so that users can redirect to
+ ;; "/dev/null" no matter the actual value of `null-device'.
+ ("/dev/null" (lambda (_mode) (throw 'eshell-null-device t)) t)
+ ("/dev/eshell" eshell-interactive-print nil)
("/dev/kill" (lambda (mode)
- (if (eq mode 'overwrite)
- (kill-new ""))
- 'eshell-kill-append) t)
+ (when (eq mode 'overwrite)
+ (kill-new ""))
+ #'eshell-kill-append)
+ t)
("/dev/clip" (lambda (mode)
- (if (eq mode 'overwrite)
- (let ((select-enable-clipboard t))
- (kill-new "")))
- 'eshell-clipboard-append) t))
+ (when (eq mode 'overwrite)
+ (let ((select-enable-clipboard t))
+ (kill-new "")))
+ #'eshell-clipboard-append)
+ t))
"Map virtual devices name to Emacs Lisp functions.
If the user specifies any of the filenames above as a redirection
target, the function in the second element will be called.
@@ -138,10 +144,8 @@ function.
The output function is then called repeatedly with single strings,
which represents successive pieces of the output of the command, until nil
-is passed, meaning EOF.
-
-NOTE: /dev/null is handled specially as a virtual target, and should
-not be added to this variable."
+is passed, meaning EOF."
+ :version "30.1"
:type '(repeat
(list (string :tag "Target")
function
@@ -291,25 +295,58 @@ describing the mode, e.g. for using with `eshell-get-target'.")
(defun eshell-create-handles
(stdout output-mode &optional stderr error-mode)
"Create a new set of file handles for a command.
-The default location for standard output and standard error will go to
-STDOUT and STDERR, respectively.
-OUTPUT-MODE and ERROR-MODE are either `overwrite', `append' or `insert';
-a nil value of mode defaults to `insert'."
+The default target for standard output and standard error will
+go to STDOUT and STDERR, respectively. OUTPUT-MODE and
+ERROR-MODE are either `overwrite', `append' or `insert'; a nil
+value of mode defaults to `insert'.
+
+The result is a vector of file handles. Each handle is of the form:
+
+ ((TARGETS . REF-COUNT) DEFAULT)
+
+TARGETS is a list of destinations for output. REF-COUNT is the
+number of references to this handle (initially 1); see
+`eshell-protect-handles' and `eshell-close-handles'. DEFAULT is
+non-nil if handle has its initial default value (always t after
+calling this function)."
(let* ((handles (make-vector eshell-number-of-handles nil))
- (output-target (eshell-get-target stdout output-mode))
- (error-target (if stderr
- (eshell-get-target stderr error-mode)
- output-target)))
- (aset handles eshell-output-handle (cons output-target 1))
- (aset handles eshell-error-handle (cons error-target 1))
+ (output-target
+ (let ((target (eshell-get-target stdout output-mode)))
+ (cons (when target (list target)) 1)))
+ (error-target
+ (if stderr
+ (let ((target (eshell-get-target stderr error-mode)))
+ (cons (when target (list target)) 1))
+ (cl-incf (cdr output-target))
+ output-target)))
+ (aset handles eshell-output-handle (list output-target t))
+ (aset handles eshell-error-handle (list error-target t))
handles))
+(defun eshell-duplicate-handles (handles &optional steal-p)
+ "Create a duplicate of the file handles in HANDLES.
+This uses the targets of each handle in HANDLES, incrementing its
+reference count by one (unless STEAL-P is non-nil). These
+targets are shared between the original set of handles and the
+new one, so the targets are only closed when the reference count
+drops to 0 (see `eshell-close-handles').
+
+This function also sets the DEFAULT field for each handle to
+t (see `eshell-create-handles'). Unlike the targets, this value
+is not shared with the original handles."
+ (let ((dup-handles (make-vector eshell-number-of-handles nil)))
+ (dotimes (idx eshell-number-of-handles)
+ (when-let ((handle (aref handles idx)))
+ (unless steal-p
+ (cl-incf (cdar handle)))
+ (aset dup-handles idx (list (car handle) t))))
+ dup-handles))
+
(defun eshell-protect-handles (handles)
"Protect the handles in HANDLES from a being closed."
(dotimes (idx eshell-number-of-handles)
- (when (aref handles idx)
- (setcdr (aref handles idx)
- (1+ (cdr (aref handles idx))))))
+ (when-let ((handle (aref handles idx)))
+ (cl-incf (cdar handle))))
handles)
(defun eshell-close-handles (&optional exit-code result handles)
@@ -327,46 +364,56 @@ the value already set in `eshell-last-command-result'."
(when result
(cl-assert (eq (car result) 'quote))
(setq eshell-last-command-result (cadr result)))
- (let ((handles (or handles eshell-current-handles)))
+ (let ((handles (or handles eshell-current-handles))
+ (succeeded (= eshell-last-command-status 0)))
(dotimes (idx eshell-number-of-handles)
- (when-let ((handle (aref handles idx)))
- (setcdr handle (1- (cdr handle)))
- (when (= (cdr handle) 0)
- (dolist (target (ensure-list (car (aref handles idx))))
- (eshell-close-target target (= eshell-last-command-status 0)))
- (setcar handle nil))))))
+ (eshell-close-handle (aref handles idx) succeeded))))
+
+(defun eshell-close-handle (handle status)
+ "Close a single HANDLE, taking refcounts into account.
+This will pass STATUS to each target for the handle, which should
+be a non-nil value on successful termination."
+ (when handle
+ (cl-assert (> (cdar handle) 0)
+ "Attempted to close a handle with 0 references")
+ (when (and (> (cdar handle) 0)
+ (= (cl-decf (cdar handle)) 0))
+ (dolist (target (caar handle))
+ (eshell-close-target target status))
+ (setcar (car handle) nil))))
(defun eshell-set-output-handle (index mode &optional target handles)
"Set handle INDEX for the current HANDLES to point to TARGET using MODE.
-If HANDLES is nil, use `eshell-current-handles'."
+If HANDLES is nil, use `eshell-current-handles'.
+
+If the handle is currently set to its default value (see
+`eshell-create-handles'), this will overwrite the targets with
+the new target. Otherwise, it will append the new target to the
+current list of targets."
(when target
- (let ((handles (or handles eshell-current-handles)))
- (if (and (stringp target)
- ;; The literal string "/dev/null" is intentional here.
- ;; It just provides compatibility so that users can
- ;; redirect to "/dev/null" no matter the actual value
- ;; of `null-device'.
- (string= target "/dev/null"))
- (aset handles index nil)
- (let ((where (eshell-get-target target mode))
- (current (car (aref handles index))))
- (if (listp current)
- (unless (member where current)
- (setq current (append current (list where))))
- (setq current (list where)))
- (if (not (aref handles index))
- (aset handles index (cons nil 1)))
- (setcar (aref handles index) current))))))
+ (let* ((handles (or handles eshell-current-handles))
+ (handle (or (aref handles index)
+ (aset handles index (list (cons nil 1) nil))))
+ (defaultp (cadr handle)))
+ (when defaultp
+ (cl-decf (cdar handle))
+ (setcar handle (cons nil 1)))
+ (catch 'eshell-null-device
+ (let ((current (caar handle))
+ (where (eshell-get-target target mode)))
+ (unless (member where current)
+ (setcar (car handle) (append current (list where))))))
+ (setcar (cdr handle) nil))))
(defun eshell-copy-output-handle (index index-to-copy &optional handles)
"Copy the handle INDEX-TO-COPY to INDEX for the current HANDLES.
If HANDLES is nil, use `eshell-current-handles'."
(let* ((handles (or handles eshell-current-handles))
(handle-to-copy (car (aref handles index-to-copy))))
- (setcar (aref handles index)
- (if (listp handle-to-copy)
- (copy-sequence handle-to-copy)
- handle-to-copy))))
+ (when handle-to-copy
+ (cl-incf (cdr handle-to-copy)))
+ (eshell-close-handle (aref handles index) nil)
+ (setcar (aref handles index) handle-to-copy)))
(defun eshell-set-all-output-handles (mode &optional target handles)
"Set output and error HANDLES to point to TARGET using MODE.
@@ -497,9 +544,9 @@ INDEX is the handle index to check. If nil, check
(let ((handles (or handles eshell-current-handles))
(index (or index eshell-output-handle)))
(if (eq index 'all)
- (and (eq (car (aref handles eshell-output-handle)) t)
- (eq (car (aref handles eshell-error-handle)) t))
- (eq (car (aref handles index)) t))))
+ (and (equal (caar (aref handles eshell-output-handle)) '(t))
+ (equal (caar (aref handles eshell-error-handle)) '(t)))
+ (equal (caar (aref handles index)) '(t)))))
(defvar eshell-print-queue nil)
(defvar eshell-print-queue-count -1)
@@ -606,15 +653,10 @@ Returns what was actually sent, or nil if nothing was sent."
If HANDLE-INDEX is nil, output to `eshell-output-handle'.
HANDLES is the set of file handles to use; if nil, use
`eshell-current-handles'."
- (let ((target (car (aref (or handles eshell-current-handles)
- (or handle-index eshell-output-handle)))))
- (if (listp target)
- (while target
- (eshell-output-object-to-target object (car target))
- (setq target (cdr target)))
- (eshell-output-object-to-target object target)
- ;; Explicitly return nil to match the list case above.
- nil)))
+ (let ((targets (caar (aref (or handles eshell-current-handles)
+ (or handle-index eshell-output-handle)))))
+ (dolist (target targets)
+ (eshell-output-object-to-target object target))))
(provide 'esh-io)
;;; esh-io.el ends here
diff --git a/lisp/eshell/esh-opt.el b/lisp/eshell/esh-opt.el
index f52b70fe7a6..551317d8339 100644
--- a/lisp/eshell/esh-opt.el
+++ b/lisp/eshell/esh-opt.el
@@ -132,7 +132,7 @@ This code doesn't really need to be macro expanded everywhere."
(setq args (eshell--process-args name args options))
nil))))
(when usage-msg
- (error "%s" usage-msg))))))
+ (user-error "%s" usage-msg))))))
(if ext-command
(throw 'eshell-external
(eshell-external-command ext-command orig-args))
@@ -237,7 +237,7 @@ remaining characters in SWITCH to be processed later as further short
options.
If no matching handler is found, and an :external command is defined
-(and available), it will be called; otherwise, an error will be
+\(and available), it will be called; otherwise, an error will be
triggered to say that the switch is unrecognized."
(let ((switch (eshell--split-switch switch kind))
(opts options)
diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el
index 950922ea7f8..c56278aad02 100644
--- a/lisp/eshell/esh-proc.el
+++ b/lisp/eshell/esh-proc.el
@@ -467,7 +467,7 @@ PROC is the process that's exiting. STRING is the exit message."
(if (process-get proc :eshell-busy)
(run-at-time 0 nil finish-io)
(when data
- (ignore-error 'eshell-pipe-broken
+ (ignore-error eshell-pipe-broken
(eshell-output-object
data index handles)))
(eshell-close-handles
diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el
index 0ec11e8a0b3..aceca28befb 100644
--- a/lisp/eshell/esh-util.el
+++ b/lisp/eshell/esh-util.el
@@ -362,9 +362,13 @@ Prepend remote identification of `default-directory', if any."
"Convert each element of ARGS into a string value."
(mapcar #'eshell-stringify args))
+(defsubst eshell-list-to-string (list)
+ "Convert LIST into a single string separated by spaces."
+ (mapconcat #'eshell-stringify list " "))
+
(defsubst eshell-flatten-and-stringify (&rest args)
"Flatten and stringify all of the ARGS into a single string."
- (mapconcat #'eshell-stringify (flatten-tree args) " "))
+ (eshell-list-to-string (flatten-tree args)))
(defsubst eshell-directory-files (regexp &optional directory)
"Return a list of files in the given DIRECTORY matching REGEXP."
diff --git a/lisp/eshell/esh-var.el b/lisp/eshell/esh-var.el
index 4806041c59e..807a8ecc446 100644
--- a/lisp/eshell/esh-var.el
+++ b/lisp/eshell/esh-var.el
@@ -86,6 +86,13 @@
;; Returns the length of the value of $EXPR. This could also be
;; done using the `length' Lisp function.
;;
+;; $@EXPR
+;;
+;; Splices the value of $EXPR in-place into the current list of
+;; arguments. This is analogous to the `,@' token in Elisp
+;; backquotes, and works as if the user typed '$EXPR[0] $EXPR[1]
+;; ... $EXPR[N]'.
+;;
;; There are also a few special variables defined by Eshell. '$$' is
;; the value of the last command (t or nil, in the case of an external
;; command). This makes it possible to chain results:
@@ -320,10 +327,9 @@ copied (a.k.a. \"exported\") to the environment of created subprocesses."
"Parse a variable interpolation.
This function is explicit for adding to `eshell-parse-argument-hook'."
(when (and (eq (char-after) ?$)
- (/= (1+ (point)) (point-max)))
+ (/= (1+ (point)) (point-max)))
(forward-char)
- (list 'eshell-escape-arg
- (eshell-parse-variable))))
+ (eshell-parse-variable)))
(defun eshell/define (var-alias definition)
"Define a VAR-ALIAS using DEFINITION."
@@ -453,6 +459,8 @@ Its purpose is to call `eshell-parse-variable-ref', and then to
process any indices that come after the variable reference."
(let* ((get-len (when (eq (char-after) ?#)
(forward-char) t))
+ (splice (when (eq (char-after) ?@)
+ (forward-char) t))
value indices)
(setq value (eshell-parse-variable-ref get-len)
indices (and (not (eobp))
@@ -464,7 +472,13 @@ process any indices that come after the variable reference."
(when get-len
(setq value `(length ,value)))
(when eshell-current-quoted
- (setq value `(eshell-stringify ,value)))
+ (if splice
+ (setq value `(eshell-list-to-string ,value)
+ splice nil)
+ (setq value `(eshell-stringify ,value))))
+ (setq value `(eshell-escape-arg ,value))
+ (when splice
+ (setq value `(eshell-splice-args ,value)))
value))
(defun eshell-parse-variable-ref (&optional modifier-p)
@@ -751,12 +765,13 @@ For example, to retrieve the second element of a user's record in
(defun eshell-complete-variable-reference ()
"If there is a variable reference, complete it."
- (let ((arg (pcomplete-actual-arg)) index)
- (when (setq index
- (string-match
- (concat "\\$\\(" eshell-variable-name-regexp
- "\\)?\\'") arg))
- (setq pcomplete-stub (substring arg (1+ index)))
+ (let ((arg (pcomplete-actual-arg)))
+ (when (string-match
+ (rx "$" (? (or "#" "@"))
+ (? (group (regexp eshell-variable-name-regexp)))
+ string-end)
+ arg)
+ (setq pcomplete-stub (substring arg (match-beginning 1)))
(throw 'pcomplete-completions (eshell-variables-list)))))
(defun eshell-variables-list ()
diff --git a/lisp/files.el b/lisp/files.el
index 522e4fbf935..e729c007821 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6193,11 +6193,11 @@ instance of such commands."
(rename-buffer (generate-new-buffer-name base-name))
(force-mode-line-update))))
-(defun files--ensure-directory (mkdir dir)
- "Use function MKDIR to make directory DIR if it is not already a directory.
+(defun files--ensure-directory (dir)
+ "Make directory DIR if it is not already a directory.
Return non-nil if DIR is already a directory."
(condition-case err
- (funcall mkdir dir)
+ (make-directory-internal dir)
(error
(or (file-directory-p dir)
(signal (car err) (cdr err))))))
@@ -6223,32 +6223,27 @@ Signal an error if unsuccessful."
;; If default-directory is a remote directory,
;; make sure we find its make-directory handler.
(setq dir (expand-file-name dir))
- (let ((mkdir (if-let ((handler (find-file-name-handler dir 'make-directory)))
- #'(lambda (dir)
- ;; Use 'ignore' since the handler might be designed for
- ;; Emacs 28-, so it might return an (undocumented)
- ;; non-nil value, whereas the Emacs 29+ convention is
- ;; to return nil here.
- (ignore (funcall handler 'make-directory dir)))
- #'make-directory-internal)))
- (if (not parents)
- (funcall mkdir dir)
- (let ((dir (directory-file-name (expand-file-name dir)))
- already-dir create-list parent)
- (while (progn
- (setq parent (directory-file-name
- (file-name-directory dir)))
- (condition-case ()
- (ignore (setq already-dir
- (files--ensure-directory mkdir dir)))
- (error
- ;; Do not loop if root does not exist (Bug#2309).
- (not (string= dir parent)))))
- (setq create-list (cons dir create-list)
- dir parent))
- (dolist (dir create-list)
- (setq already-dir (files--ensure-directory mkdir dir)))
- already-dir))))
+ (let ((handler (find-file-name-handler dir 'make-directory)))
+ (if handler
+ (funcall handler 'make-directory dir parents)
+ (if (not parents)
+ (make-directory-internal dir)
+ (let ((dir (directory-file-name (expand-file-name dir)))
+ already-dir create-list parent)
+ (while (progn
+ (setq parent (directory-file-name
+ (file-name-directory dir)))
+ (condition-case ()
+ (ignore (setq already-dir
+ (files--ensure-directory dir)))
+ (error
+ ;; Do not loop if root does not exist (Bug#2309).
+ (not (string= dir parent)))))
+ (setq create-list (cons dir create-list)
+ dir parent))
+ (dolist (dir create-list)
+ (setq already-dir (files--ensure-directory dir)))
+ already-dir)))))
(defun make-empty-file (filename &optional parents)
"Create an empty file FILENAME.
diff --git a/lisp/frame.el b/lisp/frame.el
index 400f8a44eea..e4cd2cd8ae2 100644
--- a/lisp/frame.el
+++ b/lisp/frame.el
@@ -1188,7 +1188,7 @@ e.g. (mapc \\='frame-set-background-mode (frame-list))."
(defvar inhibit-frame-set-background-mode nil)
-(defun frame--current-backround-mode (frame)
+(defun frame--current-background-mode (frame)
(let* ((frame-default-bg-mode (frame-terminal-default-bg-mode frame))
(bg-color (frame-parameter frame 'background-color))
(tty-type (tty-type frame))
@@ -1218,7 +1218,7 @@ If optional arg KEEP-FACE-SPECS is non-nil, don't recalculate
face specs for the new background mode."
(unless inhibit-frame-set-background-mode
(let* ((bg-mode
- (frame--current-backround-mode frame))
+ (frame--current-background-mode frame))
(display-type
(cond ((null (window-system frame))
(if (tty-display-color-p frame) 'color 'mono))
@@ -1297,7 +1297,7 @@ the `background-mode' terminal parameter."
;; :global t
;; :group 'faces
;; (when (eq dark-mode
-;; (eq 'light (frame--current-backround-mode (selected-frame))))
+;; (eq 'light (frame--current-background-mode (selected-frame))))
;; ;; FIXME: Change the face's SPEC instead?
;; (set-face-attribute 'default nil
;; :foreground (face-attribute 'default :background)
@@ -3105,6 +3105,9 @@ If FRAME isn't maximized, show the title bar."
frame 'undecorated
(eq (alist-get 'fullscreen (frame-parameters frame)) 'maximized)))
+(define-obsolete-function-alias 'frame--current-backround-mode
+ #'frame--current-background-mode "30.1")
+
(provide 'frame)
;;; frame.el ends here
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el
index cf5ca628cff..c5cd4d7d6be 100644
--- a/lisp/gnus/gnus-registry.el
+++ b/lisp/gnus/gnus-registry.el
@@ -394,7 +394,7 @@ This is not required after changing `gnus-registry-cache-file'."
(with-no-warnings
(eieio-persistent-read file 'registry-db))
;; Older EIEIO versions do not check the class name.
- ('wrong-number-of-arguments
+ (wrong-number-of-arguments
(eieio-persistent-read file)))))
(gnus-message 5 "Reading Gnus registry from %s...done" file))
diff --git a/lisp/gnus/mml.el b/lisp/gnus/mml.el
index ebd0adf2e25..dc86fe6db96 100644
--- a/lisp/gnus/mml.el
+++ b/lisp/gnus/mml.el
@@ -1484,10 +1484,12 @@ Ask for type, description or disposition according to
(setq disposition (mml-minibuffer-read-disposition type nil file)))
(mml-attach-file file type description disposition)))))
-(defun mml-attach-buffer (buffer &optional type description disposition)
+(defun mml-attach-buffer (buffer &optional type description disposition filename)
"Attach a buffer to the outgoing MIME message.
BUFFER is the name of the buffer to attach. See
-`mml-attach-file' for details of operation."
+`mml-attach-file' regarding TYPE, DESCRIPTION and DISPOSITION.
+FILENAME is a suggested file name for the attachment should a
+recipient wish to save a copy separate from the message."
(interactive
(let* ((buffer (read-buffer "Attach buffer: "))
(type (mml-minibuffer-read-type buffer "text/plain"))
@@ -1497,9 +1499,10 @@ BUFFER is the name of the buffer to attach. See
;; If in the message header, attach at the end and leave point unchanged.
(let ((head (unless (message-in-body-p) (point))))
(if head (goto-char (point-max)))
- (mml-insert-empty-tag 'part 'type type 'buffer buffer
- 'disposition disposition
- 'description description)
+ (apply #'mml-insert-empty-tag
+ 'part 'type type 'buffer buffer
+ 'disposition disposition 'description description
+ (and filename `(filename ,filename)))
;; When using Mail mode, make sure it does the mime encoding
;; when you send the message.
(or (eq mail-user-agent 'message-user-agent)
diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el
index ab9c6dd74f9..e3fb5d8f872 100644
--- a/lisp/gnus/nndiary.el
+++ b/lisp/gnus/nndiary.el
@@ -339,8 +339,15 @@ all. This may very well take some time.")
;; for this header) or one list (specifying all the possible values for this
;; header). In the latter case, the list does NOT include the unspecified
;; spec (*).
+
;; For time zone values, we have symbolic time zone names associated with
;; the (relative) number of seconds ahead GMT.
+ ;; The list of time zone values is obsolescent, and new code should
+ ;; not rely on it. Many of the time zone abbreviations are wrong;
+ ;; in particular, all single-letter abbreviations other than "Z" have
+ ;; been wrong since Internet RFC 2822 (2001). However, the
+ ;; abbreviations have not been changed due to backward compatibility
+ ;; concerns.
)
(defsubst nndiary-schedule ()
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index e29f763dabc..3307771ef68 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -2004,8 +2004,8 @@ variable with value KEYMAP."
(mapatoms (lambda (symb)
(when (and (boundp symb)
(eq (symbol-value symb) keymap)
- (not (eq symb 'keymap))
- (throw 'found-keymap symb)))))
+ (not (eq symb 'keymap)))
+ (throw 'found-keymap symb))))
nil)))
;; Follow aliasing.
(or (ignore-errors (indirect-variable name)) name))))
diff --git a/lisp/image-mode.el b/lisp/image-mode.el
index bd208fbad46..10af8c6cab9 100644
--- a/lisp/image-mode.el
+++ b/lisp/image-mode.el
@@ -1086,7 +1086,7 @@ Otherwise, display the image by calling `image-mode'."
(unwind-protect
(progn
(setq-local image-fit-to-window-lock t)
- (ignore-error 'remote-file-error
+ (ignore-error remote-file-error
(image-toggle-display-image)))
(setq image-fit-to-window-lock nil)))))))))))
diff --git a/lisp/ldefs-boot.el b/lisp/ldefs-boot.el
index bad13e9bb9f..c21955c3f06 100644
--- a/lisp/ldefs-boot.el
+++ b/lisp/ldefs-boot.el
@@ -2020,7 +2020,7 @@ other modes. See `override-global-mode'.
(fn &rest ARGS)" nil t)
(autoload 'describe-personal-keybindings "bind-key" "\
Display all the personal keybindings defined by `bind-key'." t)
-(register-definition-prefixes "bind-key" '("bind-key" "compare-keybindings" "get-binding-description" "override-global-m" "personal-keybindings"))
+(register-definition-prefixes "bind-key" '("bind-key" "override-global-m" "personal-keybindings"))
;;; Generated autoloads from emacs-lisp/bindat.el
@@ -8197,6 +8197,7 @@ Valid keywords and arguments are:
`nodigits' to suppress digits as prefix arguments.
(fn BS &optional NAME M ARGS)")
+(make-obsolete 'easy-mmode-define-keymap 'define-keymap "29.1")
(autoload 'easy-mmode-defmap "easy-mmode" "\
Define a constant M whose value is the result of `easy-mmode-define-keymap'.
The M, BS, and ARGS arguments are as per that function. DOC is
@@ -8207,6 +8208,7 @@ This macro is deprecated; use `defvar-keymap' instead.
(fn M BS DOC &rest ARGS)" nil t)
(function-put 'easy-mmode-defmap 'doc-string-elt 3)
(function-put 'easy-mmode-defmap 'lisp-indent-function 1)
+(make-obsolete 'easy-mmode-defmap 'defvar-keymap "29.1")
(autoload 'easy-mmode-defsyntax "easy-mmode" "\
Define variable ST as a syntax-table.
CSS contains a list of syntax specifications of the form (CHAR . SYNTAX).
@@ -23412,6 +23414,11 @@ the `Version:' header.")
(defcustom package-quickstart-file (locate-user-emacs-file "package-quickstart.el") "\
Location of the file used to speed up activation of packages at startup." :type 'file :group 'applications :initialize #'custom-initialize-delay :version "27.1")
(custom-autoload 'package-quickstart-file "package" t)
+(autoload 'package-report-bug "package" "\
+Prepare a message to send to the maintainers of a package.
+DESC must be a `package-desc' object.
+
+(fn DESC)" '(package-menu-mode))
(register-definition-prefixes "package" '("bad-signature" "define-package" "describe-package-1" "package-"))
@@ -28246,29 +28253,17 @@ With ARG non-nil, silently save all file-visiting buffers, then kill.
If emacsclient was started with a list of filenames to edit, then
only these files will be asked to be saved.
+When running Emacs as a daemon and with
+`server-stop-automatically' (which see) set to `kill-terminal' or
+`delete-frame', this function may call `save-buffers-kill-emacs'
+if there are no other active clients.
+
(fn ARG)")
(autoload 'server-stop-automatically "server" "\
-Automatically stop server as specified by ARG.
-
-If ARG is the symbol `empty', stop the server when it has no
-remaining clients, no remaining unsaved file-visiting buffers,
-and no running processes with a `query-on-exit' flag.
-
-If ARG is the symbol `delete-frame', ask the user when the last
-frame is deleted whether each unsaved file-visiting buffer must
-be saved and each running process with a `query-on-exit' flag
-can be stopped, and if so, stop the server itself.
-
-If ARG is the symbol `kill-terminal', ask the user when the
-terminal is killed with \\[save-buffers-kill-terminal] whether each unsaved file-visiting
-buffer must be saved and each running process with a `query-on-exit'
-flag can be stopped, and if so, stop the server itself.
-
-Any other value of ARG will cause this function to signal an error.
+Automatically stop the Emacs server as specified by VALUE.
+This sets the variable `server-stop-automatically' (which see).
-This function is meant to be called from the user init file.
-
-(fn ARG)")
+(fn VALUE)")
(register-definition-prefixes "server" '("server-"))
@@ -30228,7 +30223,7 @@ Return the width of STRING in pixels.
(autoload 'string-glyph-split "subr-x" "\
Split STRING into a list of strings representing separate glyphs.
This takes into account combining characters and grapheme clusters:
-if compositions are enabled, each sequence of characters composed
+if compositions are enbaled, each sequence of characters composed
on display into a single grapheme cluster is treated as a single
indivisible unit.
@@ -32694,7 +32689,7 @@ Add archive file name handler to `file-name-handler-alist'." (when (and tramp-ar
;;; Generated autoloads from net/trampver.el
-(push (purecopy '(tramp 2 6 0 29 1)) package--builtin-versions)
+(push (purecopy '(tramp 2 6 0 -1)) package--builtin-versions)
(register-definition-prefixes "trampver" '("tramp-"))
@@ -34435,7 +34430,7 @@ revision, with SUBJECT derived from each revision subject.
When invoked with a numerical prefix argument, use the last N
revisions.
When invoked interactively in a Log View buffer with
-marked revisions, use those these.
+marked revisions, use those.
(fn ADDRESSEE SUBJECT REVISIONS)" t)
(register-definition-prefixes "vc" '("vc-" "with-vc-properties"))
@@ -34704,7 +34699,7 @@ Key bindings:
;;; Generated autoloads from progmodes/verilog-mode.el
-(push (purecopy '(verilog-mode 2021 10 14 127365406)) package--builtin-versions)
+(push (purecopy '(verilog-mode 2022 12 18 181110314)) package--builtin-versions)
(autoload 'verilog-mode "verilog-mode" "\
Major mode for editing Verilog code.
\\<verilog-mode-map>
@@ -34738,6 +34733,11 @@ Variables controlling indentation/edit style:
function keyword.
`verilog-indent-level-directive' (default 1)
Indentation of \\=`ifdef/\\=`endif blocks.
+ `verilog-indent-ignore-multiline-defines' (default t)
+ Non-nil means ignore indentation on lines that are part of a multiline
+ define.
+ `verilog-indent-ignore-regexp' (default nil
+ Regexp that matches lines that should be ignored for indentation.
`verilog-cexp-indent' (default 1)
Indentation of Verilog statements broken across lines i.e.:
if (a)
@@ -34761,6 +34761,9 @@ Variables controlling indentation/edit style:
otherwise you get:
if (a)
begin
+ `verilog-indent-class-inside-pkg' (default t)
+ Non-nil means indent classes inside packages.
+ Otherwise, classes have zero indentation.
`verilog-auto-endcomments' (default t)
Non-nil means a comment /* ... */ is set after the ends which ends
cases, tasks, functions and modules.
@@ -34770,6 +34773,17 @@ Variables controlling indentation/edit style:
will be inserted. Setting this variable to zero results in every
end acquiring a comment; the default avoids too many redundant
comments in tight quarters.
+ `verilog-align-decl-expr-comments' (default t)
+ Non-nil means align declaration and expressions comments.
+ `verilog-align-comment-distance' (default 1)
+ Distance (in spaces) between longest declaration and comments.
+ Only works if `verilog-align-decl-expr-comments' is non-nil.
+ `verilog-align-assign-expr' (default nil)
+ Non-nil means align expressions of continuous assignments.
+ `verilog-align-typedef-regexp' (default nil)
+ Regexp that matches user typedefs for declaration alignment.
+ `verilog-align-typedef-words' (default nil)
+ List of words that match user typedefs for declaration alignment.
`verilog-auto-lineup' (default `declarations')
List of contexts where auto lineup of code should be done.
@@ -34793,17 +34807,20 @@ Some other functions are:
\\[verilog-mark-defun] Mark function.
\\[verilog-beg-of-defun] Move to beginning of current function.
\\[verilog-end-of-defun] Move to end of current function.
- \\[verilog-label-be] Label matching begin ... end, fork ... join, etc statements.
+ \\[verilog-label-be] Label matching begin ... end, fork ... join, etc
+ statements.
\\[verilog-comment-region] Put marked area in a comment.
- \\[verilog-uncomment-region] Uncomment an area commented with \\[verilog-comment-region].
+ \\[verilog-uncomment-region] Uncomment an area commented with
+ \\[verilog-comment-region].
\\[verilog-insert-block] Insert begin ... end.
\\[verilog-star-comment] Insert /* ... */.
\\[verilog-sk-always] Insert an always @(AS) begin .. end block.
\\[verilog-sk-begin] Insert a begin .. end block.
\\[verilog-sk-case] Insert a case block, prompting for details.
- \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for details.
+ \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for
+ details.
\\[verilog-sk-generate] Insert a generate .. endgenerate block.
\\[verilog-sk-header] Insert a header block at the top of file.
\\[verilog-sk-initial] Insert an initial begin .. end block.
@@ -34826,14 +34843,17 @@ Some other functions are:
\\[verilog-sk-else-if] Insert an else if (..) begin .. end block.
\\[verilog-sk-comment] Insert a comment block.
\\[verilog-sk-assign] Insert an assign .. = ..; statement.
- \\[verilog-sk-function] Insert a function .. begin .. end endfunction block.
+ \\[verilog-sk-function] Insert a function .. begin .. end endfunction
+ block.
\\[verilog-sk-input] Insert an input declaration, prompting for details.
\\[verilog-sk-output] Insert an output declaration, prompting for details.
- \\[verilog-sk-state-machine] Insert a state machine definition, prompting for details.
+ \\[verilog-sk-state-machine] Insert a state machine definition, prompting
+ for details.
\\[verilog-sk-inout] Insert an inout declaration, prompting for details.
\\[verilog-sk-wire] Insert a wire declaration, prompting for details.
\\[verilog-sk-reg] Insert a register declaration, prompting for details.
- \\[verilog-sk-define-signal] Define signal under point as a register at the top of the module.
+ \\[verilog-sk-define-signal] Define signal under point as a register at
+ the top of the module.
All key bindings can be seen in a Verilog-buffer with \\[describe-bindings].
Key bindings specific to `verilog-mode-map' are:
@@ -35952,6 +35972,7 @@ The mode's hook is called both when the mode is enabled and when
it is disabled.
(fn &optional ARG)" t)
+(put 'global-whitespace-mode 'globalized-minor-mode t)
(defvar global-whitespace-mode nil "\
Non-nil if Global Whitespace mode is enabled.
See the `global-whitespace-mode' command
@@ -35961,25 +35982,18 @@ either customize it (see the info node `Easy Customization')
or call the function `global-whitespace-mode'.")
(custom-autoload 'global-whitespace-mode "whitespace" nil)
(autoload 'global-whitespace-mode "whitespace" "\
-Toggle whitespace visualization globally (Global Whitespace mode).
-
-See also `whitespace-style', `whitespace-newline' and
-`whitespace-display-mappings'.
-
-This is a global minor mode. If called interactively, toggle the
-`Global Whitespace mode' mode. If the prefix argument is
-positive, enable the mode, and if it is zero or negative, disable
-the mode.
+Toggle Whitespace mode in all buffers.
+With prefix ARG, enable Global Whitespace mode if ARG is positive;
+otherwise, disable it.
-If called from Lisp, toggle the mode if ARG is `toggle'. Enable
-the mode if ARG is nil, omitted, or is a positive number.
+If called from Lisp, toggle the mode if ARG is `toggle'.
+Enable the mode if ARG is nil, omitted, or is a positive number.
Disable the mode if ARG is a negative number.
-To check whether the minor mode is enabled in the current buffer,
-evaluate `(default-value \\='global-whitespace-mode)'.
+Whitespace mode is enabled in all buffers where
+`whitespace-turn-on-if-enabled' would do it.
-The mode's hook is called both when the mode is enabled and when
-it is disabled.
+See `whitespace-mode' for more information on Whitespace mode.
(fn &optional ARG)" t)
(defvar global-whitespace-newline-mode nil "\
diff --git a/lisp/mail/rmailout.el b/lisp/mail/rmailout.el
index c1371308d4f..18f980df975 100644
--- a/lisp/mail/rmailout.el
+++ b/lisp/mail/rmailout.el
@@ -327,15 +327,14 @@ Replaces the From line with a \"Mail-from\" header. Adds \"Date\" and
"Date: \\2, \\4 \\3 \\9 \\5 "
;; The timezone could be matched by group 7 or group 10.
- ;; If neither of them matched, assume EST, since only
- ;; Easterners would be so sloppy.
+ ;; If neither matched, use "-0000" for an unknown zone.
;; It's a shame the substitution can't use "\\10".
(cond
((/= (match-beginning 7) (match-end 7)) "\\7")
((/= (match-beginning 10) (match-end 10))
(buffer-substring (match-beginning 10)
(match-end 10)))
- (t "EST"))
+ (t "-0000"))
"\n"))
;; Keep and reformat the sender if we don't
;; have a From: field.
diff --git a/lisp/mh-e/mh-identity.el b/lisp/mh-e/mh-identity.el
index bcdf91299be..2507c677462 100644
--- a/lisp/mh-e/mh-identity.el
+++ b/lisp/mh-e/mh-identity.el
@@ -141,7 +141,7 @@ See `mh-identity-list'."
(cons '("None")
(mapcar #'list (mapcar #'car mh-identity-list)))
nil t default nil default))
- (if (eq identity "None")
+ (if (equal identity "None")
nil
identity)))
diff --git a/lisp/mouse.el b/lisp/mouse.el
index f72ab4fc642..095d30a2856 100644
--- a/lisp/mouse.el
+++ b/lisp/mouse.el
@@ -105,6 +105,15 @@ point at the click position."
:type 'boolean
:version "22.1")
+(defcustom mouse-1-double-click-prefer-symbols nil
+ "If non-nil, double-clicking Mouse-1 attempts to select the symbol at click.
+
+If nil, the default, double-clicking Mouse-1 on a word-constituent
+character will select only the word at click location, which could
+select fewer characters than the symbol at click."
+ :type 'boolean
+ :version "30.1")
+
(defcustom mouse-drag-and-drop-region-scroll-margin nil
"If non-nil, the scroll margin inside a window when dragging text.
If the mouse moves this many lines close to the top or bottom of
@@ -1800,10 +1809,17 @@ The region will be defined with mark and point."
;; Commands to handle xterm-style multiple clicks.
(defun mouse-skip-word (dir)
"Skip over word, over whitespace, or over identical punctuation.
+If `mouse-1-double-click-prefer-symbols' is non-nil, skip over symbol.
If DIR is positive skip forward; if negative, skip backward."
(let* ((char (following-char))
- (syntax (char-to-string (char-syntax char))))
- (cond ((string= syntax "w")
+ (syntax (char-to-string (char-syntax char)))
+ sym)
+ (cond ((and mouse-1-double-click-prefer-symbols
+ (setq sym (bounds-of-thing-at-point 'symbol)))
+ (goto-char (if (< dir 0)
+ (car sym)
+ (cdr sym))))
+ ((string= syntax "w")
;; Here, we can't use skip-syntax-forward/backward because
;; they don't pay attention to word-separating-categories,
;; and thus they will skip over a true word boundary. So,
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index 6e17e417ea3..f8e2858bc3f 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -4129,7 +4129,7 @@ directory, so that Emacs will know its current contents."
(or (file-exists-p parent)
(ange-ftp-make-directory parent parents))))
(if (file-exists-p dir)
- (unless parents
+ (if parents t
(signal
'file-already-exists
(list "Cannot make directory: file already exists" dir)))
@@ -4158,7 +4158,8 @@ directory, so that Emacs will know its current contents."
(format "Could not make directory %s: %s"
dir
(cdr result))))
- (ange-ftp-add-file-entry dir t))
+ (ange-ftp-add-file-entry dir t)
+ nil)
(ange-ftp-real-make-directory dir)))))
(defun ange-ftp-delete-directory (dir &optional recursive trash)
@@ -4498,6 +4499,25 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
(put 'process-file 'ange-ftp 'ange-ftp-process-file)
(put 'start-file-process 'ange-ftp 'ignore)
(put 'shell-command 'ange-ftp 'ange-ftp-shell-command)
+
+;; Do not execute system information functions.
+(put 'file-system-info 'ange-ftp 'ignore)
+(put 'list-system-processes 'ange-ftp 'ignore)
+(put 'memory-info 'ange-ftp 'ignore)
+(put 'process-attributes 'ange-ftp 'ignore)
+
+;; There aren't ACLs. `file-selinux-context' shall return '(nil nil
+;; nil nil) if the file is nonexistent, so we let the default file
+;; name handler do the job.
+(put 'file-acl 'ange-ftp 'ignore)
+;; (put 'file-selinux-context 'ange-ftp 'ignore)
+(put 'set-file-acl 'ange-ftp 'ignore)
+(put 'set-file-selinux-context 'ange-ftp 'ignore)
+
+;; There aren't file notifications.
+(put 'file-notify-add-watch 'ange-ftp 'ignore)
+(put 'file-notify-rm-watch 'ange-ftp 'ignore)
+(put 'file-notify-valid-p 'ange-ftp 'ignore)
;;; Define ways of getting at unmodified Emacs primitives,
;;; turning off our handler.
diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 3799ef96e84..a8a985b8dea 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -2498,10 +2498,10 @@ Otherwise, the restored buffer will contain a prompt to do so by using
(when (plist-get eww-data :url)
(cl-case eww-restore-desktop
((t auto) (eww (plist-get eww-data :url)))
- ((zerop (buffer-size))
- (let ((inhibit-read-only t))
- (insert (substitute-command-keys
- eww-restore-reload-prompt)))))))
+ ((nil) (when (zerop (buffer-size))
+ (let ((inhibit-read-only t))
+ (insert (substitute-command-keys
+ eww-restore-reload-prompt))))))))
;; .
(current-buffer)))
diff --git a/lisp/net/gnutls.el b/lisp/net/gnutls.el
index 9f14df08a79..f828ccfc1b0 100644
--- a/lisp/net/gnutls.el
+++ b/lisp/net/gnutls.el
@@ -262,6 +262,7 @@ For the meaning of the rest of the parameters, see `gnutls-boot-parameters'."
&key type hostname priority-string
trustfiles crlfiles keylist min-prime-bits
verify-flags verify-error verify-hostname-error
+ pass flags
&allow-other-keys)
"Return a keyword list of parameters suitable for passing to `gnutls-boot'.
@@ -278,6 +279,13 @@ default.
VERIFY-HOSTNAME-ERROR is a backwards compatibility option for
putting `:hostname' in VERIFY-ERROR.
+PASS is a string, the password of the key. It may also be nil,
+for a NULL password.
+
+FLAGS is a list of symbols corresponding to the equivalent ORed
+bitflag of the gnutls_pkcs_encrypt_flags_t enum of GnuTLS. The
+empty list corresponds to the bitflag with value 0.
+
When VERIFY-ERROR is t or a list containing `:trustfiles', an
error will be raised when the peer certificate verification fails
as per GnuTLS' gnutls_certificate_verify_peers2. Otherwise, only
@@ -355,6 +363,8 @@ defaults to GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT."
:keylist ,keylist
:verify-flags ,verify-flags
:verify-error ,verify-error
+ :pass ,pass
+ :flags ,flags
:callbacks nil)))
(defun gnutls--get-files (files)
diff --git a/lisp/net/newst-backend.el b/lisp/net/newst-backend.el
index af196ccecf9..2a87742fdf8 100644
--- a/lisp/net/newst-backend.el
+++ b/lisp/net/newst-backend.el
@@ -1623,7 +1623,7 @@ Sat, 07 Sep 2002 00:00:01 GMT
":\\([0-9]\\{2\\}\\)"
;; second
"\\(:\\([0-9]\\{2\\}\\)\\)?"
- ;; zone -- fixme
+ ;; zone
"\\(\\s-+\\("
"UT\\|GMT\\|EST\\|EDT\\|CST\\|CDT\\|MST\\|MDT\\|PST\\|PDT"
"\\|\\([-+]\\)\\([0-9]\\{2\\}\\)\\([0-9]\\{2\\}\\)"
@@ -1642,16 +1642,26 @@ Sat, 07 Sep 2002 00:00:01 GMT
(offset-hour (read (or (match-string 14 rfc822-string)
"0")))
(offset-minute (read (or (match-string 15 rfc822-string)
- "0")))
- ;;FIXME
- )
+ "0"))))
(when zone
(cond ((string= sign "+")
(setq hour (- hour offset-hour))
(setq minute (- minute offset-minute)))
((string= sign "-")
(setq hour (+ hour offset-hour))
- (setq minute (+ minute offset-minute)))))
+ (setq minute (+ minute offset-minute)))
+ ((or (string= zone "UT") (string= zone "GMT"))
+ nil)
+ ((string= zone "EDT")
+ (setq hour (+ hour 4)))
+ ((or (string= zone "EST") (string= zone "CDT"))
+ (setq hour (+ hour 5)))
+ ((or (string= zone "CST") (string= zone "MDT"))
+ (setq hour (+ hour 6)))
+ ((or (string= zone "MST") (string= zone "PDT"))
+ (setq hour (+ hour 7)))
+ ((string= zone "PST")
+ (setq hour (+ hour 8)))))
(condition-case error-data
(let ((i 1))
(dolist (m '("Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" "Aug"
diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el
index 29957a62d04..81a572250af 100644
--- a/lisp/net/rcirc.el
+++ b/lisp/net/rcirc.el
@@ -1396,10 +1396,10 @@ inserted."
(interactive "P")
(rcirc-format "\^_" replace))
-(defun rcirc-format-strike-trough (replace)
- "Insert strike-trough formatting.
+(defun rcirc-format-strike-through (replace)
+ "Insert strike-through formatting.
If REPLACE is non-nil or a prefix argument is given, any prior
-formatting will be replaced before the strike-trough formatting
+formatting will be replaced before the strike-through formatting
is inserted."
(interactive "P")
(rcirc-format "\^^" replace))
@@ -1421,7 +1421,7 @@ inserted."
"C-c C-f C-b" #'rcirc-format-bold
"C-c C-f C-i" #'rcirc-format-italic
"C-c C-f C-u" #'rcirc-format-underline
- "C-c C-f C-s" #'rcirc-format-strike-trough
+ "C-c C-f C-s" #'rcirc-format-strike-through
"C-c C-f C-f" #'rcirc-format-fixed-width
"C-c C-f C-t" #'rcirc-format-fixed-width ;as in AucTeX
"C-c C-f C-d" #'rcirc-unformat
@@ -1807,7 +1807,7 @@ extracted."
"C-c C-f C-b" #'rcirc-format-bold
"C-c C-f C-i" #'rcirc-format-italic
"C-c C-f C-u" #'rcirc-format-underline
- "C-c C-f C-s" #'rcirc-format-strike-trough
+ "C-c C-f C-s" #'rcirc-format-strike-through
"C-c C-f C-f" #'rcirc-format-fixed-width
"C-c C-f C-t" #'rcirc-format-fixed-width ;as in AucTeX
"C-c C-f C-d" #'rcirc-unformat
@@ -2371,9 +2371,11 @@ This function does not alter the INPUT string."
"C-c C-@" #'rcirc-next-active-buffer
"C-c C-SPC" #'rcirc-next-active-buffer)
-(defcustom rcirc-track-abbrevate-flag t
+(define-obsolete-variable-alias 'rcirc-track-abbrevate-flag
+ 'rcirc-track-abbreviate-flag "30.1")
+(defcustom rcirc-track-abbreviate-flag t
"Non-nil means `rcirc-track-minor-mode' should abbreviate names."
- :version "28.1"
+ :version "30.1"
:type 'boolean)
;;;###autoload
@@ -2559,7 +2561,7 @@ activity. Only run if the buffer is not visible and
(funcall rcirc-channel-filter
(replace-regexp-in-string
"@.*?\\'" ""
- (or (and rcirc-track-abbrevate-flag
+ (or (and rcirc-track-abbreviate-flag
rcirc-short-buffer-name)
(buffer-name))))))
@@ -4002,6 +4004,9 @@ PROCESS is the process object for the current connection."
(string-equal (downcase (car setting)) parameter))
return (cadr setting)))
+(define-obsolete-function-alias 'rcirc-format-strike-trough
+ 'rcirc-format-strike-through "30.1")
+
(provide 'rcirc)
;;; rcirc.el ends here
diff --git a/lisp/net/soap-client.el b/lisp/net/soap-client.el
index 5e7bdbe6c6a..6e9200e4656 100644
--- a/lisp/net/soap-client.el
+++ b/lisp/net/soap-client.el
@@ -1317,7 +1317,7 @@ See also `soap-wsdl-resolve-references'."
"Validate VALUE against the basic type TYPE."
(let* ((kind (soap-xs-basic-type-kind type)))
(cl-case kind
- ((anyType Array byte[])
+ ((anyType Array byte\[\])
value)
(t
(let ((convert (get kind 'rng-xsd-convert)))
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 90020fbb1b6..5a025130ecf 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -411,20 +411,11 @@ Emacs dired can't find files."
(defun tramp-adb-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (setq dir (expand-file-name dir))
- (with-parsed-tramp-file-name dir nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists dir))
- (when parents
- (let ((par (expand-file-name ".." dir)))
- (unless (file-directory-p par)
- (make-directory par parents))))
- (tramp-flush-directory-properties v localname)
- (unless (or (tramp-adb-send-command-and-check
- v (format "mkdir -m %#o %s"
- (default-file-modes)
- (tramp-shell-quote-argument localname)))
- (and parents (file-directory-p dir)))
+ (tramp-skeleton-make-directory dir parents
+ (unless (tramp-adb-send-command-and-check
+ v (format "mkdir -m %#o %s"
+ (default-file-modes)
+ (tramp-shell-quote-argument localname)))
(tramp-error v 'file-error "Couldn't make directory %s" dir))))
(defun tramp-adb-handle-delete-directory (directory &optional recursive trash)
diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el
index 249b3fcd4d7..e6c0ebccbff 100644
--- a/lisp/net/tramp-crypt.el
+++ b/lisp/net/tramp-crypt.el
@@ -800,16 +800,9 @@ WILDCARD is not supported."
(defun tramp-crypt-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (with-parsed-tramp-file-name (expand-file-name dir) nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists dir))
+ (tramp-skeleton-make-directory dir parents
(let (tramp-crypt-enabled)
- (make-directory (tramp-crypt-encrypt-file-name dir) parents))
- ;; When PARENTS is non-nil, DIR could be a chain of non-existent
- ;; directories a/b/c/... Instead of checking, we simply flush the
- ;; whole cache.
- (tramp-flush-directory-properties
- v (if parents "/" (file-name-directory localname)))))
+ (make-directory (tramp-crypt-encrypt-file-name dir) parents))))
(defun tramp-crypt-handle-rename-file
(filename newname &optional ok-if-already-exists)
diff --git a/lisp/net/tramp-fuse.el b/lisp/net/tramp-fuse.el
index ea6b5a0622c..5176c6e9c48 100644
--- a/lisp/net/tramp-fuse.el
+++ b/lisp/net/tramp-fuse.el
@@ -127,14 +127,8 @@
(defun tramp-fuse-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (with-parsed-tramp-file-name (expand-file-name dir) nil
- (make-directory (tramp-fuse-local-file-name dir) parents)
- ;; When PARENTS is non-nil, DIR could be a chain of non-existent
- ;; directories a/b/c/... Instead of checking, we simply flush the
- ;; whole file cache.
- (tramp-flush-file-properties v localname)
- (tramp-flush-directory-properties
- v (if parents "/" (file-name-directory localname)))))
+ (tramp-skeleton-make-directory dir parents
+ (make-directory (tramp-fuse-local-file-name dir) parents)))
;; File name helper functions.
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index da7641774fb..66f4de989d0 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1560,27 +1560,13 @@ If FILE-SYSTEM is non-nil, return file system attributes."
(defun tramp-gvfs-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (setq dir (directory-file-name (expand-file-name dir)))
- (with-parsed-tramp-file-name dir nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists dir))
- (tramp-flush-directory-properties v localname)
+ (tramp-skeleton-make-directory dir parents
(save-match-data
- (let ((ldir (file-name-directory dir)))
- ;; Make missing directory parts. "gvfs-mkdir -p ..." does not
- ;; work robust.
- (when (and parents (not (file-directory-p ldir)))
- (make-directory ldir parents))
- ;; Just do it.
- (or (when-let ((mkdir-succeeded
- (and
- (tramp-gvfs-send-command
- v "gvfs-mkdir" (tramp-gvfs-url-file-name dir))
- (tramp-gvfs-info dir))))
- (set-file-modes dir (default-file-modes))
- mkdir-succeeded)
- (and parents (file-directory-p dir))
- (tramp-error v 'file-error "Couldn't make directory %s" dir))))))
+ (if (and (tramp-gvfs-send-command
+ v "gvfs-mkdir" (tramp-gvfs-url-file-name dir))
+ (tramp-gvfs-info dir))
+ (set-file-modes dir (default-file-modes))
+ (tramp-error v 'file-error "Couldn't make directory %s" dir)))))
(defun tramp-gvfs-handle-rename-file
(filename newname &optional ok-if-already-exists)
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index ac5de22cb84..a5327e428ac 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2559,19 +2559,10 @@ The method used must be an out-of-band method."
(defun tramp-sh-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (setq dir (expand-file-name dir))
- (with-parsed-tramp-file-name dir nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists dir))
- ;; When PARENTS is non-nil, DIR could be a chain of non-existent
- ;; directories a/b/c/... Instead of checking, we simply flush the
- ;; whole cache.
- (tramp-flush-directory-properties
- v (if parents "/" (file-name-directory localname)))
+ (tramp-skeleton-make-directory dir parents
(tramp-barf-unless-okay
v (format "%s -m %#o %s"
- (if parents "mkdir -p" "mkdir")
- (default-file-modes)
+ "mkdir" (default-file-modes)
(tramp-shell-quote-argument localname))
"Couldn't make directory %s" dir)))
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index cd73b9b8eca..b51f42deb45 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1172,30 +1172,14 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(defun tramp-smb-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (setq dir (directory-file-name (expand-file-name dir)))
- (unless (file-name-absolute-p dir)
- (setq dir (expand-file-name dir default-directory)))
- (with-parsed-tramp-file-name dir nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists dir))
- (let* ((ldir (file-name-directory dir)))
- ;; Make missing directory parts.
- (when (and parents
- (tramp-smb-get-share v)
- (not (file-directory-p ldir)))
- (make-directory ldir parents))
- ;; Just do it.
- (when (file-directory-p ldir)
- (tramp-smb-send-command
- v (if (tramp-smb-get-cifs-capabilities v)
- (format "posix_mkdir %s %o"
- (tramp-smb-shell-quote-localname v) (default-file-modes))
- (format "mkdir %s" (tramp-smb-shell-quote-localname v))))
- ;; We must also flush the cache of the directory, because
- ;; `file-attributes' reads the values from there.
- (tramp-flush-file-properties v localname))
- (unless (file-directory-p dir)
- (tramp-error v 'file-error "Couldn't make directory %s" dir)))))
+ (tramp-skeleton-make-directory dir parents
+ (tramp-smb-send-command
+ v (if (tramp-smb-get-cifs-capabilities v)
+ (format "posix_mkdir %s %o"
+ (tramp-smb-shell-quote-localname v) (default-file-modes))
+ (format "mkdir %s" (tramp-smb-shell-quote-localname v))))
+ (unless (file-directory-p dir)
+ (tramp-error v 'file-error "Couldn't make directory %s" dir))))
;; This is not used anymore.
(defun tramp-smb-handle-make-directory-internal (directory)
diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el
index fcc27dd8343..8774367cefe 100644
--- a/lisp/net/tramp-sudoedit.el
+++ b/lisp/net/tramp-sudoedit.el
@@ -626,18 +626,9 @@ the result will be a local, non-Tramp, file name."
(defun tramp-sudoedit-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
- (setq dir (expand-file-name dir))
- (with-parsed-tramp-file-name dir nil
- (when (and (null parents) (file-exists-p dir))
- (tramp-error v 'file-already-exists "Directory already exists %s" dir))
- ;; When PARENTS is non-nil, DIR could be a chain of non-existent
- ;; directories a/b/c/... Instead of checking, we simply flush the
- ;; whole cache.
- (tramp-flush-directory-properties
- v (if parents "/" (file-name-directory localname)))
+ (tramp-skeleton-make-directory dir parents
(unless (tramp-sudoedit-send-command
- v (if parents '("mkdir" "-p") "mkdir")
- "-m" (format "%#o" (default-file-modes))
+ v "mkdir" "-m" (format "%#o" (default-file-modes))
(tramp-compat-file-name-unquote localname))
(tramp-error v 'file-error "Couldn't make directory %s" dir))))
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index ca8963fbf54..acbd50dc0fb 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -3537,6 +3537,27 @@ BODY is the backend specific code."
;; Trigger the `file-missing' error.
(signal 'error nil)))))
+(defmacro tramp-skeleton-make-directory (dir &optional parents &rest body)
+ "Skeleton for `tramp-*-handle-make-directory'.
+BODY is the backend specific code."
+ ;; Since Emacs 29.1, PARENTS isn't propagated to the handlers
+ ;; anymore. And the return values are specified since then as well.
+ (declare (indent 2) (debug t))
+ `(let* ((dir (directory-file-name (expand-file-name ,dir)))
+ (par (file-name-directory dir)))
+ (with-parsed-tramp-file-name dir nil
+ (when (and (null ,parents) (file-exists-p dir))
+ (tramp-error v 'file-already-exists dir))
+ ;; Make missing directory parts.
+ (when ,parents
+ (unless (file-directory-p par)
+ (make-directory par ,parents)))
+ ;; Just do it.
+ (if (file-exists-p dir) t
+ (tramp-flush-file-properties v localname)
+ ,@body
+ nil))))
+
(defmacro tramp-skeleton-set-file-modes-times-uid-gid
(filename &rest body)
"Skeleton for `tramp-*-set-file-{modes,times,uid-gid}'.
@@ -5418,7 +5439,7 @@ Wait, until the connection buffer changes."
;; Hide message in buffer.
(narrow-to-region (point-max) (point-max))
;; Wait for new output.
- (while (not (tramp-compat-ignore-error 'file-error
+ (while (not (tramp-compat-ignore-error file-error
(tramp-wait-for-regexp
proc 0.1 tramp-security-key-confirmed-regexp)))
(when (tramp-check-for-regexp proc tramp-security-key-timeout-regexp)
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index 49caadc93ab..caf6750c26d 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -7,7 +7,7 @@
;; Maintainer: Michael Albinus <michael.albinus@gmx.de>
;; Keywords: comm, processes
;; Package: tramp
-;; Version: 2.6.0.29.1
+;; Version: 2.6.0-pre
;; Package-Requires: ((emacs "26.1"))
;; Package-Type: multi
;; URL: https://www.gnu.org/software/tramp/
@@ -40,7 +40,7 @@
;; ./configure" to change them.
;;;###tramp-autoload
-(defconst tramp-version "2.6.0.29.1"
+(defconst tramp-version "2.6.0-pre"
"This version of Tramp.")
;;;###tramp-autoload
@@ -78,7 +78,7 @@
;; Check for Emacs version.
(let ((x (if (not (string-version-lessp emacs-version "26.1"))
"ok"
- (format "Tramp 2.6.0.29.1 is not fit for %s"
+ (format "Tramp 2.6.0-pre is not fit for %s"
(replace-regexp-in-string "\n" "" (emacs-version))))))
(unless (string-equal "ok" x) (error "%s" x)))
@@ -104,8 +104,7 @@
("2.3.3" . "26.1") ("2.3.3.26.1" . "26.1") ("2.3.5.26.2" . "26.2")
("2.3.5.26.3" . "26.3")
("2.4.3.27.1" . "27.1") ("2.4.5.27.2" . "27.2")
- ("2.5.2.28.1" . "28.1") ("2.5.3.28.2" . "28.2")
- ("2.6.0.29.1" . "29.1")))
+ ("2.5.2.28.1" . "28.1") ("2.5.3.28.2" . "28.2")))
(add-hook 'tramp-unload-hook
(lambda ()
diff --git a/lisp/proced.el b/lisp/proced.el
index c7419288edf..c09ee18a8be 100644
--- a/lisp/proced.el
+++ b/lisp/proced.el
@@ -656,6 +656,14 @@ Important: the match ends just after the marker.")
)
(put 'proced-mark :advertised-binding "m")
+(defvar-local proced-refinements nil
+ "Information about the current buffer refinements.
+
+It should be a list of elements of the form (REFINER PID KEY GRAMMAR), where
+REFINER and GRAMMAR are as described in `proced-grammar-alist', PID is the
+process ID of the process used to create the refinement, and KEY the attribute
+of the process. A value of nil indicates that there are no active refinements.")
+
(easy-menu-define proced-menu proced-mode-map
"Proced Menu."
`("Proced"
@@ -1337,20 +1345,7 @@ a certain refinement, consider defining a new filter in `proced-filter-alist'."
(let* ((grammar (assq key proced-grammar-alist))
(refiner (nth 7 grammar)))
(when refiner
- (cond ((functionp (car refiner))
- (setq proced-process-alist (funcall (car refiner) pid)))
- ((consp refiner)
- (let ((predicate (nth 4 grammar))
- (ref (cdr (assq key (cdr (assq pid proced-process-alist)))))
- val new-alist)
- (dolist (process proced-process-alist)
- (setq val (funcall predicate (cdr (assq key (cdr process))) ref))
- (if (cond ((not val) (nth 2 refiner))
- ((eq val 'equal) (nth 1 refiner))
- (val (car refiner)))
- (push process new-alist)))
- (setq proced-process-alist new-alist))))
- ;; Do not revert listing.
+ (add-to-list 'proced-refinements (list refiner pid key grammar) t)
(proced-update)))
(message "No refiner defined here."))))
@@ -1859,10 +1854,29 @@ After updating a displayed Proced buffer run the normal hook
"Updating process display...")))
(if revert ;; evaluate all processes
(setq proced-process-alist (proced-process-attributes)))
- ;; filtering and sorting
+ ;; filtering
+ (setq proced-process-alist (proced-filter proced-process-alist proced-filter))
+ ;; refinements
+ (pcase-dolist (`(,refiner ,pid ,key ,grammar) proced-refinements)
+ ;; It's possible the process has exited since the refinement was made
+ (when (assq pid proced-process-alist)
+ (cond ((functionp (car refiner))
+ (setq proced-process-alist (funcall (car refiner) pid)))
+ ((consp refiner)
+ (let ((predicate (nth 4 grammar))
+ (ref (cdr (assq key (cdr (assq pid proced-process-alist)))))
+ val new-alist)
+ (dolist (process proced-process-alist)
+ (setq val (funcall predicate (cdr (assq key (cdr process))) ref))
+ (when (cond ((not val) (nth 2 refiner))
+ ((eq val 'equal) (nth 1 refiner))
+ (val (car refiner)))
+ (push process new-alist)))
+ (setq proced-process-alist new-alist))))))
+
+ ;; sorting
(setq proced-process-alist
- (proced-sort (proced-filter proced-process-alist proced-filter)
- proced-sort proced-descend))
+ (proced-sort proced-process-alist proced-sort proced-descend))
;; display as process tree?
(setq proced-process-alist
@@ -1976,7 +1990,9 @@ After updating a displayed Proced buffer run the normal hook
(defun proced-revert (&rest _args)
"Reevaluate the process listing based on the currently running processes.
-Preserves point and marks."
+Preserves point and marks, but not refinements (see `proced-refine' for
+information on refinements)."
+ (setq proced-refinements nil)
(proced-update t))
(defun proced-marked-processes ()
diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el
index 82a13e97625..972a4d5aa5d 100644
--- a/lisp/progmodes/c-ts-mode.el
+++ b/lisp/progmodes/c-ts-mode.el
@@ -800,6 +800,10 @@ Set up:
(unless (treesit-ready-p 'cpp)
(error "Tree-sitter for C++ isn't available"))
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "raw_string_literal")))
+
(treesit-parser-create 'cpp)
(setq-local syntax-propertize-function
#'c-ts-mode--syntax-propertize)
diff --git a/lisp/progmodes/csharp-mode.el b/lisp/progmodes/csharp-mode.el
index bd0e023db18..4bd5d15fb1b 100644
--- a/lisp/progmodes/csharp-mode.el
+++ b/lisp/progmodes/csharp-mode.el
@@ -899,6 +899,11 @@ Key bindings:
;; Comments.
(c-ts-mode-comment-setup)
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "verbatim_string-literal"
+ "interpolated_verbatim_string-text")))
+
;; Indent.
(setq-local treesit-simple-indent-rules csharp-ts-mode--indent-rules)
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index a4a8cd84050..7af62c35358 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -1635,6 +1635,7 @@ buffer."
(define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode
"Flymake diagnostics"
"A mode for listing Flymake diagnostics."
+ :interactive nil
(setq tabulated-list-format flymake--diagnostics-base-tabulated-list-format)
(setq tabulated-list-entries
'flymake--diagnostics-buffer-entries)
@@ -1692,6 +1693,7 @@ some of this variable's contents the diagnostic listings.")
(define-derived-mode flymake-project-diagnostics-mode tabulated-list-mode
"Flymake diagnostics"
"A mode for listing Flymake diagnostics."
+ :interactive nil
(setq tabulated-list-format
(vconcat [("File" 25 t)]
flymake--diagnostics-base-tabulated-list-format))
diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el
index e8d8f9104e4..ff14546c63a 100644
--- a/lisp/progmodes/gdb-mi.el
+++ b/lisp/progmodes/gdb-mi.el
@@ -1113,13 +1113,13 @@ no input, and GDB is waiting for input."
(process-live-p proc)
(not gud-running)
(= (point) (marker-position (process-mark proc))))
- ;; Sending an EOF does not work with GDB-MI; submit an
- ;; explicit quit command.
- (progn
- (if (> gdb-control-level 0)
- (process-send-eof proc)
- (insert "quit")
- (comint-send-input t t)))
+ ;; Exit a recursive reading loop or quit.
+ (if (> gdb-control-level 0)
+ (process-send-eof proc)
+ ;; Sending an EOF does not work with GDB-MI; submit an
+ ;; explicit quit command.
+ (insert "quit")
+ (comint-send-input t t))
(delete-char arg))))
(defvar gdb-define-alist nil "Alist of #define directives for GUD tooltips.")
@@ -4355,6 +4355,24 @@ member."
:group 'gud
:version "29.1")
+(defcustom gdb-locals-table-row-config `((name . 20)
+ (type . 20)
+ (value . ,gdb-locals-value-limit))
+ "Configuration for table rows in the local variable display.
+
+An alist that controls the display of the name, type and value of
+local variables inside the currently active stack-frame. The key
+controls which column to change whereas the value determines the
+maximum number of characters to display in each column. A value
+of 0 means there is no limit.
+
+Additionally, the order the element in the alist determines the
+left-to-right display order of the properties."
+ :type '(alist :key-type symbol :value-type integer)
+ :group 'gud
+ :version "30.1")
+
+
(defvar gdb-locals-values-table (make-hash-table :test #'equal)
"Mapping of local variable names to a string with their value.")
@@ -4384,12 +4402,9 @@ member."
(defun gdb-locals-value-filter (value)
"Filter function for the local variable VALUE."
- (let* ((no-nl (replace-regexp-in-string "\n" " " value))
- (str (replace-regexp-in-string "[[:space:]]+" " " no-nl))
- (limit gdb-locals-value-limit))
- (if (>= (length str) limit)
- (concat (substring str 0 limit) "...")
- str)))
+ (let* ((no-nl (replace-regexp-in-string "\n" " " (or value "<Unknown>")))
+ (str (replace-regexp-in-string "[[:space:]]+" " " no-nl)))
+ str))
(defun gdb-edit-locals-value (&optional event)
"Assign a value to a variable displayed in the locals buffer."
@@ -4403,6 +4418,22 @@ member."
(gud-basic-call
(concat "-gdb-set variable " var " = " value)))))
+
+(defun gdb-locals-table-columns-list (alist)
+ "Format and arrange the columns in locals display based on ALIST."
+ (let (columns)
+ (dolist (config gdb-locals-table-row-config columns)
+ (let* ((key (car config))
+ (max (cdr config))
+ (prop (alist-get key alist)))
+ (when prop
+ (if (and (> max 0) (length> prop max))
+ (push (propertize (string-truncate-left prop max) 'help-echo prop)
+ columns)
+ (push prop columns)))))
+ (nreverse columns)))
+
+
;; Complex data types are looked up in `gdb-locals-values-table'.
(defun gdb-locals-handler-custom ()
"Handler to rebuild the local variables table buffer."
@@ -4431,12 +4462,14 @@ member."
help-echo "mouse-2: edit value"
local-map ,gdb-edit-locals-map-1)
value))
+ (setf (gdb-table-right-align table) t)
+ (setq name (propertize name 'font-lock-face font-lock-variable-name-face))
+ (setq type (propertize type 'font-lock-face font-lock-type-face))
(gdb-table-add-row
table
- (list
- (propertize type 'font-lock-face font-lock-type-face)
- (propertize name 'font-lock-face font-lock-variable-name-face)
- value)
+ (gdb-locals-table-columns-list `((name . ,name)
+ (type . ,type)
+ (value . ,value)))
`(gdb-local-variable ,local))))
(insert (gdb-table-string table " "))
(setq mode-name
@@ -5124,6 +5157,8 @@ This arrangement depends on the values of variable
(defun gdb-reset ()
"Exit a debugging session cleanly.
Kills the gdb buffers, and resets variables and the source buffers."
+ ;; Save GDB history
+ (comint-write-input-ring)
;; The gdb-inferior buffer has a pty hooked up to the main gdb
;; process. This pty must be deleted explicitly.
(let ((pty (get-process "gdb-inferior")))
diff --git a/lisp/progmodes/gud.el b/lisp/progmodes/gud.el
index 143fa8c6798..6ffcf497b93 100644
--- a/lisp/progmodes/gud.el
+++ b/lisp/progmodes/gud.el
@@ -159,143 +159,96 @@ Used to gray out relevant toolbar icons.")
(t
(comint-interrupt-subjob)))))
-(easy-mmode-defmap gud-menu-map
- '(([help] "Info (debugger)" . gud-goto-info)
- ([tooltips] menu-item "Show GUD tooltips" gud-tooltip-mode
- :enable (and (not emacs-basic-display)
- (display-graphic-p)
- (fboundp 'x-show-tip))
- :visible (memq gud-minor-mode
- '(gdbmi guiler dbx sdb xdb pdb))
- :button (:toggle . gud-tooltip-mode))
- ([refresh] "Refresh" . gud-refresh)
- ([run] menu-item "Run" gud-run
- :enable (not gud-running)
- :visible (or (memq gud-minor-mode '(gdb dbx jdb))
- (and (eq gud-minor-mode 'gdbmi)
- (or (not (gdb-show-run-p))
- (bound-and-true-p
- gdb-active-process)))))
- ([go] . (menu-item (if (bound-and-true-p gdb-active-process)
- "Continue" "Run")
- gud-go
- :visible (and (eq gud-minor-mode 'gdbmi)
- (gdb-show-run-p))))
- ([stop] menu-item "Stop" gud-stop-subjob
- :visible (or (not (memq gud-minor-mode '(gdbmi pdb)))
- (and (eq gud-minor-mode 'gdbmi)
- (gdb-show-stop-p))))
- ([until] menu-item "Continue to selection" gud-until
- :enable (not gud-running)
- :visible (and (memq gud-minor-mode '(gdbmi gdb perldb))
- (gud-tool-bar-item-visible-no-fringe)))
- ([remove] menu-item "Remove Breakpoint" gud-remove
- :enable (not gud-running)
- :visible (gud-tool-bar-item-visible-no-fringe))
- ([tbreak] menu-item "Temporary Breakpoint" gud-tbreak
- :enable (not gud-running)
- :visible (memq gud-minor-mode
- '(gdbmi gdb sdb xdb)))
- ([break] menu-item "Set Breakpoint" gud-break
- :enable (not gud-running)
- :visible (gud-tool-bar-item-visible-no-fringe))
- ([up] menu-item "Up Stack" gud-up
- :enable (not gud-running)
- :visible (memq gud-minor-mode
- '(gdbmi gdb guiler dbx xdb jdb pdb)))
- ([down] menu-item "Down Stack" gud-down
- :enable (not gud-running)
- :visible (memq gud-minor-mode
- '(gdbmi gdb guiler dbx xdb jdb pdb)))
- ([pp] menu-item "Print S-expression" gud-pp
- :enable (and (not gud-running)
- (bound-and-true-p gdb-active-process))
- :visible (and (string-equal
- (buffer-local-value
- 'gud-target-name gud-comint-buffer)
- "emacs")
- (eq gud-minor-mode 'gdbmi)))
- ([print*] . (menu-item (if (eq gud-minor-mode 'jdb)
- "Dump object"
- "Print Dereference")
- gud-pstar
- :enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb jdb))))
- ([print] menu-item "Print Expression" gud-print
- :enable (not gud-running))
- ([watch] menu-item "Watch Expression" gud-watch
- :enable (not gud-running)
- :visible (eq gud-minor-mode 'gdbmi))
- ([finish] menu-item "Finish Function" gud-finish
- :enable (not gud-running)
- :visible (memq gud-minor-mode
- '(gdbmi gdb guiler xdb jdb pdb)))
- ([stepi] menu-item "Step Instruction" gud-stepi
- :enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb dbx)))
- ([nexti] menu-item "Next Instruction" gud-nexti
- :enable (not gud-running)
- :visible (memq gud-minor-mode '(gdbmi gdb dbx)))
- ([step] menu-item "Step Line" gud-step
- :enable (not gud-running))
- ([next] menu-item "Next Line" gud-next
- :enable (not gud-running))
- ([cont] menu-item "Continue" gud-cont
- :enable (not gud-running)
- :visible (not (eq gud-minor-mode 'gdbmi))))
- "Menu for `gud-mode'."
- :name "Gud")
-
-(easy-mmode-defmap gud-minor-mode-map
- (append
- `(([menu-bar debug] . ("Gud" . ,gud-menu-map)))
- ;; Get tool bar like functionality from the menu bar on a text only
- ;; terminal.
- (unless window-system
- `(([menu-bar down]
- . (,(propertize "down" 'face 'font-lock-doc-face) . gud-down))
- ([menu-bar up]
- . (,(propertize "up" 'face 'font-lock-doc-face) . gud-up))
- ([menu-bar finish]
- . (,(propertize "finish" 'face 'font-lock-doc-face) . gud-finish))
- ([menu-bar step]
- . (,(propertize "step" 'face 'font-lock-doc-face) . gud-step))
- ([menu-bar next]
- . (,(propertize "next" 'face 'font-lock-doc-face) . gud-next))
- ([menu-bar until] menu-item
- ,(propertize "until" 'face 'font-lock-doc-face) gud-until
- :visible (memq gud-minor-mode '(gdbmi gdb perldb)))
- ([menu-bar cont] menu-item
- ,(propertize "cont" 'face 'font-lock-doc-face) gud-cont
- :visible (not (eq gud-minor-mode 'gdbmi)))
- ([menu-bar run] menu-item
- ,(propertize "run" 'face 'font-lock-doc-face) gud-run
- :visible (memq gud-minor-mode '(gdbmi gdb dbx jdb)))
- ([menu-bar go] menu-item
- ,(propertize " go " 'face 'font-lock-doc-face) gud-go
- :visible (and (eq gud-minor-mode 'gdbmi)
- (gdb-show-run-p)))
- ([menu-bar stop] menu-item
- ,(propertize "stop" 'face 'font-lock-doc-face) gud-stop-subjob
- :visible (or (and (eq gud-minor-mode 'gdbmi)
- (gdb-show-stop-p))
- (not (eq gud-minor-mode 'gdbmi))))
- ([menu-bar print]
- . (,(propertize "print" 'face 'font-lock-doc-face) . gud-print))
- ([menu-bar tools] . undefined)
- ([menu-bar buffer] . undefined)
- ([menu-bar options] . undefined)
- ([menu-bar edit] . undefined)
- ([menu-bar file] . undefined))))
- "Map used in visited files.")
+(defvar-keymap gud-mode-map
+ ;; Will inherit from comint-mode via define-derived-mode.
+ :doc "`gud-mode' keymap.")
-(setf (alist-get 'gud-minor-mode minor-mode-map-alist)
- gud-minor-mode-map)
+(defvar-keymap gud-minor-mode-map
+ :parent gud-mode-map)
-(defvar gud-mode-map
- ;; Will inherit from comint-mode via define-derived-mode.
- (make-sparse-keymap)
- "`gud-mode' keymap.")
+(easy-menu-define gud-menu-map gud-mode-map
+ "Menu for `gud-mode'."
+ '("Gud"
+ ["Continue" gud-cont
+ :enable (not gud-running)
+ :visible (not (eq gud-minor-mode 'gdbmi))]
+ ["Next Line" gud-next
+ :enable (not gud-running)]
+ ["Step Line" gud-step
+ :enable (not gud-running)]
+ ["Next Instruction" gud-nexti
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb dbx))]
+ ["Step Instruction" gud-stepi
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb dbx))]
+ ["Finish Function" gud-finish
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb guiler xdb jdb pdb))]
+ ["Watch Expression" gud-watch
+ :enable (not gud-running)
+ :visible (eq gud-minor-mode 'gdbmi)]
+ ["Print Expression" gud-print
+ :enable (not gud-running)]
+ ["Dump object-Derefenrece" gud-pstar
+ :label (if (eq gud-minor-mode 'jdb)
+ "Dump object"
+ "Print Dereference")
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb jdb))]
+ ["Print S-expression" gud-pp
+ :enable (and (not gud-running)
+ (bound-and-true-p gdb-active-process))
+ :visible (and (string-equal
+ (buffer-local-value
+ 'gud-target-name gud-comint-buffer)
+ "emacs")
+ (eq gud-minor-mode 'gdbmi))]
+ ["Down Stack" gud-down
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb guiler dbx xdb jdb pdb))]
+ ["Up Stack" gud-up
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode
+ '(gdbmi gdb guiler dbx xdb jdb pdb))]
+ ["Set Breakpoint" gud-break
+ :enable (not gud-running)
+ :visible (gud-tool-bar-item-visible-no-fringe)]
+ ["Temporary Breakpoint" gud-tbreak
+ :enable (not gud-running)
+ :visible (memq gud-minor-mode '(gdbmi gdb sdb xdb))]
+ ["Remove Breakpoint" gud-remove
+ :enable (not gud-running)
+ :visible (gud-tool-bar-item-visible-no-fringe)]
+ ["Continue to selection" gud-until
+ :enable (not gud-running)
+ :visible (and (memq gud-minor-mode '(gdbmi gdb perldb))
+ (gud-tool-bar-item-visible-no-fringe))]
+ ["Stop" gud-stop-subjob
+ :visible (or (not (memq gud-minor-mode '(gdbmi pdb)))
+ (and (eq gud-minor-mode 'gdbmi)
+ (gdb-show-stop-p)))]
+ ["Continue-Run" gud-go
+ :label (if (bound-and-true-p gdb-active-process)
+ "Continue" "Run")
+ :visible (and (eq gud-minor-mode 'gdbmi)
+ (gdb-show-run-p))]
+ ["Run" gud-run
+ :enable (not gud-running)
+ :visible (or (memq gud-minor-mode '(gdb dbx jdb))
+ (and (eq gud-minor-mode 'gdbmi)
+ (or (not (gdb-show-run-p))
+ (bound-and-true-p
+ gdb-active-process))))]
+ ["Refresh" gud-refresh]
+ ["Show GUD tooltips" gud-tooltip-mode
+ :enable (and (not emacs-basic-display)
+ (display-graphic-p)
+ (fboundp 'x-show-tip))
+ :visible (memq gud-minor-mode
+ '(gdbmi guiler dbx sdb xdb pdb))
+ :button (:toggle . gud-tooltip-mode)]
+ ["Info (debugger)" gud-goto-info]))
(setf (alist-get 'gud-minor-mode minor-mode-map-alist)
gud-minor-mode-map)
diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index c13cf032c44..215b5c16388 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -281,6 +281,11 @@ Return nil if there is no name or if NODE is not a defun node."
;; Comments.
(c-ts-mode-comment-setup)
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("line_comment"
+ "block_comment"
+ "text_block")))
+
;; Indent.
(setq-local treesit-simple-indent-rules java-ts-mode--indent-rules)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 0cc673a80ff..9c26c52df94 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3793,6 +3793,11 @@ Currently there are `js-mode' and `js-ts-mode'."
;; Comment.
(c-ts-mode-comment-setup)
(setq-local comment-multi-line t)
+
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "template_string")))
+
;; Electric-indent.
(setq-local electric-indent-chars
(append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*".
diff --git a/lisp/progmodes/prog-mode.el b/lisp/progmodes/prog-mode.el
index 58cb48f1829..2e0cb6cd25c 100644
--- a/lisp/progmodes/prog-mode.el
+++ b/lisp/progmodes/prog-mode.el
@@ -30,7 +30,12 @@
;;; Code:
(eval-when-compile (require 'cl-lib)
- (require 'subr-x))
+ (require 'subr-x)
+ (require 'treesit))
+
+(declare-function treesit-available-p "treesit.c")
+(declare-function treesit-parser-list "treesit.c")
+(declare-function treesit-node-type "treesit.c")
(defgroup prog-mode nil
"Generic programming mode, from which others derive."
@@ -102,7 +107,8 @@
(defvar-keymap prog-mode-map
:doc "Keymap used for programming modes."
- "C-M-q" #'prog-indent-sexp)
+ "C-M-q" #'prog-indent-sexp
+ "M-q" #'prog-fill-reindent-defun)
(defvar prog-indentation-context nil
"When non-nil, provides context for indenting embedded code chunks.
@@ -140,6 +146,31 @@ instead."
(end (progn (forward-sexp 1) (point))))
(indent-region start end nil))))
+(defun prog-fill-reindent-defun (&optional argument)
+ "Refill or reindent the paragraph or defun that contains point.
+
+If the point is in a string or a comment, fill the paragraph that
+contains point or follows point.
+
+Otherwise, reindent the function definition that contains point
+or follows point."
+ (interactive "P")
+ (save-excursion
+ (let ((treesit-text-node
+ (and (treesit-available-p)
+ (treesit-parser-list)
+ (string-match-p
+ treesit-text-type-regexp
+ (treesit-node-type (treesit-node-at (point)))))))
+ (if (or treesit-text-node
+ (nth 8 (syntax-ppss))
+ (re-search-forward "\\s-*\\s<" (line-end-position) t))
+ (fill-paragraph argument (region-active-p))
+ (beginning-of-defun)
+ (let ((start (point)))
+ (end-of-defun)
+ (indent-region start (point) nil))))))
+
(defun prog-first-column ()
"Return the indentation column normally used for top-level constructs."
(or (car prog-indentation-context) 0))
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index 3a3391ccdd2..d12ade36af3 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1623,6 +1623,10 @@ not written in Bash or sh."
( bracket delimiter misc-punctuation operator)))
(setq-local treesit-font-lock-settings
sh-mode--treesit-settings)
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "heredoc_start"
+ "heredoc_body")))
(setq-local treesit-defun-type-regexp "function_definition")
(treesit-major-mode-setup)))
diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index 8935165d1fa..05ddc0e7a94 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -334,6 +334,11 @@ Argument LANGUAGE is either `typescript' or `tsx'."
;; Comments.
(c-ts-mode-comment-setup)
+ (setq-local treesit-defun-prefer-top-level t)
+
+ (setq-local treesit-text-type-regexp
+ (regexp-opt '("comment"
+ "template_string")))
;; Electric
(setq-local electric-indent-chars
diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el
index e5458e6a07f..47a1cb32337 100644
--- a/lisp/progmodes/verilog-mode.el
+++ b/lisp/progmodes/verilog-mode.el
@@ -9,7 +9,7 @@
;; Keywords: languages
;; The "Version" is the date followed by the decimal rendition of the Git
;; commit hex.
-;; Version: 2021.10.14.127365406
+;; Version: 2022.12.18.181110314
;; Yoni Rabkin <yoni@rabkins.net> contacted the maintainer of this
;; file on 19/3/2008, and the maintainer agreed that when a bug is
@@ -124,7 +124,7 @@
;;
;; This variable will always hold the version number of the mode
-(defconst verilog-mode-version "2021-10-14-797711e-vpo-GNU"
+(defconst verilog-mode-version "2022-12-18-acb862a-vpo-GNU"
"Version of this Verilog mode.")
(defconst verilog-mode-release-emacs t
"If non-nil, this version of Verilog mode was released with Emacs itself.")
@@ -455,11 +455,11 @@ This function may be removed when Emacs 21 is no longer supported."
last-command-event)))
(defvar verilog-no-change-functions nil
- "True if `after-change-functions' is disabled.
+ "Non-nil if `after-change-functions' is disabled.
Use of `syntax-ppss' may break, as ppss's cache may get corrupted.")
(defvar verilog-in-hooks nil
- "True when within a `verilog-run-hooks' block.")
+ "Non-nil when within a `verilog-run-hooks' block.")
(defmacro verilog-run-hooks (&rest hooks)
"Run each hook in HOOKS using `run-hooks'.
@@ -505,8 +505,14 @@ Set `verilog-in-hooks' during this time, to assist AUTO caches."
(defvar verilog-debug nil
"Non-nil means enable debug messages for `verilog-mode' internals.")
-(defvar verilog-warn-fatal nil
- "Non-nil means `verilog-warn-error' warnings are fatal `error's.")
+(defcustom verilog-warn-fatal nil
+ "Non-nil means `verilog-warn-error' warnings are fatal `error's."
+ :group 'verilog-mode-auto
+ :type 'boolean)
+(put 'verilog-warn-fatal 'safe-local-variable #'verilog-booleanp)
+
+;; Internal use similar to `verilog-warn-fatal'
+(defvar verilog-warn-fatal-internal t)
(defcustom verilog-linter
"echo 'No verilog-linter set, see \"M-x describe-variable verilog-linter\"'"
@@ -679,6 +685,18 @@ Set to 0 to have all directives start at the left side of the screen."
:type 'integer)
(put 'verilog-indent-level-directive 'safe-local-variable #'integerp)
+(defcustom verilog-indent-ignore-multiline-defines t
+ "Non-nil means ignore indentation on lines that are part of a multiline define."
+ :group 'verilog-mode-indent
+ :type 'boolean)
+(put 'verilog-indent-ignore-multiline-defines 'safe-local-variable #'verilog-booleanp)
+
+(defcustom verilog-indent-ignore-regexp nil
+ "Regexp that matches lines that should be ignored for indentation."
+ :group 'verilog-mode-indent
+ :type 'boolean)
+(put 'verilog-indent-ignore-regexp 'safe-local-variable #'stringp)
+
(defcustom verilog-cexp-indent 2
"Indentation of Verilog statements split across lines."
:group 'verilog-mode-indent
@@ -723,6 +741,13 @@ Otherwise, line them up."
:type 'boolean)
(put 'verilog-indent-begin-after-if 'safe-local-variable #'verilog-booleanp)
+(defcustom verilog-indent-class-inside-pkg t
+ "Non-nil means indent classes inside packages.
+Otherwise, classes have zero indentation."
+ :group 'verilog-mode-indent
+ :type 'boolean)
+(put 'verilog-indent-class-inside-pkg 'safe-local-variable #'verilog-booleanp)
+
(defcustom verilog-align-ifelse nil
"Non-nil means align `else' under matching `if'.
Otherwise else is lined up with first character on line holding matching if."
@@ -730,6 +755,38 @@ Otherwise else is lined up with first character on line holding matching if."
:type 'boolean)
(put 'verilog-align-ifelse 'safe-local-variable #'verilog-booleanp)
+(defcustom verilog-align-decl-expr-comments t
+ "Non-nil means align declaration and expressions comments."
+ :group 'verilog-mode-indent
+ :type 'boolean)
+(put 'verilog-align-decl-expr-comments 'safe-local-variable #'verilog-booleanp)
+
+(defcustom verilog-align-comment-distance 1
+ "Distance (in spaces) between longest declaration/expression and comments.
+Only works if `verilog-align-decl-expr-comments' is non-nil."
+ :group 'verilog-mode-indent
+ :type 'integer)
+(put 'verilog-align-comment-distance 'safe-local-variable #'integerp)
+
+(defcustom verilog-align-assign-expr nil
+ "Non-nil means align expressions of continuous assignments."
+ :group 'verilog-mode-indent
+ :type 'boolean)
+(put 'verilog-align-assign-expr 'safe-local-variable #'verilog-booleanp)
+
+(defcustom verilog-align-typedef-regexp nil
+ "Regexp that matches user typedefs for declaration alignment."
+ :group 'verilog-mode-indent
+ :type '(choice (regexp :tag "Regexp")
+ (const :tag "None" nil)))
+(put 'verilog-align-typedef-regexp 'safe-local-variable #'stringp)
+
+(defcustom verilog-align-typedef-words nil
+ "List of words that match user typedefs for declaration alignment."
+ :group 'verilog-mode-indent
+ :type '(repeat string))
+(put 'verilog-align-typedef-words 'safe-local-variable #'listp)
+
(defcustom verilog-minimum-comment-distance 10
"Minimum distance (in lines) between begin and end required before a comment.
Setting this variable to zero results in every end acquiring a comment; the
@@ -876,6 +933,12 @@ always be saved."
:type 'boolean)
(put 'verilog-auto-star-save 'safe-local-variable #'verilog-booleanp)
+(defcustom verilog-fontify-variables t
+ "Non-nil means fontify declaration variables."
+ :group 'verilog-mode-actions
+ :type 'boolean)
+(put 'verilog-fontify-variables 'safe-local-variable #'verilog-booleanp)
+
(defvar verilog-auto-update-tick nil
"Modification tick at which autos were last performed.")
@@ -1052,7 +1115,7 @@ You might want these defined in each file; put at the *END* of your file
something like:
// Local Variables:
- // verilog-library-files:(\"/some/path/technology.v\" \"/some/path/tech2.v\")
+ // verilog-library-files:(\"/path/technology.v\" \"/path2/tech2.v\")
// End:
Verilog-mode attempts to detect changes to this local variable, but they
@@ -1124,7 +1187,7 @@ those temporaries reset. See example in `verilog-auto-reset'."
(put 'verilog-auto-reset-blocking-in-non 'safe-local-variable #'verilog-booleanp)
(defcustom verilog-auto-reset-widths t
- "True means AUTORESET should determine the width of signals.
+ "Non-nil means AUTORESET should determine the width of signals.
This is then used to set the width of the zero (32'h0 for example). This
is required by some lint tools that aren't smart enough to ignore widths of
the constant zero. This may result in ugly code when parameters determine
@@ -1264,7 +1327,7 @@ See `verilog-auto-inst-param-value'."
Also affects AUTOINSTPARAM. Declaration order is the default for
backward compatibility, and as some teams prefer signals that are
declared together to remain together. Sorted order reduces
-changes when declarations are moved around in a file. Sorting is
+changes when declarations are moved around in a file. Sorting is
within input/output/inout groupings, there is intentionally no
option to intermix between input/output/inouts.
@@ -1275,7 +1338,7 @@ See also `verilog-auto-arg-sort'."
(put 'verilog-auto-inst-sort 'safe-local-variable #'verilog-booleanp)
(defcustom verilog-auto-inst-vector t
- "True means when creating default ports with AUTOINST, use bus subscripts.
+ "Non-nil means when creating default ports with AUTOINST, use bus subscripts.
If nil, skip the subscript when it matches the entire bus as declared in
the module (AUTOWIRE signals always are subscripted, you must manually
declare the wire to have the subscripts removed.) Setting this to nil may
@@ -1515,10 +1578,9 @@ If set will become buffer local.")
(define-key map "\C-c/" #'verilog-star-comment)
(define-key map "\C-c\C-c" #'verilog-comment-region)
(define-key map "\C-c\C-u" #'verilog-uncomment-region)
- (when (featurep 'xemacs)
- (define-key map [(meta control h)] #'verilog-mark-defun)
- (define-key map "\M-\C-a" #'verilog-beg-of-defun)
- (define-key map "\M-\C-e" #'verilog-end-of-defun))
+ (define-key map "\M-\C-h" #'verilog-mark-defun)
+ (define-key map "\M-\C-a" #'verilog-beg-of-defun)
+ (define-key map "\M-\C-e" #'verilog-end-of-defun)
(define-key map "\C-c\C-d" #'verilog-goto-defun)
(define-key map "\C-c\C-k" #'verilog-delete-auto)
(define-key map "\C-c\C-a" #'verilog-auto)
@@ -2028,11 +2090,11 @@ Where __FLAGS__ appears in the string `verilog-current-flags'
will be substituted. Where __FILE__ appears in the string, the
current buffer's file-name, without the directory portion, will
be substituted."
- (setq command (verilog-string-replace-matches
+ (setq command (verilog-string-replace-matches
;; Note \\b only works if under verilog syntax table
"\\b__FLAGS__\\b" (verilog-current-flags)
t t command))
- (setq command (verilog-string-replace-matches
+ (setq command (verilog-string-replace-matches
"\\b__FILE__\\b" (file-name-nondirectory
(or (buffer-file-name) ""))
t t command))
@@ -2468,13 +2530,8 @@ find the errors."
;;
;; Regular expressions used to calculate indent, etc.
;;
-(defconst verilog-symbol-re "\\<[a-zA-Z_][a-zA-Z_0-9.]*\\>")
-;; Want to match
-;; aa :
-;; aa,bb :
-;; a[34:32] :
-;; a,
-;; b :
+(defconst verilog-identifier-re "[a-zA-Z_][a-zA-Z_0-9]*")
+(defconst verilog-identifier-sym-re (concat "\\<" verilog-identifier-re "\\>"))
(defconst verilog-assignment-operator-re
(eval-when-compile
(verilog-regexp-opt
@@ -2492,12 +2549,11 @@ find the errors."
) 't
)))
(defconst verilog-assignment-operation-re
- (concat
- ;; "\\(^\\s-*[A-Za-z0-9_]+\\(\\[\\([A-Za-z0-9_]+\\)\\]\\)*\\s-*\\)"
- ;; "\\(^\\s-*[^=<>+-*/%&|^:\\s-]+[^=<>+-*/%&|^\n]*?\\)"
- "\\(^.*?\\)" "\\B" verilog-assignment-operator-re "\\B" ))
+ (concat "\\(^.*?\\)" verilog-assignment-operator-re))
+(defconst verilog-assignment-operation-re-2
+ (concat "\\(.*?\\)" verilog-assignment-operator-re))
-(defconst verilog-label-re (concat verilog-symbol-re "\\s-*:\\s-*"))
+(defconst verilog-label-re (concat verilog-identifier-sym-re "\\s-*:\\s-*"))
(defconst verilog-property-re
(concat "\\(" verilog-label-re "\\)?"
;; "\\(assert\\|assume\\|cover\\)\\s-+property\\>"
@@ -2732,6 +2788,9 @@ find the errors."
"\\|\\(\\<clocking\\>\\)" ;17
"\\|\\(\\<`[ou]vm_[a-z_]+_begin\\>\\)" ;18
"\\|\\(\\<`vmm_[a-z_]+_member_begin\\>\\)"
+ "\\|\\(\\<`ifn?def\\>\\)" ;20, matched end can be: `else `elsif `endif
+ "\\|\\(\\<`else\\>\\)" ;21, matched end can be: `endif
+ "\\|\\(\\<`elsif\\>\\)" ;22, matched end can be: `else `endif
;;
))
@@ -2817,40 +2876,54 @@ find the errors."
"localparam" "parameter" "var"
;; misc
"string" "event" "chandle" "virtual" "enum" "genvar"
- "struct" "union"
+ "struct" "union" "type"
;; builtin classes
"mailbox" "semaphore"
))))
-(defconst verilog-declaration-re
- (concat "\\(" verilog-declaration-prefix-re "\\s-*\\)?" verilog-declaration-core-re))
(defconst verilog-range-re "\\(\\[[^]]*\\]\\s-*\\)+")
(defconst verilog-optional-signed-re "\\s-*\\(\\(un\\)?signed\\)?")
(defconst verilog-optional-signed-range-re
- (concat
- "\\s-*\\(\\<\\(reg\\|wire\\)\\>\\s-*\\)?\\(\\<\\(un\\)?signed\\>\\s-*\\)?\\(" verilog-range-re "\\)?"))
+ (concat "\\s-*\\(\\<\\(reg\\|wire\\)\\>\\s-*\\)?\\(\\<\\(un\\)?signed\\>\\s-*\\)?\\(" verilog-range-re "\\)?"))
(defconst verilog-macroexp-re "`\\sw+")
-
(defconst verilog-delay-re "#\\s-*\\(\\([0-9_]+\\('s?[hdxbo][0-9a-fA-F_xz]+\\)?\\)\\|\\(([^()]*)\\)\\|\\(\\sw+\\)\\)")
-(defconst verilog-declaration-re-2-no-macro
- (concat "\\s-*" verilog-declaration-re
- "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)"
- "\\)"))
-(defconst verilog-declaration-re-2-macro
- (concat "\\s-*" verilog-declaration-re
- "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)"
- "\\|\\(" verilog-macroexp-re "\\)"
- "\\)"))
-(defconst verilog-declaration-re-1-macro
- (concat "^" verilog-declaration-re-2-macro))
-
-(defconst verilog-declaration-re-1-no-macro (concat "^" verilog-declaration-re-2-no-macro))
+(defconst verilog-interface-modport-re "\\(\\s-*\\([a-zA-Z0-9`_$]+\\.[a-zA-Z0-9`_$]+\\)[ \t\f]+\\)")
+(defconst verilog-comment-start-regexp "//\\|/\\*" "Dual comment value for `comment-start-regexp'.")
+(defconst verilog-typedef-enum-re
+ (concat "^\\s-*\\(typedef\\s-+\\)?enum\\(\\s-+" verilog-declaration-core-re verilog-optional-signed-range-re "\\)?"))
+
+(defconst verilog-declaration-simple-re
+ (concat "\\(" verilog-declaration-prefix-re "\\s-*\\)?" verilog-declaration-core-re))
+(defconst verilog-declaration-re
+ (concat "\\s-*" verilog-declaration-simple-re
+ "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)\\)"))
+(defconst verilog-declaration-re-macro
+ (concat "\\s-*" verilog-declaration-simple-re
+ "\\s-*\\(\\(" verilog-optional-signed-range-re "\\)\\|\\(" verilog-delay-re "\\)\\|\\(" verilog-macroexp-re "\\)\\)"))
+(defconst verilog-declaration-or-iface-mp-re
+ (concat "\\(" verilog-declaration-re "\\)\\|\\(" verilog-interface-modport-re "\\)"))
+(defconst verilog-declaration-embedded-comments-re
+ (concat "\\( " verilog-declaration-re "\\) ""\\s-*" "\\(" verilog-comment-start-regexp "\\)")
+ "Match expressions such as: input logic [7:0] /* auto enum sm_psm */ sm_psm;.")
(defconst verilog-defun-re
(eval-when-compile (verilog-regexp-words '("macromodule" "connectmodule" "module" "class" "program" "interface" "package" "primitive" "config"))))
(defconst verilog-end-defun-re
(eval-when-compile (verilog-regexp-words '("endconnectmodule" "endmodule" "endclass" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig"))))
+(defconst verilog-defun-tf-re-beg
+ (eval-when-compile (verilog-regexp-words '("macromodule" "connectmodule" "module" "class" "program" "interface" "package" "primitive" "config" "function" "task"))))
+(defconst verilog-defun-tf-re-end
+ (eval-when-compile (verilog-regexp-words '("endconnectmodule" "endmodule" "endclass" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig" "endfunction" "endtask"))))
+(defconst verilog-defun-tf-re-all
+ (eval-when-compile (verilog-regexp-words '("macromodule" "connectmodule" "module" "class" "program" "interface" "package" "primitive" "config" "function" "task"
+ "endconnectmodule" "endmodule" "endclass" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig" "endfunction" "endtask"))))
+(defconst verilog-defun-no-class-re
+ (eval-when-compile (verilog-regexp-words '("macromodule" "connectmodule" "module" "program" "interface" "package" "primitive" "config"))))
+(defconst verilog-end-defun-no-class-re
+ (eval-when-compile (verilog-regexp-words '("endconnectmodule" "endmodule" "endprogram" "endinterface" "endpackage" "endprimitive" "endconfig"))))
(defconst verilog-zero-indent-re
(concat verilog-defun-re "\\|" verilog-end-defun-re))
+(defconst verilog-zero-indent-no-class-re
+ (concat verilog-defun-no-class-re "\\|" verilog-end-defun-no-class-re))
(defconst verilog-inst-comment-re
(eval-when-compile (verilog-regexp-words '("Outputs" "Inouts" "Inputs" "Interfaces" "Interfaced"))))
@@ -2983,19 +3056,38 @@ find the errors."
(defconst verilog-extended-case-re "\\(\\(unique0?\\s-+\\|priority\\s-+\\)?case[xz]?\\|randcase\\)")
(defconst verilog-extended-complete-re
;; verilog-beg-of-statement also looks backward one token to extend this match
- (concat "\\(\\(\\<extern\\s-+\\|\\<\\(\\<\\(pure\\|context\\)\\>\\s-+\\)?virtual\\s-+\\|\\<protected\\s-+\\|\\<static\\s-+\\)*\\(\\<function\\>\\|\\<task\\>\\)\\)"
+ (concat "\\(\\(\\<extern\\s-+\\|\\<\\(\\<\\(pure\\|context\\)\\>\\s-+\\)?virtual\\s-+\\|\\<local\\s-+\\|\\<protected\\s-+\\|\\<static\\s-+\\)*\\(\\<function\\>\\|\\<task\\>\\)\\)"
"\\|\\(\\(\\<typedef\\>\\s-+\\)*\\(\\<struct\\>\\|\\<union\\>\\|\\<class\\>\\)\\)"
"\\|\\(\\(\\<\\(import\\|export\\)\\>\\s-+\\)?\\(\"DPI\\(-C\\)?\"\\s-+\\)?\\(\\<\\(pure\\|context\\)\\>\\s-+\\)?\\([A-Za-z_][A-Za-z0-9_]*\\s-*=\\s-*\\)?\\(function\\>\\|task\\>\\)\\)"
"\\|" verilog-extended-case-re ))
+
+(eval-and-compile
+ (defconst verilog-basic-complete-words
+ '("always" "assign" "always_latch" "always_ff" "always_comb" "analog" "connectmodule" "constraint"
+ "import" "initial" "final" "module" "macromodule" "repeat" "randcase" "while"
+ "if" "for" "forever" "foreach" "else" "parameter" "do" "localparam" "assert" "default" "generate"))
+ (defconst verilog-basic-complete-words-expr
+ (let ((words verilog-basic-complete-words))
+ (dolist (word '("default" "parameter" "localparam"))
+ (setq words (remove word words)))
+ words))
+ (defconst verilog-basic-complete-words-expr-no-assign
+ (remove "assign" verilog-basic-complete-words-expr)))
+
(defconst verilog-basic-complete-re
(eval-when-compile
- (verilog-regexp-words
- '(
- "always" "assign" "always_latch" "always_ff" "always_comb" "analog" "connectmodule" "constraint"
- "import" "initial" "final" "module" "macromodule" "repeat" "randcase" "while"
- "if" "for" "forever" "foreach" "else" "parameter" "do" "localparam" "assert"
- ))))
-(defconst verilog-complete-reg
+ (verilog-regexp-words verilog-basic-complete-words)))
+
+(defconst verilog-basic-complete-expr-re
+ (eval-when-compile
+ (verilog-regexp-words verilog-basic-complete-words-expr)))
+
+(defconst verilog-basic-complete-expr-no-assign-re
+ (eval-when-compile
+ (verilog-regexp-words verilog-basic-complete-words-expr-no-assign)))
+
+
+(defconst verilog-complete-re
(concat
verilog-extended-complete-re "\\|\\(" verilog-basic-complete-re "\\)"))
@@ -3114,9 +3206,6 @@ find the errors."
))
"List of Verilog keywords.")
-(defconst verilog-comment-start-regexp "//\\|/\\*"
- "Dual comment value for `comment-start-regexp'.")
-
(defvar verilog-mode-syntax-table
(let ((table (make-syntax-table)))
;; Populate the syntax TABLE.
@@ -3338,12 +3427,12 @@ See also `verilog-font-lock-extra-types'.")
(list
"\\<\\(\\(macro\\|connect\\)?module\\|primitive\\|class\\|program\\|interface\\|package\\|task\\)\\>\\s-*\\(\\sw+\\)"
'(1 font-lock-keyword-face)
- '(3 font-lock-function-name-face prepend))
+ '(3 font-lock-function-name-face))
;; Fontify function definitions
(list
(concat "\\<function\\>\\s-+\\(integer\\|real\\(time\\)?\\|time\\)\\s-+\\(\\sw+\\)" )
'(1 font-lock-keyword-face)
- '(3 font-lock-constant-face prepend))
+ '(3 font-lock-constant-face))
'("\\<function\\>\\s-+\\(\\[[^]]+\\]\\)\\s-+\\(\\sw+\\)"
(1 font-lock-keyword-face)
(2 font-lock-constant-face append))
@@ -3358,12 +3447,12 @@ See also `verilog-font-lock-extra-types'.")
;; Pre-form for this anchored matcher:
;; First, avoid declaration keywords written in comments,
;; which can also trigger this anchor.
- '(if (not (verilog-in-comment-p))
+ '(if (and (not (verilog-in-comment-p))
+ (not (member (thing-at-point 'symbol) verilog-keywords)))
(verilog-single-declaration-end verilog-highlight-max-lookahead)
(point)) ;; => current declaration statement is of 0 length
nil ;; Post-form: nothing to be done
- '(0 font-lock-variable-name-face t t)))
- )))
+ '(0 font-lock-variable-name-face))))))
(setq verilog-font-lock-keywords-2
@@ -3617,7 +3706,7 @@ inserted using a single call to `verilog-insert'."
(defun verilog-single-declaration-end (limit)
"Return pos where current (single) declaration statement ends.
Also, this function moves POINT forward to the start of a variable name
-(skipping the range-part and whitespace).
+\(skipping the range-part and whitespace).
Function expected to be called with POINT just after a declaration keyword.
LIMIT sets the max POINT for searching and moving to. No such limit if LIMIT
is 0.
@@ -3629,8 +3718,6 @@ Meaning of *single* declaration:
and `output [1:0] y' is the other single declaration. In the 1st single
declaration, POINT is moved to start of `clk'. And in the 2nd declaration,
POINT is moved to `y'."
-
-
(let (maxpoint old-point)
;; maxpoint = min(curr-point + limit, buffer-size)
(setq maxpoint (if (eq limit 0)
@@ -3651,7 +3738,7 @@ POINT is moved to `y'."
(not (eq old-point (point)))
(not (eq (char-after) ?\; ))
(not (eq (char-after) ?\) ))
- (not (looking-at verilog-declaration-re)))
+ (not (looking-at (verilog-get-declaration-re))))
(setq old-point (point))
(ignore-errors
(forward-sexp)
@@ -3669,31 +3756,28 @@ This function moves POINT to the next variable within the same declaration (if
it exists).
LIMIT is expected to be the pos at which current single-declaration ends,
obtained using `verilog-single-declaration-end'."
-
- (let (found-var old-point)
-
- ;; Remove starting whitespace
- (verilog-forward-ws&directives limit)
-
- (when (< (point) limit) ;; no matching if this is violated
-
- ;; Find the variable name (match-data is set here)
- (setq found-var (re-search-forward verilog-symbol-re limit t))
-
- ;; Walk to this variable's delimiter
- (save-match-data
- (verilog-forward-ws&directives limit)
- (setq old-point nil)
- (while (and (< (point) limit)
- (not (member (char-after) '(?, ?\) ?\;)))
- (not (eq old-point (point))))
- (setq old-point (point))
+ (when (and verilog-fontify-variables
+ (not (member (thing-at-point 'symbol) verilog-keywords)))
+ (let (found-var old-point)
+ ;; Remove starting whitespace
+ (verilog-forward-ws&directives limit)
+ (when (< (point) limit) ;; no matching if this is violated
+ ;; Find the variable name (match-data is set here)
+ (setq found-var (re-search-forward verilog-identifier-sym-re limit t))
+ ;; Walk to this variable's delimiter
+ (save-match-data
(verilog-forward-ws&directives limit)
- (forward-sexp)
- (verilog-forward-ws&directives limit))
- ;; Only a comma or semicolon expected at this point
- (skip-syntax-forward "."))
- found-var)))
+ (setq old-point nil)
+ (while (and (< (point) limit)
+ (not (member (char-after) '(?, ?\) ?\] ?\} ?\;)))
+ (not (eq old-point (point))))
+ (setq old-point (point))
+ (verilog-forward-ws&directives limit)
+ (forward-sexp)
+ (verilog-forward-ws&directives limit))
+ ;; Only a comma or semicolon expected at this point
+ (skip-syntax-forward "."))
+ found-var))))
(defun verilog-point-text (&optional pointnum)
"Return text describing where POINTNUM or current point is (for errors).
@@ -3728,9 +3812,14 @@ Use filename, if current buffer being edited shorten to just buffer name."
(elsec 1)
(found nil)
(st (point)))
- (if (not (looking-at "\\<"))
- (forward-word-strictly -1))
+ (unless (looking-at "\\<")
+ (forward-word-strictly -1))
(cond
+ ((save-excursion
+ (goto-char st)
+ (member (preceding-char) '(?\) ?\} ?\])))
+ (goto-char st)
+ (backward-sexp 1))
((verilog-skip-backward-comment-or-string))
((looking-at "\\<else\\>")
(setq reg (concat
@@ -3754,7 +3843,17 @@ Use filename, if current buffer being edited shorten to just buffer name."
(setq found 't))))))
((looking-at verilog-end-block-re)
(verilog-leap-to-head))
- ((looking-at "\\(endmodule\\>\\)\\|\\(\\<endprimitive\\>\\)\\|\\(\\<endclass\\>\\)\\|\\(\\<endprogram\\>\\)\\|\\(\\<endinterface\\>\\)\\|\\(\\<endpackage\\>\\)\\|\\(\\<endconnectmodule\\>\\)")
+ (;; Fallback, when current word does not match `verilog-end-block-re'
+ (looking-at (concat
+ "\\(\\<endmodule\\>\\)\\|" ; 1
+ "\\(\\<endprimitive\\>\\)\\|" ; 2
+ "\\(\\<endclass\\>\\)\\|" ; 3
+ "\\(\\<endprogram\\>\\)\\|" ; 4
+ "\\(\\<endinterface\\>\\)\\|" ; 5
+ "\\(\\<endpackage\\>\\)\\|" ; 6
+ "\\(\\<endconnectmodule\\>\\)\\|" ; 7
+ "\\(\\<endchecker\\>\\)\\|" ; 8
+ "\\(\\<endconfig\\>\\)")) ; 9
(cond
((match-end 1)
(verilog-re-search-backward "\\<\\(macro\\)?module\\>" nil 'move))
@@ -3769,7 +3868,11 @@ Use filename, if current buffer being edited shorten to just buffer name."
((match-end 6)
(verilog-re-search-backward "\\<package\\>" nil 'move))
((match-end 7)
- (verilog-re-search-backward "\\<connectmodule\\>" nil 'move))
+ (verilog-re-search-backward "\\<connectmodule\\>" nil 'move))
+ ((match-end 8)
+ (verilog-re-search-backward "\\<checker\\>" nil 'move))
+ ((match-end 9)
+ (verilog-re-search-backward "\\<config\\>" nil 'move))
(t
(goto-char st)
(backward-sexp 1))))
@@ -3782,9 +3885,14 @@ Use filename, if current buffer being edited shorten to just buffer name."
(md 2)
(st (point))
(nest 'yes))
- (if (not (looking-at "\\<"))
- (forward-word-strictly -1))
+ (unless (looking-at "\\<")
+ (forward-word-strictly -1))
(cond
+ ((save-excursion
+ (goto-char st)
+ (member (following-char) '(?\( ?\{ ?\[)))
+ (goto-char st)
+ (forward-sexp 1))
((verilog-skip-forward-comment-or-string)
(verilog-forward-syntactic-ws))
((looking-at verilog-beg-block-re-ordered)
@@ -3843,22 +3951,31 @@ Use filename, if current buffer being edited shorten to just buffer name."
;; Search forward for matching endtask
(setq reg "\\<endtask\\>" )
(setq nest 'no))
- ((match-end 12)
+ ((match-end 13)
;; Search forward for matching endgenerate
(setq reg "\\(\\<generate\\>\\)\\|\\(\\<endgenerate\\>\\)" ))
- ((match-end 13)
+ ((match-end 14)
;; Search forward for matching endgroup
(setq reg "\\(\\<covergroup\\>\\)\\|\\(\\<endgroup\\>\\)" ))
- ((match-end 14)
+ ((match-end 15)
;; Search forward for matching endproperty
(setq reg "\\(\\<property\\>\\)\\|\\(\\<endproperty\\>\\)" ))
- ((match-end 15)
+ ((match-end 16)
;; Search forward for matching endsequence
(setq reg "\\(\\<\\(rand\\)?sequence\\>\\)\\|\\(\\<endsequence\\>\\)" )
(setq md 3)) ; 3 to get to endsequence in the reg above
((match-end 17)
;; Search forward for matching endclocking
- (setq reg "\\(\\<clocking\\>\\)\\|\\(\\<endclocking\\>\\)" )))
+ (setq reg "\\(\\<clocking\\>\\)\\|\\(\\<endclocking\\>\\)" ))
+ ((match-end 20)
+ ;; Search forward for matching `ifn?def, can be `else `elseif or `endif
+ (setq reg "\\(\\<`ifn?def\\>\\)\\|\\(\\<`endif\\>\\|\\<`else\\>\\|\\<`elsif\\>\\)" ))
+ ((match-end 21)
+ ;; Search forward for matching `else, can be `endif
+ (setq reg "\\(\\<`else\\>\\|\\<`ifn?def\\>\\)\\|\\(\\<`endif\\>\\)" ))
+ ((match-end 22)
+ ;; Search forward for matching `elsif, can be `else or `endif, DONT support `elsif
+ (setq reg "\\(\\<`elsif\\>\\|\\<`ifn?def\\>\\)\\|\\(\\<`endif\\>\\|\\<`else\\>\\)" )))
(if (and reg
(forward-word-strictly 1))
(catch 'skip
@@ -3867,15 +3984,26 @@ Use filename, if current buffer being edited shorten to just buffer name."
here)
(while (verilog-re-search-forward reg nil 'move)
(cond
- ((match-end md) ; a closer in regular expression, so we are climbing out
+ ((and (or (match-end md)
+ (and (member (match-string-no-properties 1) '("`else" "`elsif"))
+ (= 1 depth)))
+ (or (and (member (match-string-no-properties 2) '("`else" "`elsif"))
+ (= 1 depth))
+ ;; stop at `else/`elsif which matching ifn?def (or `elsif with same depth)
+ ;; a closer in regular expression, so we are climbing out
+ (not (member (match-string-no-properties 2) '("`else" "`elsif")))))
(setq depth (1- depth))
(if (= 0 depth) ; we are out!
(throw 'skip 1)))
- ((match-end 1) ; an opener in the r-e, so we are in deeper now
+ ((and (match-end 1) ; an opener in the r-e, so we are in deeper now
+ (not (member (match-string-no-properties 1) '("`else" "`elsif"))))
(setq here (point)) ; remember where we started
(goto-char (match-beginning 1))
(cond
- ((if (or
+ ((verilog-looking-back "\\(\\<typedef\\>\\s-+\\)" (point-at-bol))
+ ;; avoid nesting for typedef class defs
+ (forward-word-strictly 1))
+ ((if (or
(looking-at verilog-disable-fork-re)
(and (looking-at "fork")
(progn
@@ -3890,28 +4018,37 @@ Use filename, if current buffer being edited shorten to just buffer name."
(throw 'skip 1))))))
((looking-at (concat
- "\\(\\<\\(macro\\)?module\\>\\)\\|"
- "\\(\\<primitive\\>\\)\\|"
- "\\(\\<class\\>\\)\\|"
- "\\(\\<program\\>\\)\\|"
- "\\(\\<interface\\>\\)\\|"
- "\\(\\<package\\>\\)\\|"
- "\\(\\<connectmodule\\>\\)"))
+ "\\(\\<\\(macro\\)?module\\>\\)\\|" ; 1,2
+ "\\(\\<primitive\\>\\)\\|" ; 3
+ "\\(\\(\\(interface\\|virtual\\)\\s-+\\)?\\<class\\>\\)\\|" ; 4,5,6
+ "\\(\\<program\\>\\)\\|" ; 7
+ "\\(\\<interface\\>\\)\\|" ; 8
+ "\\(\\<package\\>\\)\\|" ; 9
+ "\\(\\<connectmodule\\>\\)\\|" ; 10
+ "\\(\\<generate\\>\\)\\|" ; 11
+ "\\(\\<checker\\>\\)\\|" ; 12
+ "\\(\\<config\\>\\)")) ; 13
(cond
((match-end 1)
(verilog-re-search-forward "\\<endmodule\\>" nil 'move))
- ((match-end 2)
- (verilog-re-search-forward "\\<endprimitive\\>" nil 'move))
((match-end 3)
- (verilog-re-search-forward "\\<endclass\\>" nil 'move))
+ (verilog-re-search-forward "\\<endprimitive\\>" nil 'move))
((match-end 4)
+ (verilog-re-search-forward "\\<endclass\\>" nil 'move))
+ ((match-end 7)
(verilog-re-search-forward "\\<endprogram\\>" nil 'move))
- ((match-end 5)
+ ((match-end 8)
(verilog-re-search-forward "\\<endinterface\\>" nil 'move))
- ((match-end 6)
+ ((match-end 9)
(verilog-re-search-forward "\\<endpackage\\>" nil 'move))
- ((match-end 7)
- (verilog-re-search-forward "\\<endconnectmodule\\>" nil 'move))
+ ((match-end 10)
+ (verilog-re-search-forward "\\<endconnectmodule\\>" nil 'move))
+ ((match-end 11)
+ (verilog-re-search-forward "\\<endgenerate\\>" nil 'move))
+ ((match-end 12)
+ (verilog-re-search-forward "\\<endchecker\\>" nil 'move))
+ ((match-end 13)
+ (verilog-re-search-forward "\\<endconfig\\>" nil 'move))
(t
(goto-char st)
(if (= (following-char) ?\) )
@@ -3924,11 +4061,69 @@ Use filename, if current buffer being edited shorten to just buffer name."
(forward-sexp 1))))))
(defun verilog-declaration-beg ()
- (verilog-re-search-backward verilog-declaration-re (bobp) t))
-
-;;
-;;
-;; Mode
+ (verilog-re-search-backward (verilog-get-declaration-re) (bobp) t))
+
+(defun verilog-align-typedef-enabled-p ()
+ "Return non-nil if alignment of user typedefs is enabled.
+This will be automatically set when either `verilog-align-typedef-regexp'
+or `verilog-align-typedef-words' are non-nil."
+ (when (or verilog-align-typedef-regexp
+ verilog-align-typedef-words)
+ t))
+
+(defun verilog-get-declaration-typedef-re ()
+ "Return regexp of a user defined typedef.
+See `verilog-align-typedef-regexp' and `verilog-align-typedef-words'."
+ (let (typedef-re words words-re re)
+ (when (verilog-align-typedef-enabled-p)
+ (setq typedef-re verilog-align-typedef-regexp)
+ (setq words verilog-align-typedef-words)
+ (setq words-re (verilog-regexp-words verilog-align-typedef-words))
+ (cond ((and typedef-re (not words))
+ (setq re typedef-re))
+ ((and (not typedef-re) words)
+ (setq re words-re))
+ ((and typedef-re words)
+ (setq re (concat verilog-align-typedef-regexp "\\|" words-re))))
+ (concat "\\s-*" "\\(" verilog-declaration-prefix-re "\\s-*\\(" verilog-range-re "\\)?" "\\s-*\\)?"
+ (concat "\\(" re "\\)")
+ "\\(\\s-*" verilog-range-re "\\)?\\s-+"))))
+
+(defun verilog-get-declaration-re (&optional type)
+ "Return declaration regexp depending on customizable variables and TYPE."
+ (let ((re (cond ((equal type 'iface-mp)
+ verilog-declaration-or-iface-mp-re)
+ ((equal type 'embedded-comments)
+ verilog-declaration-embedded-comments-re)
+ (verilog-indent-declaration-macros
+ verilog-declaration-re-macro)
+ (t
+ verilog-declaration-re))))
+ (when (and (verilog-align-typedef-enabled-p)
+ (or (string= re verilog-declaration-or-iface-mp-re)
+ (string= re verilog-declaration-re)))
+ (setq re (concat "\\(" (verilog-get-declaration-typedef-re) "\\)\\|\\(" re "\\)")))
+ re))
+
+(defun verilog-looking-at-decl-to-align ()
+ "Return non-nil if pointing at a Verilog variable declaration that must be aligned."
+ (let* ((re (verilog-get-declaration-re))
+ (valid-re (looking-at re))
+ (id-pos (match-end 0)))
+ (and valid-re
+ (not (verilog-at-struct-decl-p))
+ (not (verilog-at-enum-decl-p))
+ (save-excursion
+ (goto-char id-pos)
+ (verilog-forward-syntactic-ws)
+ (and (not (looking-at ";"))
+ (not (member (thing-at-point 'symbol) verilog-keywords))
+ (progn ; Avoid alignment of instances whose name match user defined types
+ (forward-word)
+ (verilog-forward-syntactic-ws)
+ (not (looking-at "("))))))))
+
+;;; Mode:
;;
(defvar verilog-which-tool 1)
;;;###autoload
@@ -3965,6 +4160,11 @@ Variables controlling indentation/edit style:
function keyword.
`verilog-indent-level-directive' (default 1)
Indentation of \\=`ifdef/\\=`endif blocks.
+ `verilog-indent-ignore-multiline-defines' (default t)
+ Non-nil means ignore indentation on lines that are part of a multiline
+ define.
+ `verilog-indent-ignore-regexp' (default nil
+ Regexp that matches lines that should be ignored for indentation.
`verilog-cexp-indent' (default 1)
Indentation of Verilog statements broken across lines i.e.:
if (a)
@@ -3988,6 +4188,9 @@ Variables controlling indentation/edit style:
otherwise you get:
if (a)
begin
+ `verilog-indent-class-inside-pkg' (default t)
+ Non-nil means indent classes inside packages.
+ Otherwise, classes have zero indentation.
`verilog-auto-endcomments' (default t)
Non-nil means a comment /* ... */ is set after the ends which ends
cases, tasks, functions and modules.
@@ -3997,6 +4200,17 @@ Variables controlling indentation/edit style:
will be inserted. Setting this variable to zero results in every
end acquiring a comment; the default avoids too many redundant
comments in tight quarters.
+ `verilog-align-decl-expr-comments' (default t)
+ Non-nil means align declaration and expressions comments.
+ `verilog-align-comment-distance' (default 1)
+ Distance (in spaces) between longest declaration and comments.
+ Only works if `verilog-align-decl-expr-comments' is non-nil.
+ `verilog-align-assign-expr' (default nil)
+ Non-nil means align expressions of continuous assignments.
+ `verilog-align-typedef-regexp' (default nil)
+ Regexp that matches user typedefs for declaration alignment.
+ `verilog-align-typedef-words' (default nil)
+ List of words that match user typedefs for declaration alignment.
`verilog-auto-lineup' (default `declarations')
List of contexts where auto lineup of code should be done.
@@ -4020,17 +4234,20 @@ Some other functions are:
\\[verilog-mark-defun] Mark function.
\\[verilog-beg-of-defun] Move to beginning of current function.
\\[verilog-end-of-defun] Move to end of current function.
- \\[verilog-label-be] Label matching begin ... end, fork ... join, etc statements.
+ \\[verilog-label-be] Label matching begin ... end, fork ... join, etc
+ statements.
\\[verilog-comment-region] Put marked area in a comment.
- \\[verilog-uncomment-region] Uncomment an area commented with \\[verilog-comment-region].
+ \\[verilog-uncomment-region] Uncomment an area commented with
+ \\[verilog-comment-region].
\\[verilog-insert-block] Insert begin ... end.
\\[verilog-star-comment] Insert /* ... */.
\\[verilog-sk-always] Insert an always @(AS) begin .. end block.
\\[verilog-sk-begin] Insert a begin .. end block.
\\[verilog-sk-case] Insert a case block, prompting for details.
- \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for details.
+ \\[verilog-sk-for] Insert a for (...) begin .. end block, prompting for
+ details.
\\[verilog-sk-generate] Insert a generate .. endgenerate block.
\\[verilog-sk-header] Insert a header block at the top of file.
\\[verilog-sk-initial] Insert an initial begin .. end block.
@@ -4053,14 +4270,17 @@ Some other functions are:
\\[verilog-sk-else-if] Insert an else if (..) begin .. end block.
\\[verilog-sk-comment] Insert a comment block.
\\[verilog-sk-assign] Insert an assign .. = ..; statement.
- \\[verilog-sk-function] Insert a function .. begin .. end endfunction block.
+ \\[verilog-sk-function] Insert a function .. begin .. end endfunction
+ block.
\\[verilog-sk-input] Insert an input declaration, prompting for details.
\\[verilog-sk-output] Insert an output declaration, prompting for details.
- \\[verilog-sk-state-machine] Insert a state machine definition, prompting for details.
+ \\[verilog-sk-state-machine] Insert a state machine definition, prompting
+ for details.
\\[verilog-sk-inout] Insert an inout declaration, prompting for details.
\\[verilog-sk-wire] Insert a wire declaration, prompting for details.
\\[verilog-sk-reg] Insert a register declaration, prompting for details.
- \\[verilog-sk-define-signal] Define signal under point as a register at the top of the module.
+ \\[verilog-sk-define-signal] Define signal under point as a register at
+ the top of the module.
All key bindings can be seen in a Verilog-buffer with \\[describe-bindings].
Key bindings specific to `verilog-mode-map' are:
@@ -4147,7 +4367,7 @@ Key bindings specific to `verilog-mode-map' are:
;; verilog-mode-hook call added by define-derived-mode
)
-;;; Integration with the speedbar
+;;; Integration with the speedbar:
;;
;; Avoid problems with XEmacs byte-compiles.
@@ -4427,15 +4647,24 @@ following code fragment:
"Mark the current Verilog function (or procedure).
This puts the mark at the end, and point at the beginning."
(interactive)
- (if (featurep 'xemacs)
- (progn
- (push-mark)
- (verilog-end-of-defun)
- (push-mark)
- (verilog-beg-of-defun)
- (if (fboundp 'zmacs-activate-region)
- (zmacs-activate-region)))
- (mark-defun)))
+ (let (found)
+ (if (featurep 'xemacs)
+ (progn
+ (push-mark)
+ (verilog-end-of-defun)
+ (push-mark)
+ (verilog-beg-of-defun)
+ (if (fboundp 'zmacs-activate-region)
+ (zmacs-activate-region)))
+ ;; GNU Emacs
+ (when (verilog-beg-of-defun)
+ (setq found (point))
+ (verilog-end-of-defun)
+ (end-of-line)
+ (push-mark)
+ (goto-char found)
+ (beginning-of-line)
+ (setq mark-active t)))))
(defun verilog-comment-region (start end)
;; checkdoc-params: (start end)
@@ -4514,7 +4743,21 @@ area. See also `verilog-comment-region'."
(defun verilog-beg-of-defun ()
"Move backward to the beginning of the current function or procedure."
(interactive)
- (verilog-re-search-backward verilog-defun-re nil 'move))
+ (let (found)
+ (save-excursion
+ (when (verilog-looking-back verilog-defun-tf-re-end (point-at-bol))
+ (verilog-backward-sexp)
+ (setq found (point)))
+ (while (and (not found)
+ (verilog-re-search-backward verilog-defun-tf-re-all nil t))
+ (cond ((verilog-looking-back "\\(\\<typedef\\>\\s-+\\)" (point-at-bol)) ; corner case, e.g. 'typedef class <id>;'
+ (backward-word))
+ ((looking-at verilog-defun-tf-re-end)
+ (verilog-backward-sexp))
+ ((looking-at verilog-defun-tf-re-beg)
+ (setq found (point))))))
+ (when found
+ (goto-char found))))
(defun verilog-beg-of-defun-quick ()
"Move backward to the beginning of the current function or procedure.
@@ -4525,7 +4768,10 @@ Uses `verilog-scan' cache."
(defun verilog-end-of-defun ()
"Move forward to the end of the current function or procedure."
(interactive)
- (verilog-re-search-forward verilog-end-defun-re nil 'move))
+ (when (or (looking-at verilog-defun-tf-re-beg)
+ (verilog-beg-of-defun))
+ (verilog-forward-sexp)
+ (point)))
(defun verilog-get-end-of-defun ()
(save-excursion
@@ -4542,10 +4788,10 @@ Uses `verilog-scan' cache."
(case-fold-search nil)
(oldpos (point))
(b (progn
- (verilog-beg-of-defun)
+ (verilog-re-search-backward verilog-defun-re nil 'move)
(point-marker)))
(e (progn
- (verilog-end-of-defun)
+ (verilog-re-search-forward verilog-end-defun-re nil 'move)
(point-marker))))
(goto-char (marker-position b))
(if (> (- e b) 200)
@@ -4605,19 +4851,18 @@ Uses `verilog-scan' cache."
(goto-char h)))
;; stop if we see an extended complete reg, perhaps a complete one
(and
- (looking-at verilog-complete-reg)
+ (looking-at verilog-complete-re)
(let* ((p (point)))
(while (and (looking-at verilog-extended-complete-re)
(progn (setq p (point))
(verilog-backward-token)
(/= p (point)))))
(goto-char p)))
- ;; stop if we see a complete reg (previous found extended ones)
- (looking-at verilog-basic-complete-re)
;; stop if previous token is an ender
(save-excursion
(verilog-backward-token)
- (looking-at verilog-end-block-re))))
+ (or (looking-at verilog-end-block-re)
+ (verilog-in-directive-p)))))
(verilog-backward-syntactic-ws)
(verilog-backward-token))
;; Now point is where the previous line ended.
@@ -4634,28 +4879,23 @@ Uses `verilog-scan' cache."
(verilog-backward-syntactic-ws))
(let ((pt (point)))
(catch 'done
- (while (not (looking-at verilog-complete-reg))
+ (while (not (looking-at verilog-complete-re))
(setq pt (point))
(verilog-backward-syntactic-ws)
(if (or (bolp)
(= (preceding-char) ?\;)
+ (and (= (preceding-char) ?\{)
+ (save-excursion
+ (backward-char)
+ (verilog-at-struct-p)))
(progn
(verilog-backward-token)
- (looking-at verilog-ends-re)))
+ (or (looking-at verilog-ends-re)
+ (looking-at "begin"))))
(progn
(goto-char pt)
(throw 'done t)))))
(verilog-forward-syntactic-ws)))
-;;
-;; (while (and
-;; (not (looking-at verilog-complete-reg))
-;; (not (bolp))
-;; (not (= (preceding-char) ?\;)))
-;; (verilog-backward-token)
-;; (verilog-backward-syntactic-ws)
-;; (setq pt (point)))
-;; (goto-char pt)
-;; ;(verilog-forward-syntactic-ws)
(defun verilog-end-of-statement ()
"Move forward to end of current statement."
@@ -4713,7 +4953,7 @@ Uses `verilog-scan' cache."
pos)))))
(defun verilog-in-case-region-p ()
- "Return true if in a case region.
+ "Return non-nil if in a case region.
More specifically, point @ in the line foo : @ begin"
(interactive)
(save-excursion
@@ -4758,37 +4998,29 @@ More specifically, point @ in the line foo : @ begin"
(forward-sexp arg)))
(defun verilog-in-generate-region-p ()
- "Return true if in a generate region.
+ "Return non-nil if in a generate region.
More specifically, after a generate and before an endgenerate."
(interactive)
- (let ((nest 1))
- (save-excursion
- (catch 'done
- (while (and
- (/= nest 0)
- (verilog-re-search-backward
- "\\<\\(module\\)\\|\\(connectmodule\\)\\|\\(generate\\)\\|\\(endgenerate\\)\\|\\(if\\)\\|\\(case\\)\\|\\(for\\)\\>" nil 'move)
- (cond
- ((match-end 1) ; module - we have crawled out
- (throw 'done 1))
- ((match-end 2) ; connectmodule - we have crawled out
- (throw 'done 1))
- ((match-end 3) ; generate
- (setq nest (1- nest)))
- ((match-end 4) ; endgenerate
- (setq nest (1+ nest)))
- ((match-end 5) ; if
- (setq nest (1- nest)))
- ((match-end 6) ; case
- (setq nest (1- nest)))
- ((match-end 7) ; for
- (setq nest (1- nest))))))))
- (= nest 0) )) ; return nest
+ (let ((pos (point))
+ gen-beg-point gen-end-point)
+ (save-match-data
+ (save-excursion
+ (and (verilog-re-search-backward "\\<\\(generate\\)\\>" nil t)
+ (forward-word)
+ (setq gen-beg-point (point))
+ (verilog-forward-sexp)
+ (backward-word)
+ (setq gen-end-point (point)))))
+ (if (and gen-beg-point gen-end-point
+ (>= pos gen-beg-point)
+ (<= pos gen-end-point))
+ t
+ nil)))
(defun verilog-in-fork-region-p ()
- "Return true if between a fork and join."
+ "Return non-nil if between a fork and join."
(interactive)
- (let ((lim (save-excursion (verilog-beg-of-defun) (point)))
+ (let ((lim (save-excursion (verilog-re-search-backward verilog-defun-re nil 'move) (point)))
(nest 1))
(save-excursion
(while (and
@@ -4802,7 +5034,7 @@ More specifically, after a generate and before an endgenerate."
(= nest 0) )) ; return nest
(defun verilog-in-deferred-immediate-final-p ()
- "Return true if inside an `assert/assume/cover final' statement."
+ "Return non-nil if inside an `assert/assume/cover final' statement."
(interactive)
(and (looking-at "final")
(verilog-looking-back "\\<\\(?:assert\\|assume\\|cover\\)\\>\\s-+" nil))
@@ -5013,7 +5245,7 @@ primitive or interface named NAME."
(insert str)
(ding 't))
(let ((lim
- (save-excursion (verilog-beg-of-defun) (point)))
+ (save-excursion (verilog-re-search-backward verilog-defun-re nil 'move) (point)))
(here (point)))
(cond
(;-- handle named block differently
@@ -5461,7 +5693,7 @@ For example:
becomes:
// surefire lint_line_off UDDONX"
(interactive)
- (let ((buff (if (boundp 'next-error-last-buffer) ;Added to Emacs-22.1
+ (let ((buff (if (boundp 'next-error-last-buffer) ; Added to Emacs-22.1
next-error-last-buffer
(verilog--suppressed-warnings
((obsolete compilation-last-buffer))
@@ -5585,13 +5817,14 @@ FILENAME to find directory to run in, or defaults to `buffer-file-name'."
(defun verilog-warn-error (string &rest args)
"Call `error' using STRING and optional ARGS.
If `verilog-warn-fatal' is non-nil, call `verilog-warn' instead."
- (apply (if verilog-warn-fatal #'error #'verilog-warn)
+ (apply (if (and verilog-warn-fatal verilog-warn-fatal-internal)
+ #'error #'verilog-warn)
string args))
(defmacro verilog-batch-error-wrapper (&rest body)
"Execute BODY and add error prefix to any errors found.
This lets programs calling batch mode to easily extract error messages."
- `(let ((verilog-warn-fatal nil))
+ `(let ((verilog-warn-fatal-internal nil))
(condition-case err
(progn ,@body)
(error
@@ -5721,7 +5954,7 @@ This sets up the appropriate Verilog mode environment, calls
(string . 0)))
(defun verilog-continued-line-1 (lim)
- "Return true if this is a continued line.
+ "Return non-nil if this is a continued line.
Set point to where line starts. Limit search to point LIM."
(let ((continued 't))
(if (eq 0 (forward-line -1))
@@ -5774,7 +6007,6 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
;; if we are in a parenthesized list, and the user likes to indent these, return.
;; unless we are in the newfangled coverpoint or constraint blocks
(if (and
- verilog-indent-lists
(verilog-in-paren)
(not (verilog-in-coverage-p))
)
@@ -5791,7 +6023,7 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(looking-at verilog-in-constraint-re) )) ; may still get hosed if concat in constraint
(let ((sp (point)))
(if (and
- (not (looking-at verilog-complete-reg))
+ (not (looking-at verilog-complete-re))
(verilog-continued-line-1 lim))
(progn (goto-char sp)
(throw 'nesting 'cexp))
@@ -5996,6 +6228,12 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
(goto-char here) ; or is clocking, starts a new block
(throw 'nesting 'block)))))
+ ;; if find `ifn?def `else `elsif
+ ((or (match-end 20)
+ (match-end 21)
+ (match-end 22))
+ (throw 'continue 'foo))
+
((looking-at "\\<class\\|struct\\|function\\|task\\>")
;; *sigh* These words have an optional prefix:
;; extern {virtual|protected}? function a();
@@ -6025,7 +6263,7 @@ Return a list of two elements: (INDENT-TYPE INDENT-LEVEL)."
;; {assert|assume|cover} property (); are complete
;; and could also be labeled: - foo: assert property
;; but
- ;; property ID () ... needs end_property
+ ;; property ID () ... needs endproperty
(verilog-beg-of-statement)
(if (looking-at verilog-property-re)
(throw 'continue 'statement) ; We don't need an endproperty for these
@@ -6110,6 +6348,23 @@ of the appropriate enclosing block."
(ding 't)
(setq nest 0))))))
+(defun verilog-leap-to-class-head ()
+ (let ((nest 1)
+ (class-re (concat "\\(\\<class\\>\\)\\|\\(\\<endclass\\>\\)")))
+ (catch 'skip
+ (while (verilog-re-search-backward class-re nil 'move)
+ (cond
+ ((match-end 1) ; begin
+ (when (verilog-looking-back "\\(\\<interface\\>\\s-+\\)\\|\\(\\<virtual\\>\\s-+\\)" (point-at-bol))
+ (goto-char (match-beginning 0)))
+ (unless (verilog-looking-back "\\<typedef\\>\\s-+" (point-at-bol))
+ (setq nest (1- nest))
+ (if (= 0 nest)
+ ;; Now previous line describes syntax
+ (throw 'skip 1))))
+ ((match-end 2) ; end
+ (setq nest (1+ nest))))))))
+
(defun verilog-leap-to-head ()
"Move point to the head of this block.
Jump from end to matching begin, from endcase to matching case, and so on."
@@ -6137,7 +6392,9 @@ Jump from end to matching begin, from endcase to matching case, and so on."
(setq reg "\\(\\<fork\\>\\)\\|\\(\\<join\\(_any\\|_none\\)?\\>\\)" ))
((looking-at "\\<endclass\\>")
;; 5: Search back for matching class
- (setq reg "\\(\\<class\\>\\)\\|\\(\\<endclass\\>\\)" ))
+ (catch 'nesting
+ (verilog-leap-to-class-head)
+ (setq reg nil)))
((looking-at "\\<endtable\\>")
;; 6: Search back for matching table
(setq reg "\\(\\<table\\>\\)\\|\\(\\<endtable\\>\\)" ))
@@ -6175,7 +6432,19 @@ Jump from end to matching begin, from endcase to matching case, and so on."
(setq reg "\\(\\<\\(rand\\)?sequence\\>\\)\\|\\(\\<endsequence\\>\\)" ))
((looking-at "\\<endclocking\\>")
;; 12: Search back for matching clocking
- (setq reg "\\(\\<clocking\\)\\|\\(\\<endclocking\\>\\)" )))
+ (setq reg "\\(\\<clocking\\)\\|\\(\\<endclocking\\>\\)" ))
+ ;; Search back for matching package
+ ((looking-at "\\<endpackage\\>")
+ (setq reg "\\(\\<package\\>\\)" ))
+ ;; Search back for matching program
+ ((looking-at "\\<endprogram\\>")
+ (setq reg "\\(\\<program\\>\\)" ))
+ ((looking-at "\\<`endif\\>")
+ ;; Search back for matching `endif `else `elsif
+ (setq reg "\\(\\<`ifn?def\\>\\)\\|\\(\\<`endif\\>\\)" ))
+ ((looking-at "\\<`else\\>")
+ ;; Search back for matching `else `else `elsif
+ (setq reg "\\(\\<`ifn?def\\>\\|\\<`elsif\\>\\)\\|\\(\\<`else\\>\\)" )))
(if reg
(catch 'skip
(if (eq nesting 'yes)
@@ -6221,7 +6490,7 @@ Jump from end to matching begin, from endcase to matching case, and so on."
(throw 'skip 1)))))))
(defun verilog-continued-line ()
- "Return true if this is a continued line.
+ "Return non-nil if this is a continued line.
Set point to where line starts."
(let ((continued 't))
(if (eq 0 (forward-line -1))
@@ -6394,10 +6663,10 @@ Optional BOUND limits search."
(let ((state (save-excursion (verilog-syntax-ppss))))
(cond
((nth 7 state) ; in // comment
- (verilog-re-search-backward "//" nil 'move)
+ (re-search-backward "//" nil 'move)
(skip-chars-backward "/"))
((nth 4 state) ; in /* */ comment
- (verilog-re-search-backward "/\\*" nil 'move))))
+ (re-search-backward "/\\*" nil 'move))))
(narrow-to-region bound (point))
(while (/= here (point))
(setq here (point))
@@ -6450,13 +6719,60 @@ Optional BOUND limits search."
(if jump
(beginning-of-line 2))))))))
+(defun verilog-pos-at-beg-of-statement ()
+ "Return point position at the beginning of current statement."
+ (save-excursion
+ (verilog-beg-of-statement)
+ (point)))
+
+(defun verilog-col-at-beg-of-statement ()
+ "Return current column at the beginning of current statement."
+ (save-excursion
+ (verilog-beg-of-statement)
+ (current-column)))
+
+(defun verilog-pos-at-end-of-statement ()
+ "Return point position at the end of current statement."
+ (save-excursion
+ (verilog-end-of-statement)))
+
+(defun verilog-col-at-end-of-statement ()
+ "Return current column at the end of current statement."
+ (save-excursion
+ (verilog-end-of-statement)
+ (current-column)))
+
+(defun verilog-pos-at-forward-syntactic-ws ()
+ "Return point position at next non whitespace/comment token."
+ (save-excursion
+ (verilog-forward-syntactic-ws)
+ (point)))
+
+(defun verilog-col-at-forward-syntactic-ws ()
+ "Return current column at next non whitespace/comment token."
+ (save-excursion
+ (verilog-forward-syntactic-ws)
+ (current-column)))
+
+(defun verilog-pos-at-backward-syntactic-ws ()
+ "Return point position at previous non whitespace/comment token."
+ (save-excursion
+ (verilog-backward-syntactic-ws)
+ (point)))
+
+(defun verilog-col-at-backward-syntactic-ws ()
+ "Return current column at previous non whitespace/comment token."
+ (save-excursion
+ (verilog-backward-syntactic-ws)
+ (current-column)))
+
(defun verilog-in-comment-p ()
- "Return true if in a star or // comment."
+ "Return non-nil if in a star or // comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(or (nth 4 state) (nth 7 state))))
(defun verilog-in-star-comment-p ()
- "Return true if in a star comment."
+ "Return non-nil if in a star comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(and
(nth 4 state) ; t if in a comment of style a // or b /**/
@@ -6465,40 +6781,39 @@ Optional BOUND limits search."
))))
(defun verilog-in-slash-comment-p ()
- "Return true if in a slash comment."
+ "Return non-nil if in a slash comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(nth 7 state)))
(defun verilog-in-comment-or-string-p ()
- "Return true if in a string or comment."
+ "Return non-nil if in a string or comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(or (nth 3 state) (nth 4 state) (nth 7 state)))) ; Inside string or comment)
(defun verilog-in-attribute-p ()
- "Return true if point is in an attribute (* [] attribute *)."
- (save-match-data
- (save-excursion
- (verilog-re-search-backward "\\((\\*\\)\\|\\(\\*)\\)" nil 'move)
- (cond
- ((match-end 1)
- (progn (goto-char (match-end 1))
- (not (looking-at "\\s-*)")))
- nil)
- ((match-end 2)
- (progn (goto-char (match-beginning 2))
- (not (looking-at "(\\s-*")))
- nil)
- (t nil)))))
+ "Return non-nil if point is in an attribute (* [] attribute *)."
+ (let ((pos (point)))
+ (save-match-data
+ (save-excursion
+ (and (verilog-re-search-backward "(\\*" nil 'move)
+ (progn (forward-sexp)
+ (skip-chars-backward "*)"))
+ (< pos (point)))))))
(defun verilog-in-parameter-p ()
- "Return true if point is in a parameter assignment #( p1=1, p2=5)."
+ "Return non-nil if point is in a parameter assignment #( p1=1, p2=5)."
(save-match-data
(save-excursion
- (verilog-re-search-backward "\\(#(\\)\\|\\()\\)" nil 'move)
- (numberp (match-beginning 1)))))
+ (and (progn
+ (verilog-backward-up-list 1)
+ (verilog-backward-syntactic-ws)
+ (= (preceding-char) ?\#))
+ (progn
+ (verilog-beg-of-statement-1)
+ (looking-at verilog-defun-re))))))
(defun verilog-in-escaped-name-p ()
- "Return true if in an escaped name."
+ "Return non-nil if in an escaped name."
(save-excursion
(backward-char)
(skip-chars-backward "^ \t\n\f")
@@ -6507,20 +6822,20 @@ Optional BOUND limits search."
nil)))
(defun verilog-in-directive-p ()
- "Return true if in a directive."
+ "Return non-nil if in a directive."
(save-excursion
(beginning-of-line)
(looking-at verilog-directive-re-1)))
(defun verilog-in-parenthesis-p ()
- "Return true if in a ( ) expression (but not { } or [ ])."
+ "Return non-nil if in a ( ) expression (but not { } or [ ])."
(save-match-data
(save-excursion
(verilog-re-search-backward "\\((\\)\\|\\()\\)" nil 'move)
(numberp (match-beginning 1)))))
(defun verilog-in-paren ()
- "Return true if in a parenthetical expression.
+ "Return non-nil if in a parenthetical expression.
May cache result using `verilog-syntax-ppss'."
(let ((state (save-excursion (verilog-syntax-ppss))))
(> (nth 0 state) 0 )))
@@ -6534,7 +6849,7 @@ May cache result using `verilog-syntax-ppss'."
0 )))
(defun verilog-in-paren-quick ()
- "Return true if in a parenthetical expression.
+ "Return non-nil if in a parenthetical expression.
Always starts from `point-min', to allow inserts with hooks disabled."
;; The -quick refers to its use alongside the other -quick functions,
;; not that it's likely to be faster than verilog-in-paren.
@@ -6542,7 +6857,7 @@ Always starts from `point-min', to allow inserts with hooks disabled."
(> (nth 0 state) 0 )))
(defun verilog-in-struct-p ()
- "Return true if in a struct declaration."
+ "Return non-nil if in a struct declaration."
(interactive)
(save-excursion
(if (verilog-in-paren)
@@ -6568,7 +6883,7 @@ Return >0 for nested struct."
nil))))
(defun verilog-in-coverage-p ()
- "Return true if in a constraint or coverpoint expression."
+ "Return non-nil if in a constraint or coverpoint expression."
(interactive)
(save-excursion
(if (verilog-in-paren)
@@ -6608,7 +6923,7 @@ Also move point to constraint."
(equal (char-before) ?\;)
(equal (char-before) ?\}))
;; skip what looks like bus repetition operator {#{
- (not (string-match "^{\\s-*[()0-9a-zA-Z_\\]*\\s-*{"
+ (not (string-match "^{\\s-*[][()0-9a-zA-Z_,:\\]*\\s-*{"
(buffer-substring p (point)))))))))
(progn
(let ( (pt (point)) (pass 0))
@@ -6625,7 +6940,7 @@ Also move point to constraint."
))
;; if first word token not keyword, it maybe the instance name
;; check next word token
- (if (looking-at "\\<\\w+\\>\\|\\s-*(\\s-*\\S-+")
+ (if (looking-at "\\<\\w+\\>\\|\\s-*[[(}]\\s-*\\S-+")
(progn (verilog-beg-of-statement)
(if (and
(not (string-match verilog-named-block-re (buffer-substring pt (point)))) ;; Abort if 'begin' keyword is found
@@ -6674,13 +6989,39 @@ Also move point to constraint."
(verilog-in-struct-p)
(looking-at "}\\(?:\\s-*\\w+\\s-*\\(?:,\\s-*\\w+\\s-*\\)*\\)?;")))
+(defun verilog-at-struct-decl-p ()
+ "Return non-nil if at a struct declaration."
+ (interactive)
+ (save-excursion
+ (verilog-re-search-forward "{" (point-at-eol) t)
+ (unless (bobp)
+ (backward-char))
+ (verilog-at-struct-p)))
+
+(defun verilog-at-enum-p ()
+ "If at the { of a enum, return true, not moving point."
+ (save-excursion
+ (when (equal (char-after) ?\{)
+ (verilog-beg-of-statement)
+ (beginning-of-line)
+ (when (verilog-re-search-forward verilog-typedef-enum-re (verilog-pos-at-end-of-statement) t)
+ t))))
+
+(defun verilog-at-enum-decl-p ()
+ "Return non-nil if at a enum declaration."
+ (interactive)
+ (save-excursion
+ (verilog-re-search-forward "{" (verilog-pos-at-end-of-statement) t)
+ (unless (bobp)
+ (backward-char))
+ (verilog-at-enum-p)))
+
(defun verilog-parenthesis-depth ()
"Return non zero if in parenthetical-expression."
(save-excursion (nth 1 (verilog-syntax-ppss))))
-
(defun verilog-skip-forward-comment-or-string ()
- "Return true if in a string or comment."
+ "Return non-nil if in a string or comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(cond
((nth 3 state) ;Inside string
@@ -6695,7 +7036,7 @@ Also move point to constraint."
nil))))
(defun verilog-skip-backward-comment-or-string ()
- "Return true if in a string or comment."
+ "Return non-nil if in a string or comment."
(let ((state (save-excursion (verilog-syntax-ppss))))
(cond
((nth 3 state) ;Inside string
@@ -6712,7 +7053,7 @@ Also move point to constraint."
nil))))
(defun verilog-skip-backward-comments ()
- "Return true if a comment was skipped."
+ "Return non-nil if a comment was skipped."
(let ((more t))
(while more
(setq more
@@ -6831,6 +7172,9 @@ Only look at a few lines to determine indent level."
(let ((type (car indent-str))
(ind (car (cdr indent-str))))
(cond
+ (; handle indentation ignoring
+ (verilog-indent-ignore-p)
+ nil)
(; handle continued exp
(eq type 'cexp)
(let ((here (point)))
@@ -6840,14 +7184,14 @@ Only look at a few lines to determine indent level."
(= (preceding-char) ?\,)
(save-excursion
(verilog-beg-of-statement-1)
- (looking-at verilog-declaration-re)))
+ (verilog-looking-at-decl-to-align)))
(let* ( fst
(val
(save-excursion
(backward-char 1)
(verilog-beg-of-statement-1)
(setq fst (point))
- (if (looking-at verilog-declaration-re)
+ (if (looking-at (verilog-get-declaration-re))
(progn ; we have multiple words
(goto-char (match-end 0))
(skip-chars-forward " \t")
@@ -6869,9 +7213,9 @@ Only look at a few lines to determine indent level."
(+ (current-column) verilog-cexp-indent))))))
(goto-char here)
(indent-line-to val)
- (if (and (not verilog-indent-lists)
- (verilog-in-paren))
- (verilog-pretty-declarations-auto))
+ (when (and (not verilog-indent-lists)
+ (verilog-in-paren))
+ (verilog-pretty-declarations-auto))
))
((= (preceding-char) ?\) )
(goto-char here)
@@ -6897,21 +7241,17 @@ Only look at a few lines to determine indent level."
(; handle inside parenthetical expressions
(eq type 'cparenexp)
- (let* ( here
- (val (save-excursion
- (verilog-backward-up-list 1)
- (forward-char 1)
- (if verilog-indent-lists
- (skip-chars-forward " \t")
- (verilog-forward-syntactic-ws))
+ (let* ((val (verilog-cparenexp-indent-level))
+ (here (save-excursion
+ (verilog-backward-up-list 1)
+ (forward-char 1)
+ (skip-chars-forward " \t")
+ (point)))
+ (decl (save-excursion
+ (goto-char here)
+ (verilog-forward-syntactic-ws)
(setq here (point))
- (current-column)))
-
- (decl (save-excursion
- (goto-char here)
- (verilog-forward-syntactic-ws)
- (setq here (point))
- (looking-at verilog-declaration-re))))
+ (looking-at (verilog-get-declaration-re)))))
(indent-line-to val)
(if decl
(verilog-pretty-declarations-auto))))
@@ -6938,17 +7278,20 @@ Only look at a few lines to determine indent level."
(;-- defun
(and (eq type 'defun)
- (looking-at verilog-zero-indent-re))
+ (or (and verilog-indent-class-inside-pkg
+ (looking-at verilog-zero-indent-no-class-re))
+ (and (not verilog-indent-class-inside-pkg)
+ (looking-at verilog-zero-indent-re))))
(indent-line-to 0))
(;-- declaration
(and (or
(eq type 'defun)
(eq type 'block))
- (looking-at verilog-declaration-re)
+ (verilog-looking-at-decl-to-align)
;; Do not consider "virtual function", "virtual task", "virtual class"
;; as declarations
- (not (looking-at (concat verilog-declaration-re
+ (not (looking-at (concat (verilog-get-declaration-re)
"\\s-+\\(function\\|task\\|class\\)\\b"))))
(verilog-indent-declaration ind))
@@ -6994,6 +7337,81 @@ Do not count named blocks or case-statements."
(t
(current-column)))))
+(defun verilog-cparenexp-indent-level ()
+ "Return indent level for current line inside a parenthetical expression."
+ (let ((start-pos (point))
+ (close-par (looking-at "[)}]"))
+ pos pos-arg-paren)
+ (save-excursion
+ (verilog-backward-up-list 1)
+ (if verilog-indent-lists
+ (progn
+ (forward-char 1)
+ (skip-chars-forward " \t")
+ (current-column))
+ ;; Indentation with `verilog-indent-lists' set to nil
+ (verilog-beg-of-statement-1)
+ (when (looking-at "\\<\\(function\\|task\\)\\>")
+ (verilog-beg-of-statement)) ; find virtual/protected/static
+ (cond (;; 1) Closing ); of a module/function/task
+ (and close-par
+ (save-excursion
+ (verilog-beg-of-statement-1)
+ (or (looking-at verilog-complete-re)
+ (progn (beginning-of-line)
+ (not (looking-at verilog-assignment-operation-re))))))
+ (current-column))
+ (;; 2) if (condition)
+ (looking-at "(")
+ (forward-char 1)
+ (skip-chars-forward " \t\f" (point-at-eol))
+ (current-column))
+ (;; 3) Inside a module/defun param list or function/task argument list
+ (or (looking-at verilog-defun-level-re)
+ (looking-at "\\(\\<\\(virtual\\|protected\\|static\\)\\>\\s-+\\)?\\(\\<task\\>\\|\\<function\\>\\)"))
+ (setq pos-arg-paren (save-excursion
+ (goto-char start-pos)
+ (verilog-backward-up-list 1)
+ (forward-char)
+ (skip-chars-forward " \t")
+ (when (not (eolp))
+ (current-column))))
+ (or pos-arg-paren
+ ;; arg in next line after (
+ (+ (current-column) verilog-indent-level)))
+ (;; 4) Assignment operation
+ (save-excursion
+ (beginning-of-line)
+ (and (looking-at verilog-assignment-operation-re)
+ (save-excursion
+ (goto-char (match-beginning 2))
+ (not (verilog-within-string)))
+ (progn (verilog-forward-syntactic-ws)
+ (not (looking-at verilog-complete-re)))))
+ (goto-char (match-end 2))
+ (skip-chars-forward " \t\f" (point-at-eol))
+ (skip-chars-forward "{(" (1+ (point)))
+ (skip-chars-forward " \t\f" (point-at-eol))
+ (current-column))
+ (;; 5) Typedef enum declaration
+ (verilog-at-enum-decl-p)
+ (verilog-re-search-forward "{" (verilog-pos-at-end-of-statement) t)
+ (if (> (verilog-pos-at-forward-syntactic-ws) (point-at-eol))
+ (+ (verilog-col-at-beg-of-statement) verilog-indent-level)
+ (verilog-col-at-forward-syntactic-ws)))
+ (;; 6) Long reporting strings (e.g. $display or $sformatf inside `uvm_info)
+ (save-excursion
+ (goto-char start-pos)
+ (verilog-backward-up-list 1)
+ (setq pos (1+ (point)))
+ (backward-word)
+ (or (looking-at (concat "\\$" verilog-identifier-re)) ; System function/task
+ (looking-at verilog-uvm-statement-re))) ; `uvm_* macros
+ (goto-char pos)
+ (current-column))
+ (t ;; 7) Default
+ (+ (current-column) verilog-indent-level)))))))
+
(defun verilog-indent-comment ()
"Indent current line as comment."
(let* ((stcol
@@ -7053,90 +7471,137 @@ _ARG is ignored, for `comment-indent-function' compatibility."
;;
+(defun verilog-align-comments (startpos endpos)
+ "Align inline comments between STARTPOS and ENDPOS."
+ (let (comm-ind e)
+ (when verilog-align-decl-expr-comments
+ (setq comm-ind (verilog-get-comment-align-indent (marker-position startpos) endpos))
+ (save-excursion
+ (goto-char (marker-position startpos))
+ (while (progn (setq e (marker-position endpos))
+ (< (point) e))
+ (when (verilog-search-comment-in-declaration e)
+ (goto-char (match-beginning 0))
+ (delete-horizontal-space)
+ (indent-to (1- (+ comm-ind verilog-align-comment-distance)))))))))
+
(defun verilog-pretty-declarations-auto (&optional quiet)
"Call `verilog-pretty-declarations' QUIET based on `verilog-auto-lineup'."
(when (or (eq 'all verilog-auto-lineup)
(eq 'declarations verilog-auto-lineup))
(verilog-pretty-declarations quiet)))
+(defun verilog--pretty-declarations-find-end (&optional reg-end)
+ "Find end position for current alignment of declarations.
+If region is active, use arg REG-END to set a limit on the alignment."
+ (let (e)
+ (if (and (verilog-parenthesis-depth)
+ (not (verilog-in-struct-p)))
+ ;; In an argument list or parameter block
+ (progn
+ (verilog-backward-up-list -1)
+ (forward-char -1)
+ (verilog-backward-syntactic-ws)
+ (if (region-active-p)
+ (min reg-end (point))
+ (point)))
+ ;; In a declaration block (not in argument list)
+ (verilog-end-of-statement)
+ (setq e (point)) ; Might be on last line
+ (verilog-forward-syntactic-ws)
+ (while (verilog-looking-at-decl-to-align)
+ (verilog-end-of-statement)
+ (setq e (point))
+ (verilog-forward-syntactic-ws))
+ (if (region-active-p)
+ (min reg-end e)
+ e))))
+
+(defun verilog--pretty-declarations-find-base-ind ()
+ "Find base indentation for current alignment of declarations."
+ (if (and (verilog-parenthesis-depth)
+ (not (verilog-in-struct-p)))
+ ;; In an argument list or parameter block
+ (progn
+ (unless (or (verilog-looking-back "(" (point-at-bol))
+ (bolp))
+ (forward-char 1))
+ (skip-chars-forward " \t")
+ (current-column))
+ ;; In a declaration block (not in argument list)
+ (progn
+ (verilog-do-indent (verilog-calculate-indent))
+ (verilog-forward-ws&directives)
+ (current-column))))
+
(defun verilog-pretty-declarations (&optional quiet)
"Line up declarations around point.
Be verbose about progress unless optional QUIET set."
(interactive)
- (let* ((m1 (make-marker))
- (e (point))
- el
- r
- (here (point))
- ind
- start
- startpos
- end
- endpos
- base-ind
- )
+ (let ((m1 (make-marker))
+ (e (point))
+ (here (point))
+ el r ind start startpos end endpos base-ind rstart rend)
(save-excursion
+ (when (region-active-p)
+ (setq rstart (region-beginning))
+ (setq rend (region-end))
+ (goto-char rstart)) ; Shrinks the region but ensures that start is a valid declaration
(if (progn
- ;; (verilog-beg-of-statement-1)
+ ;; Check if alignment can be performed
(beginning-of-line)
(verilog-forward-syntactic-ws)
- (and (not (verilog-in-directive-p)) ; could have `define input foo
- (looking-at verilog-declaration-re)))
- (progn
- (if (verilog-parenthesis-depth)
- ;; in an argument list or parameter block
- (setq el (verilog-backward-up-list -1)
- start (progn
- (goto-char e)
- (verilog-backward-up-list 1)
- (forward-line) ; ignore ( input foo,
- (verilog-re-search-forward verilog-declaration-re el 'move)
- (goto-char (match-beginning 0))
+ (or (and (not (verilog-in-directive-p)) ; could have `define input foo
+ (verilog-looking-at-decl-to-align))
+ (and (verilog-parenthesis-depth)
+ (looking-at verilog-interface-modport-re))))
+ ;; Find boundaries of alignment
+ (progn
+ (cond (;; Using region
+ (region-active-p)
+ (setq start rstart
+ startpos (set-marker (make-marker) start)
+ end (progn (goto-char start)
+ (verilog--pretty-declarations-find-end rend))
+ endpos (set-marker (make-marker) end)
+ base-ind (progn (goto-char start)
+ (verilog--pretty-declarations-find-base-ind))))
+ (;; In an argument list or parameter block
+ (and (verilog-parenthesis-depth)
+ (not (verilog-in-struct-p)))
+ (setq el (verilog-backward-up-list -1)
+ start (progn
+ (goto-char e)
+ (verilog-backward-up-list 1)
+ (verilog-re-search-forward (verilog-get-declaration-re 'iface-mp) el 'move)
+ (goto-char (match-beginning 0))
+ (skip-chars-backward " \t")
+ (point))
+ startpos (set-marker (make-marker) start)
+ end (progn (goto-char start)
+ (verilog--pretty-declarations-find-end))
+ endpos (set-marker (make-marker) end)
+ base-ind (progn (goto-char start)
+ (verilog--pretty-declarations-find-base-ind))))
+ (;; In a declaration block (not in argument list)
+ t
+ (setq
+ start (progn
+ (verilog-beg-of-statement-1)
+ (while (and (verilog-looking-at-decl-to-align)
+ (not (bobp)))
(skip-chars-backward " \t")
- (point))
- startpos (set-marker (make-marker) start)
- end (progn
- (goto-char start)
- (verilog-backward-up-list -1)
- (forward-char -1)
- (verilog-backward-syntactic-ws)
- (point))
- endpos (set-marker (make-marker) end)
- base-ind (progn
- (goto-char start)
- (forward-char 1)
- (skip-chars-forward " \t")
- (current-column)))
- ;; in a declaration block (not in argument list)
- (setq
- start (progn
- (verilog-beg-of-statement-1)
- (while (and (looking-at verilog-declaration-re)
- (not (bobp)))
- (skip-chars-backward " \t")
- (setq e (point))
- (beginning-of-line)
- (verilog-backward-syntactic-ws)
- (backward-char)
- (verilog-beg-of-statement-1))
- e)
- startpos (set-marker (make-marker) start)
- end (progn
- (goto-char here)
- (verilog-end-of-statement)
- (setq e (point)) ;Might be on last line
- (verilog-forward-syntactic-ws)
- (while (looking-at verilog-declaration-re)
- (verilog-end-of-statement)
- (setq e (point))
- (verilog-forward-syntactic-ws))
- e)
- endpos (set-marker (make-marker) end)
- base-ind (progn
- (goto-char start)
- (verilog-do-indent (verilog-calculate-indent))
- (verilog-forward-ws&directives)
- (current-column))))
+ (setq e (point))
+ (verilog-backward-syntactic-ws)
+ (backward-char)
+ (verilog-beg-of-statement-1))
+ e)
+ startpos (set-marker (make-marker) start)
+ end (progn (goto-char here)
+ (verilog--pretty-declarations-find-end))
+ endpos (set-marker (make-marker) end)
+ base-ind (progn (goto-char start)
+ (verilog--pretty-declarations-find-base-ind)))))
;; OK, start and end are set
(goto-char (marker-position startpos))
(if (and (not quiet)
@@ -7152,12 +7617,13 @@ Be verbose about progress unless optional QUIET set."
(indent-line-to base-ind)
(verilog-forward-ws&directives)
(if (< (point) e)
- (verilog-re-search-forward "[ \t\n\f]" e 'move)))
+ (verilog-re-search-forward "[ \t\n\f]" (marker-position endpos) 'move)))
(t
- (just-one-space)
- (verilog-re-search-forward "[ \t\n\f]" e 'move)))
- ;;(forward-line)
- )
+ (unless (verilog-looking-back "(" (point-at-bol))
+ (just-one-space))
+ (if (looking-at verilog-comment-start-regexp)
+ (verilog-forward-syntactic-ws)
+ (verilog-re-search-forward "[ \t\n\f]" e 'move)))))
;; Now find biggest prefix
(setq ind (verilog-get-lineup-indent (marker-position startpos) endpos))
;; Now indent each line.
@@ -7167,27 +7633,27 @@ Be verbose about progress unless optional QUIET set."
(> r 0))
(setq e (point))
(unless quiet (message "%d" r))
- ;; (verilog-do-indent (verilog-calculate-indent)))
(verilog-forward-ws&directives)
(cond
- ((or (and verilog-indent-declaration-macros
- (looking-at verilog-declaration-re-2-macro))
- (looking-at verilog-declaration-re-2-no-macro))
- (let ((p (match-end 0)))
- (set-marker m1 p)
- (if (verilog-re-search-forward "[[#`]" p 'move)
- (progn
- (forward-char -1)
- (just-one-space)
- (goto-char (marker-position m1))
+ ((looking-at (verilog-get-declaration-re 'iface-mp))
+ (unless (looking-at (verilog-get-declaration-re 'embedded-comments))
+ (let ((p (match-end 0)))
+ (set-marker m1 p)
+ (if (verilog-re-search-forward "[[#`]" p 'move)
+ (progn
+ (forward-char -1)
+ (just-one-space)
+ (goto-char (marker-position m1))
+ (delete-horizontal-space)
+ (indent-to ind 1))
+ (progn
(delete-horizontal-space)
- (indent-to ind 1))
- (progn
- (delete-horizontal-space)
- (indent-to ind 1)))))
+ (indent-to ind 1))))))
((verilog-continued-line-1 (marker-position startpos))
(goto-char e)
- (indent-line-to ind))
+ (unless (and (verilog-in-parenthesis-p)
+ (looking-at (concat "\\s-*" verilog-identifier-sym-re "\\s-+" verilog-identifier-sym-re "\\s-*")))
+ (indent-line-to ind)))
((verilog-in-struct-p)
;; could have a declaration of a user defined item
(goto-char e)
@@ -7197,104 +7663,202 @@ Be verbose about progress unless optional QUIET set."
(verilog-forward-ws&directives)
(forward-line -1)))
(forward-line 1))
- (unless quiet (message "")))))))
+ ;; Align comments if enabled
+ (when verilog-align-decl-expr-comments
+ (verilog-align-comments startpos endpos)))
+ ;; Exit
+ (unless quiet (message ""))))))
+
+(defun verilog--pretty-expr-assignment-found (&optional discard-re)
+ "Return non-nil if point is at a valid assignment operation to be aligned.
+Ensure cursor is not over DISCARD-RE (e.g. Verilog keywords).
+If returned non-nil, update match data according to `verilog-assignment-operation-re'."
+ ;; Not looking at a verilog keyword sentence (i.e looking at a potential assignment)
+ (and (if discard-re
+ (not (looking-at discard-re))
+ t)
+ ;; Corner case to filter first parameter on param lists
+ (save-excursion
+ (if (and (verilog-re-search-forward verilog-assignment-operation-re (point-at-eol) 'move)
+ (verilog-in-parenthesis-p))
+ (progn (verilog-backward-up-list 1)
+ (forward-char 1)
+ (not (eq 0 (string-match discard-re (buffer-substring-no-properties (point) (point-at-eol))))))
+ t))
+ ;; Don't work on multiline assignments unless they are continued lines
+ ;; e.g, multiple parameters or variable declarations in the same statement
+ (if (save-excursion
+ (and (not (verilog-in-parameter-p))
+ (verilog-continued-line)
+ (not (looking-at verilog-basic-complete-re))))
+ (save-excursion
+ (verilog-beg-of-statement-1)
+ (looking-at (verilog-get-declaration-re)))
+ t)
+ ;; Ensure it's not any kind of logical comparison
+ (save-excursion
+ (unless (and (not (verilog-in-parameter-p))
+ (verilog-re-search-forward (verilog-regexp-words '("if" "for" "assert" "with")) (point-at-eol) 'move))
+ t))
+ ;; Looking at an assignment (last check, provides match data)
+ (looking-at verilog-assignment-operation-re)))
+
+(defun verilog--pretty-expr-find-end (&optional discard-re reg-end)
+ "Find end position for current alignment of expressions.
+Use optional arg DISCARD-RE when aligning expressions outside of an
+argument list and REG-END to set a limit on the alignment when the
+region is active."
+ (if (verilog-in-parenthesis-p)
+ ;; Limit end in argument list
+ (progn
+ (verilog-backward-up-list -1)
+ (forward-char -1)
+ (verilog-backward-syntactic-ws)
+ (if (region-active-p)
+ (min reg-end (point))
+ (point)))
+ ;; Limit end in non-argument list
+ (save-excursion ; EOL of the last line of the assignment block
+ (end-of-line)
+ (let ((pt (point))) ; Might be on last line
+ (verilog-forward-syntactic-ws)
+ (beginning-of-line)
+ (while (and (verilog--pretty-expr-assignment-found discard-re)
+ (progn
+ (end-of-line)
+ (not (eq pt (point)))))
+ (setq pt (point))
+ (verilog-forward-syntactic-ws)
+ (beginning-of-line))
+ (if (region-active-p)
+ (min reg-end pt)
+ pt)))))
(defun verilog-pretty-expr (&optional quiet)
"Line up expressions around point.
If QUIET is non-nil, do not print messages showing the progress of line-up."
(interactive)
- (unless (verilog-in-comment-or-string-p)
+ (let* ((basic-complete-pretty-expr-re (if verilog-align-assign-expr
+ verilog-basic-complete-expr-no-assign-re
+ verilog-basic-complete-expr-re))
+ (complete-pretty-expr-re (concat verilog-extended-complete-re "\\|\\(" basic-complete-pretty-expr-re "\\)"))
+ (discard-re (concat "^\\s-*\\(" complete-pretty-expr-re "\\)"))
+ rstart rend)
(save-excursion
- (let ((regexp (concat "^\\s-*" verilog-complete-reg))
- (regexp1 (concat "^\\s-*" verilog-basic-complete-re)))
+ (when (region-active-p)
+ (setq rstart (region-beginning))
+ (setq rend (region-end))
+ (goto-char rstart))
+ (unless (verilog-in-comment-or-string-p)
(beginning-of-line)
- (when (and (not (looking-at regexp))
- (looking-at verilog-assignment-operation-re)
+ (when (and (verilog--pretty-expr-assignment-found discard-re)
(save-excursion
(goto-char (match-end 2))
(and (not (verilog-in-attribute-p))
- (not (verilog-in-parameter-p))
(not (verilog-in-comment-or-string-p)))))
- (let* ((start (save-excursion ; BOL of the first line of the assignment block
- (beginning-of-line)
- (let ((pt (point)))
- (verilog-backward-syntactic-ws)
- (beginning-of-line)
- (while (and (not (looking-at regexp1))
- (looking-at verilog-assignment-operation-re)
- (not (bobp)))
- (setq pt (point))
- (verilog-backward-syntactic-ws)
- (beginning-of-line)) ; Ack, need to grok `define
- pt)))
- (end (save-excursion ; EOL of the last line of the assignment block
- (end-of-line)
- (let ((pt (point))) ; Might be on last line
- (verilog-forward-syntactic-ws)
- (beginning-of-line)
- (while (and
- (not (looking-at regexp1))
- (looking-at verilog-assignment-operation-re)
- (progn
- (end-of-line)
- (not (eq pt (point)))))
- (setq pt (point))
- (verilog-forward-syntactic-ws)
- (beginning-of-line))
- pt)))
- (contains-2-char-operator (string-match "<=" (buffer-substring-no-properties start end)))
- (endmark (set-marker (make-marker) end)))
- (goto-char start)
- (verilog-do-indent (verilog-calculate-indent))
+ (let* ((start (cond (;; Using region
+ (region-active-p)
+ rstart)
+ (;; Parameter list
+ (verilog-in-parenthesis-p)
+ (progn
+ (verilog-backward-up-list 1)
+ (forward-char)
+ (verilog-re-search-forward verilog-assignment-operation-re-2 nil 'move)
+ (goto-char (match-beginning 0))
+ (point)))
+ (t ;; Declarations
+ (save-excursion ; BOL of the first line of the assignment block
+ (beginning-of-line)
+ (let ((pt (point)))
+ (verilog-backward-syntactic-ws)
+ (beginning-of-line)
+ (while (and (verilog--pretty-expr-assignment-found discard-re)
+ (not (bobp)))
+ (setq pt (point))
+ (verilog-backward-syntactic-ws)
+ (beginning-of-line)) ; Ack, need to grok `define
+ pt)))))
+ (startpos (set-marker (make-marker) start))
+ (end (cond (;; Using region
+ (region-active-p)
+ (verilog--pretty-expr-find-end discard-re rend))
+ (;; Parameter list
+ (verilog-in-parenthesis-p)
+ (verilog--pretty-expr-find-end))
+ (t ;; Declarations
+ (verilog--pretty-expr-find-end discard-re))))
+ (endpos (set-marker (make-marker) end))
+ (contains-2-char-operator (string-match "<=" (buffer-substring-no-properties start end))))
+ ;; Start with alignment
+ (goto-char startpos)
+ (unless (save-excursion
+ (beginning-of-line)
+ (looking-at discard-re))
+ (verilog-do-indent (verilog-calculate-indent)))
(when (and (not quiet)
- (> (- end start) 100))
+ (> (- (marker-position endpos) (marker-position startpos)) 100))
(message "Lining up expressions.. (please stand by)"))
-
;; Set indent to minimum throughout region
;; Rely on mark rather than on point as the indentation changes can
;; make the older point reference obsolete
- (while (< (point) (marker-position endmark))
+ (while (< (point) (marker-position endpos))
(beginning-of-line)
(save-excursion
- (verilog-just-one-space verilog-assignment-operation-re))
+ (if (looking-at verilog-complete-re)
+ (progn (goto-char (marker-position startpos))
+ (verilog-just-one-space verilog-assignment-operation-re-2))
+ (verilog-just-one-space verilog-assignment-operation-re)))
(verilog-do-indent (verilog-calculate-indent))
(end-of-line)
(verilog-forward-syntactic-ws))
- (let ((ind (verilog-get-lineup-indent-2 verilog-assignment-operation-re start (marker-position endmark))) ; Find the biggest prefix
+ (let ((ind (verilog-get-lineup-indent-2 verilog-assignment-operation-re (marker-position startpos) (marker-position endpos))) ; Find the biggest prefix
e)
;; Now indent each line.
- (goto-char start)
+ (goto-char (marker-position startpos))
(while (progn
- (setq e (marker-position endmark))
+ (setq e (marker-position endpos))
(> e (point)))
(unless quiet
(message " verilog-pretty-expr: %d" (- e (point))))
(setq e (point))
(cond
- ((looking-at verilog-assignment-operation-re)
+ ((or (looking-at verilog-assignment-operation-re)
+ (and (verilog-in-parenthesis-p)
+ (looking-at verilog-assignment-operation-re-2)))
(goto-char (match-beginning 2))
- (unless (or (verilog-in-parenthesis-p) ; Leave attributes and comparisons alone
+ (unless (or (and (verilog-in-parenthesis-p) ; Leave attributes and comparisons alone
+ (save-excursion ; Allow alignment of some expressions inside param/port list
+ (verilog-backward-up-list 1)
+ (verilog-beg-of-statement-1)
+ (not (looking-at verilog-defun-level-re))))
(verilog-in-coverage-p))
(if (and contains-2-char-operator
(eq (char-after) ?=))
(indent-to (1+ ind)) ; Line up the = of the <= with surrounding =
- (indent-to ind))))
- ((verilog-continued-line-1 start)
+ (indent-to ind)))
+ (forward-line 1))
+ ((and (save-excursion
+ (verilog-forward-syntactic-ws)
+ (not (looking-at verilog-complete-re)))
+ (verilog-continued-line-1 (marker-position startpos)))
(goto-char e)
- (indent-line-to ind))
- (t ; Must be comment or white space
+ (indent-line-to ind)
+ (forward-line 1))
+ (t ; Must be comment, white space or syntax error
(goto-char e)
- (verilog-forward-ws&directives)
- (forward-line -1)))
- (forward-line 1))
+ (forward-line 1))))
+ ;; Align comments if enabled
+ (when verilog-align-decl-expr-comments
+ (verilog-align-comments startpos endpos))
(unless quiet
(message "")))))))))
(defun verilog-just-one-space (myre)
"Remove extra spaces around regular expression MYRE."
(interactive)
- (if (and (not(looking-at verilog-complete-reg))
+ (if (and (not(looking-at verilog-complete-re))
(looking-at myre))
(let ((p1 (match-end 1))
(p2 (match-end 2)))
@@ -7312,59 +7876,63 @@ BASEIND is the base indent to offset everything."
;; `ind' is used in expressions stored in `verilog-indent-alist'.
(verilog--suppressed-warnings ((lexical ind)) (defvar ind))
(let ((pos (point-marker))
- (lim (save-excursion
- ;; (verilog-re-search-backward verilog-declaration-opener nil 'move)
- (verilog-re-search-backward "\\(\\<begin\\>\\)\\|\\(\\<\\(connect\\)?module\\>\\)\\|\\(\\<task\\>\\)" nil 'move)
- (point)))
- (ind)
- (val)
- (m1 (make-marker)))
- (setq val
- (+ baseind (eval (cdr (assoc 'declaration verilog-indent-alist)))))
+ (m1 (make-marker))
+ (in-paren (verilog-parenthesis-depth))
+ (val (+ baseind (eval (cdr (assoc 'declaration verilog-indent-alist)))))
+ ind)
(indent-line-to val)
-
;; Use previous declaration (in this module) as template.
- (if (or (eq 'all verilog-auto-lineup)
- (eq 'declarations verilog-auto-lineup))
- (if (verilog-re-search-backward
- (or (and verilog-indent-declaration-macros
- verilog-declaration-re-1-macro)
- verilog-declaration-re-1-no-macro)
- lim t)
- (progn
- (goto-char (match-end 0))
- (skip-chars-forward " \t")
- (setq ind (current-column))
- (goto-char pos)
- (setq val
- (+ baseind
- (eval (cdr (assoc 'declaration verilog-indent-alist)))))
- (indent-line-to val)
- (if (and verilog-indent-declaration-macros
- (looking-at verilog-declaration-re-2-macro))
- (let ((p (match-end 0)))
- (set-marker m1 p)
- (if (verilog-re-search-forward "[[#`]" p 'move)
- (progn
- (forward-char -1)
- (just-one-space)
- (goto-char (marker-position m1))
- (delete-horizontal-space)
- (indent-to ind 1))
- (delete-horizontal-space)
- (indent-to ind 1)))
- (if (looking-at verilog-declaration-re-2-no-macro)
- (let ((p (match-end 0)))
- (set-marker m1 p)
- (if (verilog-re-search-forward "[[`#]" p 'move)
- (progn
- (forward-char -1)
- (just-one-space)
- (goto-char (marker-position m1))
- (delete-horizontal-space)
- (indent-to ind 1))
- (delete-horizontal-space)
- (indent-to ind 1))))))))
+ (when (and (or (eq 'all verilog-auto-lineup)
+ (eq 'declarations verilog-auto-lineup))
+ ;; Limit alignment to consecutive statements
+ (progn
+ (verilog-backward-syntactic-ws)
+ (backward-char)
+ (looking-at ";"))
+ (progn
+ (verilog-beg-of-statement)
+ (looking-at (verilog-get-declaration-re)))
+ ;; Make sure that we don't jump to an argument list or parameter block if
+ ;; we were in a declaration block (not in argument list)
+ (or (and in-paren
+ (verilog-parenthesis-depth))
+ (and (not in-paren)
+ (not (verilog-parenthesis-depth))))
+ ;; Skip variable declarations inside functions/tasks
+ (skip-chars-backward " \t\f")
+ (bolp))
+ (goto-char (match-end 0))
+ (skip-chars-forward " \t")
+ (setq ind (current-column))
+ (goto-char pos)
+ (setq val
+ (+ baseind
+ (eval (cdr (assoc 'declaration verilog-indent-alist)))))
+ (indent-line-to val)
+ (if (looking-at (verilog-get-declaration-re))
+ (let ((p (match-end 0)))
+ (set-marker m1 p)
+ (if (verilog-re-search-forward "[[#`]" p 'move)
+ (progn
+ (forward-char -1)
+ (just-one-space)
+ (goto-char (marker-position m1))
+ (delete-horizontal-space)
+ (indent-to ind 1))
+ (delete-horizontal-space)
+ (indent-to ind 1)))
+ (when (looking-at (verilog-get-declaration-re))
+ (let ((p (match-end 0)))
+ (set-marker m1 p)
+ (if (verilog-re-search-forward "[[`#]" p 'move)
+ (progn
+ (forward-char -1)
+ (just-one-space)
+ (goto-char (marker-position m1))
+ (delete-horizontal-space)
+ (indent-to ind 1))
+ (delete-horizontal-space)
+ (indent-to ind 1))))))
(goto-char pos)))
(defun verilog-get-lineup-indent (b edpos)
@@ -7376,16 +7944,13 @@ Region is defined by B and EDPOS."
;; Get rightmost position
(while (progn (setq e (marker-position edpos))
(< (point) e))
- (if (verilog-re-search-forward
- (or (and verilog-indent-declaration-macros
- verilog-declaration-re-1-macro)
- verilog-declaration-re-1-no-macro) e 'move)
- (progn
- (goto-char (match-end 0))
- (verilog-backward-syntactic-ws)
- (if (> (current-column) ind)
- (setq ind (current-column)))
- (goto-char (match-end 0)))))
+ (when (verilog-re-search-forward (verilog-get-declaration-re 'iface-mp) e 'move)
+ (goto-char (match-end 0))
+ (verilog-backward-syntactic-ws)
+ (if (> (current-column) ind)
+ (setq ind (current-column)))
+ (goto-char (match-end 0))
+ (forward-line 1)))
(if (> ind 0)
(1+ ind)
;; No lineup-string found
@@ -7402,12 +7967,13 @@ BEG and END."
(save-excursion
(let ((ind 0))
(goto-char beg)
+ (beginning-of-line)
;; Get rightmost position
(while (< (point) end)
(when (and (verilog-re-search-forward regexp end 'move)
(not (verilog-in-attribute-p))) ; skip attribute exprs
(goto-char (match-beginning 2))
- (verilog-backward-syntactic-ws)
+ (skip-chars-backward " \t")
(if (> (current-column) ind)
(setq ind (current-column)))
(goto-char (match-end 0))))
@@ -7420,6 +7986,32 @@ BEG and END."
(1+ (current-column))))
ind)))
+(defun verilog-search-comment-in-declaration (bound)
+ "Move cursor to position of comment in declaration and return point.
+BOUND is a buffer position that bounds the search."
+ (and (verilog-re-search-forward (verilog-get-declaration-re 'iface-mp) bound 'move)
+ (not (looking-at (concat "\\s-*" verilog-comment-start-regexp)))
+ (re-search-forward verilog-comment-start-regexp (point-at-eol) :noerror)))
+
+(defun verilog-get-comment-align-indent (b endpos)
+ "Return the indent level that will line up comments within the region.
+Region is defined by B and ENDPOS."
+ (save-excursion
+ (let ((ind 0)
+ e comm-ind)
+ (goto-char b)
+ ;; Get rightmost position
+ (while (progn (setq e (marker-position endpos))
+ (< (point) e))
+ (when (verilog-search-comment-in-declaration e)
+ (end-of-line)
+ (verilog-backward-syntactic-ws)
+ (setq comm-ind (1+ (current-column)))
+ (when (> comm-ind ind)
+ (setq ind comm-ind)))
+ (forward-line 1))
+ ind)))
+
(defun verilog-comment-depth (type val)
"A useful mode debugging aide. TYPE and VAL are comments for insertion."
(save-excursion
@@ -7439,6 +8031,19 @@ BEG and END."
(insert
(format "%s %d" type val))))
+(defun verilog-indent-ignore-p ()
+ "Return non-nil if current line should ignore indentation."
+ (or (and verilog-indent-ignore-multiline-defines
+ ;; Line with multiline define, ends with "\" or "\" plus trailing whitespace
+ (or (looking-at ".*\\\\\\s-*$")
+ (save-excursion ; Last line after multiline define
+ (verilog-backward-syntactic-ws)
+ (unless (bobp)
+ (backward-char))
+ (looking-at "\\\\"))))
+ (and verilog-indent-ignore-regexp ; Ignore lines according to specified regexp
+ (looking-at verilog-indent-ignore-regexp))))
+
;;; Completion:
;;
@@ -7446,7 +8051,7 @@ BEG and END."
(defvar verilog-all nil)
(defvar verilog-buffer-to-use nil)
(defvar verilog-toggle-completions nil
- "True means \\<verilog-mode-map>\\[verilog-complete-word] should try all possible completions one by one.
+ "Non-nil means \\<verilog-mode-map>\\[verilog-complete-word] should try all possible completions one by one.
Repeated use of \\[verilog-complete-word] will show you all of them.
Normally, when there is more than one possible completion,
it displays a list of all possible completions.")
@@ -7598,16 +8203,14 @@ TYPE is `module', `tf' for task or function, or t if unknown."
(defun verilog-get-completion-decl (end)
"Macro for searching through current declaration (var, type or const)
for matches of `str' and adding the occurrence tp `all' through point END."
- (let ((re (or (and verilog-indent-declaration-macros
- verilog-declaration-re-2-macro)
- verilog-declaration-re-2-no-macro))
+ (let ((re (verilog-get-declaration-re))
decl-end match)
;; Traverse lines
(while (and (< (point) end)
(verilog-re-search-forward re end t))
;; Traverse current line
(setq decl-end (save-excursion (verilog-declaration-end)))
- (while (and (verilog-re-search-forward verilog-symbol-re decl-end t)
+ (while (and (verilog-re-search-forward verilog-identifier-sym-re decl-end t)
(not (match-end 1)))
(setq match (buffer-substring (match-beginning 0) (match-end 0)))
(if (string-match (concat "\\<" verilog-str) match)
@@ -7619,7 +8222,7 @@ for matches of `str' and adding the occurrence tp `all' through point END."
"Calculate all possible completions for variables (or constants)."
(let ((start (point)))
;; Search for all reachable var declarations
- (verilog-beg-of-defun)
+ (verilog-re-search-backward verilog-defun-re nil 'move)
(save-excursion
;; Check var declarations
(verilog-get-completion-decl start))))
@@ -8765,6 +9368,11 @@ Return an array of [outputs inouts inputs wire reg assign const gparam intf]."
(t ; Bit width
(setq vec (verilog-string-replace-matches
"\\s-+" "" nil nil keywd)))))
+ ;; int'(a) is cast, not declaration of a
+ ((and (looking-at "'")
+ (not rvalue))
+ (forward-char 1)
+ (setq expect-signal nil rvalue nil))
;; Normal or escaped identifier -- note we remember the \ if escaped
((looking-at "\\s-*\\([a-zA-Z0-9`_$]+\\|\\\\[^ \t\n\f]+\\)")
(goto-char (match-end 0))
@@ -9702,9 +10310,9 @@ resolve it. If optional RECURSE is non-nil, recurse through \\=`includes.
Localparams must be simple assignments to constants, or have their own
\"localparam\" label rather than a list of localparams. Thus:
- localparam X = 5, Y = 10; // Ok
- localparam X = {1\\='b1, 2\\='h2}; // Ok
- localparam X = {1\\='b1, 2\\='h2}, Y = 10; // Bad, make into 2 localparam lines
+ localparam X = 5, Y = 10; // Ok
+ localparam X = {1\\='b1, 2\\='h2}; // Ok
+ localparam X = {1\\='b1, 2\\='h2}, Y = 10; // Bad, make into 2 localparam lines
Defines must be simple text substitutions, one on a line, starting
at the beginning of the line. Any ifdefs or multiline comments around the
@@ -9827,8 +10435,7 @@ variable over and over when many modules are compiled together, put a test
around the inside each include file:
foo.v (an include file):
- \\=`ifdef _FOO_V // include if not already included
- \\=`else
+ \\=`ifndef _FOO_V // include if not already included
\\=`define _FOO_V
... contents of file
\\=`endif // _FOO_V"
@@ -10066,7 +10673,7 @@ Results are cached if inside `verilog-preserve-dir-cache'."
;; (prin1 (verilog-dir-files ".")) nil)
(defun verilog-dir-file-exists-p (filename)
- "Return true if FILENAME exists.
+ "Return non-nil if FILENAME exists.
Like `file-exists-p' but results are cached if inside
`verilog-preserve-dir-cache'."
(let* ((dirname (file-name-directory filename))
@@ -10105,7 +10712,7 @@ Allows version control to check out the file if need be."
modi)))))
(defun verilog-is-number (symbol)
- "Return true if SYMBOL is number-like."
+ "Return non-nil if SYMBOL is number-like."
(or (string-match "^[0-9 \t:]+$" symbol)
(string-match "^[---]*[0-9]+$" symbol)
(string-match "^[0-9 \t]+'s?[hdxbo][0-9a-fA-F_xz? \t]*$" symbol)))
@@ -10177,7 +10784,7 @@ Or, just the existing dirnames themselves if there are no wildcards."
(unless dirnames
(error "`verilog-library-directories' should include at least `.'"))
(save-match-data
- (setq dirnames (reverse dirnames)) ; not nreverse
+ (setq dirnames (reverse dirnames)) ; not nreverse
(let ((dirlist nil)
pattern dirfile dirfiles dirname root filename rest basefile)
(setq dirnames (mapcar #'substitute-in-file-name dirnames))
@@ -10885,12 +11492,12 @@ This repairs those mis-inserted by an AUTOARG."
(if (equal (match-string 3 out) ">>")
(int-to-string (ash (string-to-number (match-string 2 out))
(* -1 (string-to-number (match-string 4 out))))))
- (if (equal (match-string 3 out) "<<")
- (int-to-string (ash (string-to-number (match-string 2 out))
- (string-to-number (match-string 4 out)))))
(if (equal (match-string 3 out) ">>>")
(int-to-string (ash (string-to-number (match-string 2 out))
(* -1 (string-to-number (match-string 4 out))))))
+ (if (equal (match-string 3 out) "<<")
+ (int-to-string (ash (string-to-number (match-string 2 out))
+ (string-to-number (match-string 4 out)))))
(if (equal (match-string 3 out) "<<<")
(int-to-string (ash (string-to-number (match-string 2 out))
(string-to-number (match-string 4 out)))))
@@ -10920,7 +11527,7 @@ This repairs those mis-inserted by an AUTOARG."
(ceiling (/ (log value) (log 2)))))
(defun verilog-typedef-name-p (variable-name)
- "Return true if the VARIABLE-NAME is a type definition."
+ "Return non-nil if the VARIABLE-NAME is a type definition."
(when verilog-typedef-regexp
(verilog-string-match-fold verilog-typedef-regexp variable-name)))
@@ -11678,7 +12285,7 @@ If PAR-VALUES replace final strings with these parameter values."
(concat "." vl-modport) "")
dflt-bits))
;; Find template
- (cond (tpl-ass ; Template of exact port name
+ (cond (tpl-ass ; Template of exact port name
(setq tpl-net (nth 1 tpl-ass)))
((nth 1 tpl-list) ; Wildcards in template, search them
(let ((wildcards (nth 1 tpl-list)))
@@ -12240,7 +12847,9 @@ For more information see the \\[verilog-faq] and forums at URL
(cond ((not verilog-auto-inst-first-any)
(re-search-backward "," pt t)
(delete-char 1)
- (insert ");")
+ (when (looking-at " ")
+ (delete-char 1)) ; so we can align // Templated comments
+ (insert ");")
(search-forward "\n") ; Added by inst-port
(delete-char -1)
(if (search-forward ")" nil t) ; From user, moved up a line
@@ -14645,7 +15254,7 @@ and the case items."
(if (not (member v1 verilog-keywords))
(save-excursion
(setq verilog-sk-signal v1)
- (verilog-beg-of-defun)
+ (verilog-re-search-backward verilog-defun-re nil 'move)
(verilog-end-of-statement)
(verilog-forward-syntactic-ws)
(verilog-sk-def-reg)
@@ -14897,7 +15506,12 @@ Files are checked based on `verilog-library-flags'."
'(
verilog-active-low-regexp
verilog-after-save-font-hook
+ verilog-align-assign-expr
+ verilog-align-comment-distance
+ verilog-align-decl-expr-comments
verilog-align-ifelse
+ verilog-align-typedef-regexp
+ verilog-align-typedef-words
verilog-assignment-delay
verilog-auto-arg-sort
verilog-auto-declare-nettype
@@ -14942,13 +15556,17 @@ Files are checked based on `verilog-library-flags'."
verilog-compiler
verilog-coverage
verilog-delete-auto-hook
+ verilog-fontify-variables
verilog-getopt-flags-hook
verilog-highlight-grouping-keywords
verilog-highlight-includes
verilog-highlight-modules
verilog-highlight-translate-off
verilog-indent-begin-after-if
+ verilog-indent-class-inside-pkg
verilog-indent-declaration-macros
+ verilog-indent-ignore-multiline-defines
+ verilog-indent-ignore-regexp
verilog-indent-level
verilog-indent-level-behavioral
verilog-indent-level-declaration
diff --git a/lisp/server.el b/lisp/server.el
index d963ee5b1e0..8bd622346e7 100644
--- a/lisp/server.el
+++ b/lisp/server.el
@@ -273,6 +273,11 @@ If nil, no instructions are displayed."
:version "28.1"
:type 'boolean)
+(defvar server-stop-automatically) ; Defined below to avoid recursive load.
+
+(defvar server-stop-automatically--timer nil
+ "The timer object for `server-stop-automatically--maybe-kill-emacs'.")
+
;; We do not use `temporary-file-directory' here, because emacsclient
;; does not read the init file.
(defvar server-socket-dir
@@ -636,7 +641,8 @@ anyway."
(setq stopped-p t
server-process nil
server-mode nil
- global-minor-modes (delq 'server-mode global-minor-modes)))
+ global-minor-modes (delq 'server-mode global-minor-modes))
+ (server-apply-stop-automatically))
(unwind-protect
;; Delete the socket files made by previous server
;; invocations.
@@ -757,6 +763,7 @@ the `server-process' variable."
(list :family 'local
:service server-file
:plist '(:authenticated t)))))
+ (server-apply-stop-automatically)
(unless server-process (error "Could not start server process"))
(server-log "Started server")
(process-put server-process :server-file server-file)
@@ -1769,9 +1776,6 @@ be a cons cell (LINENUMBER . COLUMNNUMBER)."
(when server-raise-frame
(select-frame-set-input-focus (window-frame)))))
-(defvar server-stop-automatically nil
- "Internal status variable for `server-stop-automatically'.")
-
;;;###autoload
(defun server-save-buffers-kill-terminal (arg)
;; Called from save-buffers-kill-terminal in files.el.
@@ -1779,11 +1783,19 @@ be a cons cell (LINENUMBER . COLUMNNUMBER)."
With ARG non-nil, silently save all file-visiting buffers, then kill.
If emacsclient was started with a list of filenames to edit, then
-only these files will be asked to be saved."
- (let ((proc (frame-parameter nil 'client)))
+only these files will be asked to be saved.
+
+When running Emacs as a daemon and with
+`server-stop-automatically' (which see) set to `kill-terminal' or
+`delete-frame', this function may call `save-buffers-kill-emacs'
+if there are no other active clients."
+ (let ((stop-automatically
+ (and (daemonp)
+ (memq server-stop-automatically '(kill-terminal delete-frame))))
+ (proc (frame-parameter nil 'client)))
(cond ((eq proc 'nowait)
;; Nowait frames have no client buffer list.
- (if (length> (frame-list) (if server-stop-automatically 2 1))
+ (if (length> (frame-list) (if stop-automatically 2 1))
;; If there are any other frames, only delete this one.
;; When `server-stop-automatically' is set, don't count
;; the daemon frame.
@@ -1792,7 +1804,7 @@ only these files will be asked to be saved."
;; If we're the last frame standing, kill Emacs.
(save-buffers-kill-emacs arg)))
((processp proc)
- (if (or (not server-stop-automatically)
+ (if (or (not stop-automatically)
(length> server-clients 1)
(seq-some
(lambda (frame)
@@ -1818,31 +1830,14 @@ only these files will be asked to be saved."
(save-buffers-kill-emacs arg)))
(t (error "Invalid client frame")))))
-(defun server-stop-automatically--handle-delete-frame (frame)
- "Handle deletion of FRAME when `server-stop-automatically' is used."
- (when server-stop-automatically
- (if (if (and (processp (frame-parameter frame 'client))
- (eq this-command 'save-buffers-kill-terminal))
- (progn
- (dolist (f (frame-list))
- (when (and (eq (frame-parameter frame 'client)
- (frame-parameter f 'client))
- (not (eq frame f)))
- (set-frame-parameter f 'client nil)
- (let ((server-stop-automatically nil))
- (delete-frame f))))
- (if (cddr (frame-list))
- (let ((server-stop-automatically nil))
- (delete-frame frame)
- nil)
- t))
- (null (cddr (frame-list))))
- (let ((server-stop-automatically nil))
- (save-buffers-kill-emacs)
- (delete-frame frame)))))
+(defun server-stop-automatically--handle-delete-frame (_frame)
+ "Handle deletion of FRAME when `server-stop-automatically' is `delete-frame'."
+ (when (null (cddr (frame-list)))
+ (let ((server-stop-automatically nil))
+ (save-buffers-kill-emacs))))
(defun server-stop-automatically--maybe-kill-emacs ()
- "Handle closing of Emacs daemon when `server-stop-automatically' is used."
+ "Handle closing of Emacs daemon when `server-stop-automatically' is `empty'."
(unless (cdr (frame-list))
(when (and
(not (memq t (mapcar (lambda (b)
@@ -1856,41 +1851,70 @@ only these files will be asked to be saved."
(process-list)))))
(kill-emacs))))
-;;;###autoload
-(defun server-stop-automatically (arg)
- "Automatically stop server as specified by ARG.
-
-If ARG is the symbol `empty', stop the server when it has no
+(defun server-apply-stop-automatically ()
+ "Apply the current value of `server-stop-automatically'.
+This function adds or removes the necessary helpers to manage
+stopping the Emacs server automatically, depending on the whether
+the server is running or not. This function only applies when
+running Emacs as a daemon."
+ (when (daemonp)
+ (let (empty-timer-p delete-frame-p)
+ (when server-process
+ (pcase server-stop-automatically
+ ('empty (setq empty-timer-p t))
+ ('delete-frame (setq delete-frame-p t))))
+ ;; Start or stop the timer.
+ (if empty-timer-p
+ (unless server-stop-automatically--timer
+ (setq server-stop-automatically--timer
+ (run-with-timer
+ 10 2
+ #'server-stop-automatically--maybe-kill-emacs)))
+ (when server-stop-automatically--timer
+ (cancel-timer server-stop-automatically--timer)
+ (setq server-stop-automatically--timer nil)))
+ ;; Add or remove the delete-frame hook.
+ (if delete-frame-p
+ (add-hook 'delete-frame-functions
+ #'server-stop-automatically--handle-delete-frame)
+ (remove-hook 'delete-frame-functions
+ #'server-stop-automatically--handle-delete-frame))))
+ ;; Return the current value of `server-stop-automatically'.
+ server-stop-automatically)
+
+(defcustom server-stop-automatically nil
+ "If non-nil, stop the server under the requested conditions.
+
+If this is the symbol `empty', stop the server when it has no
remaining clients, no remaining unsaved file-visiting buffers,
and no running processes with a `query-on-exit' flag.
-If ARG is the symbol `delete-frame', ask the user when the last
+If this is the symbol `delete-frame', ask the user when the last
frame is deleted whether each unsaved file-visiting buffer must
be saved and each running process with a `query-on-exit' flag
can be stopped, and if so, stop the server itself.
-If ARG is the symbol `kill-terminal', ask the user when the
+If this is the symbol `kill-terminal', ask the user when the
terminal is killed with \\[save-buffers-kill-terminal] \
whether each unsaved file-visiting
buffer must be saved and each running process with a `query-on-exit'
-flag can be stopped, and if so, stop the server itself.
-
-Any other value of ARG will cause this function to signal an error.
+flag can be stopped, and if so, stop the server itself."
+ :type '(choice
+ (const :tag "Never" nil)
+ (const :tag "When no clients, unsaved files, or processes"
+ empty)
+ (const :tag "When killing last terminal" kill-terminal)
+ (const :tag "When killing last terminal or frame" delete-frame))
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (server-apply-stop-automatically))
+ :version "29.1")
-This function is meant to be called from the user init file."
- (when (daemonp)
- (setq server-stop-automatically arg)
- (cond
- ((eq arg 'empty)
- (setq server-stop-automatically nil)
- (run-with-timer 10 2
- #'server-stop-automatically--maybe-kill-emacs))
- ((eq arg 'delete-frame)
- (add-hook 'delete-frame-functions
- #'server-stop-automatically--handle-delete-frame))
- ((eq arg 'kill-terminal))
- (t
- (error "Unexpected argument")))))
+;;;###autoload
+(defun server-stop-automatically (value)
+ "Automatically stop the Emacs server as specified by VALUE.
+This sets the variable `server-stop-automatically' (which see)."
+ (setopt server-stop-automatically value))
(define-key ctl-x-map "#" 'server-edit)
diff --git a/lisp/simple.el b/lisp/simple.el
index 4551b749d56..cf0845853a2 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -8438,6 +8438,43 @@ are interchanged."
(interactive "*p")
(transpose-subr 'forward-word arg))
+(defvar transpose-sexps-function
+ (lambda (arg)
+ ;; Here we should try to simulate the behavior of
+ ;; (cons (progn (forward-sexp x) (point))
+ ;; (progn (forward-sexp (- x)) (point)))
+ ;; Except that we don't want to rely on the second forward-sexp
+ ;; putting us back to where we want to be, since forward-sexp-function
+ ;; might do funny things like infix-precedence.
+ (if (if (> arg 0)
+ (looking-at "\\sw\\|\\s_")
+ (and (not (bobp))
+ (save-excursion
+ (forward-char -1)
+ (looking-at "\\sw\\|\\s_"))))
+ ;; Jumping over a symbol. We might be inside it, mind you.
+ (progn (funcall (if (> arg 0)
+ #'skip-syntax-backward #'skip-syntax-forward)
+ "w_")
+ (cons (save-excursion (forward-sexp arg) (point)) (point)))
+ ;; Otherwise, we're between sexps. Take a step back before jumping
+ ;; to make sure we'll obey the same precedence no matter which
+ ;; direction we're going.
+ (funcall (if (> arg 0) #'skip-syntax-backward #'skip-syntax-forward)
+ " .")
+ (cons (save-excursion (forward-sexp arg) (point))
+ (progn (while (or (forward-comment (if (> arg 0) 1 -1))
+ (not (zerop (funcall (if (> arg 0)
+ #'skip-syntax-forward
+ #'skip-syntax-backward)
+ ".")))))
+ (point)))))
+ "If non-nil, `transpose-sexps' delegates to this function.
+
+This function takes one argument ARG, a number. Its expected
+return value is a position pair, which is a cons (BEG . END),
+where BEG and END are buffer positions.")
+
(defun transpose-sexps (arg &optional interactive)
"Like \\[transpose-chars] (`transpose-chars'), but applies to sexps.
Unlike `transpose-words', point must be between the two sexps and not
@@ -8453,38 +8490,7 @@ report errors as appropriate for this kind of usage."
(condition-case nil
(transpose-sexps arg nil)
(scan-error (user-error "Not between two complete sexps")))
- (transpose-subr
- (lambda (arg)
- ;; Here we should try to simulate the behavior of
- ;; (cons (progn (forward-sexp x) (point))
- ;; (progn (forward-sexp (- x)) (point)))
- ;; Except that we don't want to rely on the second forward-sexp
- ;; putting us back to where we want to be, since forward-sexp-function
- ;; might do funny things like infix-precedence.
- (if (if (> arg 0)
- (looking-at "\\sw\\|\\s_")
- (and (not (bobp))
- (save-excursion
- (forward-char -1)
- (looking-at "\\sw\\|\\s_"))))
- ;; Jumping over a symbol. We might be inside it, mind you.
- (progn (funcall (if (> arg 0)
- 'skip-syntax-backward 'skip-syntax-forward)
- "w_")
- (cons (save-excursion (forward-sexp arg) (point)) (point)))
- ;; Otherwise, we're between sexps. Take a step back before jumping
- ;; to make sure we'll obey the same precedence no matter which
- ;; direction we're going.
- (funcall (if (> arg 0) 'skip-syntax-backward 'skip-syntax-forward)
- " .")
- (cons (save-excursion (forward-sexp arg) (point))
- (progn (while (or (forward-comment (if (> arg 0) 1 -1))
- (not (zerop (funcall (if (> arg 0)
- 'skip-syntax-forward
- 'skip-syntax-backward)
- ".")))))
- (point)))))
- arg 'special)))
+ (transpose-subr transpose-sexps-function arg 'special)))
(defun transpose-lines (arg)
"Exchange current line and previous line, leaving point after both.
@@ -8509,13 +8515,15 @@ With argument 0, interchanges line point is in with line mark is in."
;; FIXME document SPECIAL.
(defun transpose-subr (mover arg &optional special)
"Subroutine to do the work of transposing objects.
-Works for lines, sentences, paragraphs, etc. MOVER is a function that
-moves forward by units of the given object (e.g. `forward-sentence',
-`forward-paragraph'). If ARG is zero, exchanges the current object
-with the one containing mark. If ARG is an integer, moves the
-current object past ARG following (if ARG is positive) or
-preceding (if ARG is negative) objects, leaving point after the
-current object."
+Works for lines, sentences, paragraphs, etc. MOVER is a function
+that moves forward by units of the given
+object (e.g. `forward-sentence', `forward-paragraph'), or a
+function calculating a cons of buffer positions.
+
+ If ARG is zero, exchanges the current object with the one
+containing mark. If ARG is an integer, moves the current object
+past ARG following (if ARG is positive) or preceding (if ARG is
+negative) objects, leaving point after the current object."
(let ((aux (if special mover
(lambda (x)
(cons (progn (funcall mover x) (point))
@@ -8542,6 +8550,8 @@ current object."
(goto-char (+ (car pos2) (- (cdr pos1) (car pos1))))))))
(defun transpose-subr-1 (pos1 pos2)
+ (unless (and pos1 pos2)
+ (error "Don't have two things to transpose"))
(when (> (car pos1) (cdr pos1)) (setq pos1 (cons (cdr pos1) (car pos1))))
(when (> (car pos2) (cdr pos2)) (setq pos2 (cons (cdr pos2) (car pos2))))
(when (> (car pos1) (car pos2))
diff --git a/lisp/startup.el b/lisp/startup.el
index 6270de2ace6..5a383630774 100644
--- a/lisp/startup.el
+++ b/lisp/startup.el
@@ -2921,7 +2921,7 @@ nil default-directory" name)
(when (looking-at "#!")
(forward-line))
(let (value form)
- (while (ignore-error 'end-of-file
+ (while (ignore-error end-of-file
(setq form (read (current-buffer))))
(setq value (eval form t)))
(kill-emacs (if (numberp value)
diff --git a/lisp/subr.el b/lisp/subr.el
index c13c3c6cc54..17116a9b3cd 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -280,14 +280,20 @@ change the list."
When COND yields non-nil, eval BODY forms sequentially and return
value of last one, or nil if there are none."
(declare (indent 1) (debug t))
- (list 'if cond (cons 'progn body)))
+ (if body
+ (list 'if cond (cons 'progn body))
+ (macroexp-warn-and-return "`when' with empty body"
+ cond '(empty-body when) t)))
(defmacro unless (cond &rest body)
"If COND yields nil, do BODY, else return nil.
When COND yields nil, eval BODY forms sequentially and return
value of last one, or nil if there are none."
(declare (indent 1) (debug t))
- (cons 'if (cons cond (cons nil body))))
+ (if body
+ (cons 'if (cons cond (cons nil body)))
+ (macroexp-warn-and-return "`unless' with empty body"
+ cond '(empty-body unless) t)))
(defsubst subr-primitive-p (object)
"Return t if OBJECT is a built-in primitive function."
@@ -380,9 +386,23 @@ without silencing all errors."
"Execute BODY; if the error CONDITION occurs, return nil.
Otherwise, return result of last form in BODY.
-CONDITION can also be a list of error conditions."
+CONDITION can also be a list of error conditions.
+The CONDITION argument is not evaluated. Do not quote it."
(declare (debug t) (indent 1))
- `(condition-case nil (progn ,@body) (,condition nil)))
+ (cond
+ ((and (eq (car-safe condition) 'quote)
+ (cdr condition) (null (cddr condition)))
+ (macroexp-warn-and-return
+ (format "`ignore-error' condition argument should not be quoted: %S"
+ condition)
+ `(condition-case nil (progn ,@body) (,(cadr condition) nil))
+ nil t condition))
+ (body
+ `(condition-case nil (progn ,@body) (,condition nil)))
+ (t
+ (macroexp-warn-and-return "`ignore-error' with empty body"
+ nil '(empty-body ignore-error) t condition))))
+
;;;; Basic Lisp functions.
@@ -4850,6 +4870,7 @@ but that should be robust in the unexpected case that an error is signaled."
(declare (debug t) (indent 1))
(let* ((err (make-symbol "err"))
(orig-body body)
+ (orig-format format)
(format (if (and (stringp format) body) format
(prog1 "Error: %S"
(if format (push format body)))))
@@ -4860,7 +4881,9 @@ but that should be robust in the unexpected case that an error is signaled."
(if (eq orig-body body) exp
;; The use without `format' is obsolete, let's warn when we bump
;; into any such remaining uses.
- (macroexp-warn-and-return "Missing format argument" exp nil nil format))))
+ (macroexp-warn-and-return
+ "Missing format argument in `with-demote-errors'" exp nil nil
+ orig-format))))
(defmacro combine-after-change-calls (&rest body)
"Execute BODY, but don't call the after-change functions till the end.
@@ -6086,14 +6109,8 @@ command is called from a keyboard macro?"
;; Skip special forms (from non-compiled code).
(and frame (null (car frame)))
;; Skip also `interactive-p' (because we don't want to know if
- ;; interactive-p was called interactively but if it's caller was)
- ;; and `byte-code' (idem; this appears in subexpressions of things
- ;; like condition-case, which are wrapped in a separate bytecode
- ;; chunk).
- ;; FIXME: For lexical-binding code, this is much worse,
- ;; because the frames look like "byte-code -> funcall -> #[...]",
- ;; which is not a reliable signature.
- (memq (nth 1 frame) '(interactive-p 'byte-code))
+ ;; interactive-p was called interactively but if it's caller was).
+ (eq (nth 1 frame) 'interactive-p)
;; Skip package-specific stack-frames.
(let ((skip (run-hook-with-args-until-success
'called-interactively-p-functions
diff --git a/lisp/tab-bar.el b/lisp/tab-bar.el
index 114294615b4..7433f5c8e51 100644
--- a/lisp/tab-bar.el
+++ b/lisp/tab-bar.el
@@ -105,7 +105,7 @@ For easier selection of tabs by their numbers, consider customizing
(const hyper)
(const super)
(const alt))
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
;; Reenable the tab-bar with new keybindings
@@ -116,23 +116,23 @@ For easier selection of tabs by their numbers, consider customizing
:version "27.1")
(defun tab-bar--define-keys ()
- "Install key bindings for switching between tabs if the user has configured them."
+ "Install key bindings to switch between tabs if so configured."
(when tab-bar-select-tab-modifiers
(global-set-key (vector (append tab-bar-select-tab-modifiers (list ?0)))
- 'tab-recent)
+ #'tab-recent)
(dotimes (i 8)
(global-set-key (vector (append tab-bar-select-tab-modifiers
(list (+ i 1 ?0))))
- 'tab-bar-select-tab))
+ #'tab-bar-select-tab))
(global-set-key (vector (append tab-bar-select-tab-modifiers (list ?9)))
- 'tab-last))
+ #'tab-last))
;; Don't override user customized key bindings
(unless (global-key-binding [(control tab)])
- (global-set-key [(control tab)] 'tab-next))
+ (global-set-key [(control tab)] #'tab-next))
(unless (global-key-binding [(control shift tab)])
- (global-set-key [(control shift tab)] 'tab-previous))
+ (global-set-key [(control shift tab)] #'tab-previous))
(unless (global-key-binding [(control shift iso-lefttab)])
- (global-set-key [(control shift iso-lefttab)] 'tab-previous))
+ (global-set-key [(control shift iso-lefttab)] #'tab-previous))
;; Replace default value with a condition that supports displaying
;; global-mode-string in the tab bar instead of the mode line.
@@ -157,6 +157,9 @@ For easier selection of tabs by their numbers, consider customizing
(defun tab-bar--load-buttons ()
"Load the icons for the tab buttons."
(require 'icons)
+ (declare-function icon-string "icons" (name))
+ (declare-function iconp "icons" (object))
+ (declare-function icons--register "icons")
(unless (iconp 'tab-bar-new)
(define-icon tab-bar-new nil
`((image "tabs/new.xpm"
@@ -227,7 +230,8 @@ a list of frames to update."
;; Update `default-frame-alist'
(when (eq frames t)
(setq default-frame-alist
- (cons (cons 'tab-bar-lines (if (and tab-bar-mode (eq tab-bar-show t)) 1 0))
+ (cons (cons 'tab-bar-lines
+ (if (and tab-bar-mode (eq tab-bar-show t)) 1 0))
(assq-delete-all 'tab-bar-lines default-frame-alist)))))
(define-minor-mode tab-bar-mode
@@ -279,7 +283,8 @@ It returns a list of the form (KEY KEY-BINDING CLOSE-P), where:
;; This code is used when you click the mouse in the tab bar
;; on a console which has no window system but does have a mouse.
(let* ((x-position (car (posn-x-y posn)))
- (keymap (lookup-key (cons 'keymap (nreverse (current-active-maps))) [tab-bar]))
+ (keymap (lookup-key (cons 'keymap (nreverse (current-active-maps)))
+ [tab-bar]))
(column 0))
(when x-position
(catch 'done
@@ -478,7 +483,7 @@ you can use the command `toggle-frame-tab-bar'."
:type '(choice (const :tag "Always" t)
(const :tag "When more than one tab" 1)
(const :tag "Never" nil))
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(if val
@@ -529,7 +534,7 @@ to get the group name."
"If non-nil, show the \"New tab\" button in the tab bar.
When this is nil, you can create new tabs with \\[tab-new]."
:type 'boolean
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -550,7 +555,7 @@ If nil, don't show it at all."
(const :tag "On selected tab" selected)
(const :tag "On non-selected tabs" non-selected)
(const :tag "None" nil))
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -574,7 +579,7 @@ If nil, don't show it at all."
This helps to select the tab by its number using `tab-bar-select-tab'
and `tab-bar-select-tab-modifiers'."
:type 'boolean
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -604,7 +609,7 @@ from all windows in the window configuration."
(const :tag "All window buffers"
tab-bar-tab-name-all)
(function :tag "Function"))
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -704,7 +709,7 @@ Function gets one argument: a tab."
Function gets two arguments, the tab and its number, and should return
the formatted tab name to display in the tab bar."
:type 'function
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -753,7 +758,7 @@ of the mode line. Replacing `tab-bar-format-tabs' with
tab-bar-format-add-tab
tab-bar-format-align-right
tab-bar-format-global)
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -815,7 +820,8 @@ You can hide these buttons by customizing `tab-bar-format' and removing
,(alist-get 'binding tab)
:help "Click to visit tab"))))
(when (alist-get 'close-binding tab)
- `((,(if (eq (car tab) 'current-tab) 'C-current-tab (intern (format "C-tab-%i" i)))
+ `((,(if (eq (car tab) 'current-tab) 'C-current-tab
+ (intern (format "C-tab-%i" i)))
menu-item ""
,(alist-get 'close-binding tab))))))
@@ -832,7 +838,7 @@ You can hide these buttons by customizing `tab-bar-format' and removing
"Function to get a tab group name.
Function gets one argument: a tab."
:type 'function
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -848,7 +854,7 @@ Function gets three arguments, a tab with a group name, its number, and
an optional value that is non-nil when the tab is from the current group.
It should return the formatted tab group name to display in the tab bar."
:type 'function
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(force-mode-line-update))
@@ -919,7 +925,8 @@ when the tab is current. Return the result as a keymap."
(when (and (not (equal previous-group tab-group)) tab-group)
(tab-bar--format-tab-group tab i t))
;; Override default tab faces to use group faces
- (let ((tab-bar-tab-face-function tab-bar-tab-group-face-function))
+ (let ((tab-bar-tab-face-function
+ tab-bar-tab-group-face-function))
(tab-bar--format-tab tab i))))
;; Show first tab of other groups with a group name
((not (equal previous-group tab-group))
@@ -948,7 +955,8 @@ when the tab is current. Return the result as a keymap."
;; when windows are split horizontally (bug#59620)
(if (window-system)
`(space :align-to (- right (,hpos)))
- `(space :align-to (,(- (frame-inner-width) hpos)))))))
+ `(space :align-to (,(- (frame-inner-width)
+ hpos)))))))
`((align-right menu-item ,str ignore))))
(defun tab-bar-format-global ()
@@ -1018,7 +1026,7 @@ This variable has effect only when `tab-bar-auto-width' is non-nil."
(const :tag "No limit" nil)
(list (integer :tag "Max width (pixels)" :value 220)
(integer :tag "Max width (chars)" :value 20)))
- :initialize 'custom-initialize-default
+ :initialize #'custom-initialize-default
:set (lambda (sym val)
(set-default sym val)
(setq tab-bar--auto-width-hash nil))
@@ -1087,12 +1095,14 @@ tab bar might wrap to the second line when it shouldn't.")
curr-width)
(cond
((< prev-width width)
- (let* ((space (apply 'propertize " "
+ (let* ((space (apply #'propertize " "
(text-properties-at 0 name)))
(ins-pos (- len (if close-p 1 0)))
(prev-name name))
(while continue
- (setf (substring name ins-pos ins-pos) space)
+ (setq name (concat (substring name 0 ins-pos)
+ space
+ (substring name ins-pos)))
(setq curr-width (string-pixel-width name))
(if (and (< curr-width width)
(> curr-width prev-width))
@@ -1105,7 +1115,9 @@ tab bar might wrap to the second line when it shouldn't.")
(let ((del-pos1 (if close-p -2 -1))
(del-pos2 (if close-p -1 nil)))
(while continue
- (setf (substring name del-pos1 del-pos2) "")
+ (setq name (concat (substring name 0 del-pos1)
+ (and del-pos2
+ (substring name del-pos2))))
(setq curr-width (string-pixel-width name))
(if (and (> curr-width width)
(< curr-width prev-width))
@@ -1309,11 +1321,13 @@ Negative TAB-NUMBER counts tabs from the end of the tab bar."
(when tab-bar-history-mode
(puthash (selected-frame)
- (and (window-configuration-p (alist-get 'wc (car wc-history-back)))
+ (and (window-configuration-p
+ (alist-get 'wc (car wc-history-back)))
wc-history-back)
tab-bar-history-back)
(puthash (selected-frame)
- (and (window-configuration-p (alist-get 'wc (car wc-history-forward)))
+ (and (window-configuration-p
+ (alist-get 'wc (car wc-history-forward)))
wc-history-forward)
tab-bar-history-forward))))
@@ -1339,7 +1353,8 @@ Negative TAB-NUMBER counts tabs from the end of the tab bar."
(when from-index
(setf (nth from-index tabs) from-tab))
- (setf (nth to-index tabs) (tab-bar--current-tab-make (nth to-index tabs)))
+ (setf (nth to-index tabs)
+ (tab-bar--current-tab-make (nth to-index tabs)))
(unless tab-bar-mode
(message "Selected tab '%s'" (alist-get 'name to-tab))))
@@ -1406,7 +1421,7 @@ and rename it to NAME."
(tab-bar-new-tab)
(tab-bar-rename-tab name))))
-(defalias 'tab-bar-select-tab-by-name 'tab-bar-switch-to-tab)
+(defalias 'tab-bar-select-tab-by-name #'tab-bar-switch-to-tab)
(defun tab-bar-move-tab-to (to-number &optional from-number)
@@ -1421,7 +1436,8 @@ where argument addressing is relative."
(from-number (or from-number (1+ (tab-bar--current-tab-index tabs))))
(from-tab (nth (1- from-number) tabs))
(to-number (if to-number (prefix-numeric-value to-number) 1))
- (to-number (if (< to-number 0) (+ (length tabs) (1+ to-number)) to-number))
+ (to-number (if (< to-number 0) (+ (length tabs) (1+ to-number))
+ to-number))
(to-index (max 0 (min (1- to-number) (1- (length tabs))))))
(setq tabs (delq from-tab tabs))
(cl-pushnew from-tab (nthcdr to-index tabs))
@@ -1447,7 +1463,8 @@ Like `tab-bar-move-tab', but moves in the opposite direction."
(interactive "p")
(tab-bar-move-tab (- (or arg 1))))
-(defun tab-bar-move-tab-to-frame (arg &optional from-frame from-number to-frame to-number)
+(defun tab-bar-move-tab-to-frame (arg &optional from-frame from-number
+ to-frame to-number)
"Move tab from FROM-NUMBER position to new position at TO-NUMBER.
FROM-NUMBER defaults to the current tab number.
FROM-NUMBER and TO-NUMBER count from 1.
@@ -1463,7 +1480,8 @@ to which to move the tab; ARG defaults to 1."
(setq to-frame (next-frame to-frame))))
(unless (eq from-frame to-frame)
(let* ((from-tabs (funcall tab-bar-tabs-function from-frame))
- (from-number (or from-number (1+ (tab-bar--current-tab-index from-tabs))))
+ (from-number (or from-number
+ (1+ (tab-bar--current-tab-index from-tabs))))
(from-tab (nth (1- from-number) from-tabs))
(to-tabs (funcall tab-bar-tabs-function to-frame))
(to-index (max 0 (min (1- (or to-number 1)) (1- (length to-tabs))))))
@@ -1485,7 +1503,8 @@ to which to move the tab; ARG defaults to 1."
FROM-NUMBER defaults to the current tab (which happens interactively)."
(interactive (list (1+ (tab-bar--current-tab-index))))
(let* ((tabs (funcall tab-bar-tabs-function))
- (tab-index (1- (or from-number (1+ (tab-bar--current-tab-index tabs)))))
+ (tab-index (1- (or from-number
+ (1+ (tab-bar--current-tab-index tabs)))))
(tab-name (alist-get 'name (nth tab-index tabs)))
;; On some window managers, `make-frame' selects the new frame,
;; so previously selected frame is saved to `from-frame'.
@@ -1748,7 +1767,8 @@ for the last tab on a frame is determined by
;; Select another tab before deleting the current tab
(let ((to-index (or (if to-number (1- to-number))
(pcase tab-bar-close-tab-select
- ('left (1- (if (< current-index 1) 2 current-index)))
+ ('left (1- (if (< current-index 1) 2
+ current-index)))
('right (if (> (length tabs) (1+ current-index))
(1+ current-index)
(1- current-index)))
@@ -1773,7 +1793,8 @@ for the last tab on a frame is determined by
(force-mode-line-update)
(unless tab-bar-mode
- (message "Deleted tab and switched to %s" tab-bar-close-tab-select))))))
+ (message "Deleted tab and switched to %s"
+ tab-bar-close-tab-select))))))
(defun tab-bar-close-tab-by-name (name)
"Close the tab given its NAME.
@@ -1864,7 +1885,8 @@ If NAME is the empty string, then use the automatic name
function `tab-bar-tab-name-function'."
(interactive
(let* ((tabs (funcall tab-bar-tabs-function))
- (tab-number (or current-prefix-arg (1+ (tab-bar--current-tab-index tabs))))
+ (tab-number (or current-prefix-arg
+ (1+ (tab-bar--current-tab-index tabs))))
(tab-name (alist-get 'name (nth (1- tab-number) tabs))))
(list (read-from-minibuffer
"New name for tab (leave blank for automatic naming): "
@@ -2129,10 +2151,10 @@ and can restore them."
:version "29.1"))
(setq tab-bar-forward-button (icon-string 'tab-bar-forward))
- (add-hook 'pre-command-hook 'tab-bar--history-pre-change)
- (add-hook 'window-configuration-change-hook 'tab-bar--history-change))
- (remove-hook 'pre-command-hook 'tab-bar--history-pre-change)
- (remove-hook 'window-configuration-change-hook 'tab-bar--history-change)))
+ (add-hook 'pre-command-hook #'tab-bar--history-pre-change)
+ (add-hook 'window-configuration-change-hook #'tab-bar--history-change))
+ (remove-hook 'pre-command-hook #'tab-bar--history-pre-change)
+ (remove-hook 'window-configuration-change-hook #'tab-bar--history-change)))
;;; Non-graphical access to frame-local tabs (named window configurations)
@@ -2172,8 +2194,9 @@ For more information, see the function `tab-switcher'."
(tabs (sort tabs (lambda (a b) (< (alist-get 'time b)
(alist-get 'time a))))))
(with-current-buffer (get-buffer-create
- (format " *Tabs*<%s>" (or (frame-parameter nil 'window-id)
- (frame-parameter nil 'name))))
+ (format " *Tabs*<%s>"
+ (or (frame-parameter nil 'window-id)
+ (frame-parameter nil 'name))))
(setq buffer-read-only nil)
(erase-buffer)
(tab-switcher-mode)
@@ -2188,7 +2211,8 @@ For more information, see the function `tab-switcher'."
(propertize
(alist-get 'name tab)
'mouse-face 'highlight
- 'help-echo "mouse-2: select this window configuration"))
+ 'help-echo
+ "mouse-2: select this window configuration"))
'tab tab)))
(goto-char (point-min))
(goto-char (or (next-single-property-change (point) 'tab) (point-min)))
@@ -2264,8 +2288,8 @@ Interactively, ARG is the prefix numeric argument and defaults to 1."
(move-to-column tab-switcher-column))
(defun tab-switcher-unmark (&optional backup)
- "Cancel requested operations on window configuration on this line and move down.
-With prefix arg, move up instead."
+ "Cancel operations on window configuration on this line and move down.
+With prefix arg BACKUP, move up instead."
(interactive "P")
(beginning-of-line)
(move-to-column tab-switcher-column)
@@ -2276,7 +2300,7 @@ With prefix arg, move up instead."
(move-to-column tab-switcher-column))
(defun tab-switcher-backup-unmark ()
- "Move up one line and cancel requested operations on window configuration there."
+ "Move up one line and cancel operations on window configuration there."
(interactive)
(forward-line -1)
(tab-switcher-unmark)
@@ -2284,9 +2308,10 @@ With prefix arg, move up instead."
(move-to-column tab-switcher-column))
(defun tab-switcher-delete (&optional arg)
- "Mark window configuration on this line to be deleted by \\<tab-switcher-mode-map>\\[tab-switcher-execute] command.
+ "Mark window configuration on this line to be deleted.
Prefix arg says how many window configurations to delete.
-Negative arg means delete backwards."
+Negative arg means delete backwards.
+The deletion will be done by the \\<tab-switcher-mode-map>\\[tab-switcher-execute] command."
(interactive "p")
(let ((buffer-read-only nil))
(if (or (null arg) (= arg 0))
@@ -2304,8 +2329,9 @@ Negative arg means delete backwards."
(move-to-column tab-switcher-column)))
(defun tab-switcher-delete-backwards (&optional arg)
- "Mark window configuration on this line to be deleted by \\<tab-switcher-mode-map>\\[tab-switcher-execute] command.
-Then move up one line. Prefix arg means move that many lines."
+ "Mark window configuration on this line to be deleted.
+Then move up one line. Prefix arg means move that many lines.
+The deletion will be done by the \\<tab-switcher-mode-map>\\[tab-switcher-execute] command."
(interactive "p")
(tab-switcher-delete (- (or arg 1))))
@@ -2318,7 +2344,9 @@ Then move up one line. Prefix arg means move that many lines."
(tab-bar-tabs-set (delq tab (funcall tab-bar-tabs-function))))
(defun tab-switcher-execute ()
- "Delete window configurations marked with \\<tab-switcher-mode-map>\\[tab-switcher-delete] commands."
+ "Delete the marked window configurations.
+Use the \\<tab-switcher-mode-map>\\[tab-switcher-delete] commands
+to set those marks."
(interactive)
(save-excursion
(goto-char (point-min))
@@ -2364,7 +2392,8 @@ with those specified by the selected window configuration."
((framep all-frames) (list all-frames))
(t (list (selected-frame)))))
-(defun tab-bar-get-buffer-tab (buffer-or-name &optional all-frames ignore-current-tab all-tabs)
+(defun tab-bar-get-buffer-tab (buffer-or-name
+ &optional all-frames ignore-current-tab all-tabs)
"Return the tab that owns the window whose buffer is BUFFER-OR-NAME.
BUFFER-OR-NAME may be a buffer or a buffer name, and defaults to
the current buffer.
@@ -2540,7 +2569,7 @@ files will be visited."
(progn
(setq value (nreverse value))
(switch-to-buffer-other-tab (car value))
- (mapc 'switch-to-buffer (cdr value))
+ (mapc #'switch-to-buffer (cdr value))
value)
(switch-to-buffer-other-tab value))))
@@ -2582,26 +2611,26 @@ When `switch-to-buffer-obey-display-actions' is non-nil,
;;; Short aliases and keybindings
-(defalias 'tab-new 'tab-bar-new-tab)
-(defalias 'tab-new-to 'tab-bar-new-tab-to)
-(defalias 'tab-duplicate 'tab-bar-duplicate-tab)
-(defalias 'tab-detach 'tab-bar-detach-tab)
-(defalias 'tab-window-detach 'tab-bar-move-window-to-tab)
-(defalias 'tab-close 'tab-bar-close-tab)
-(defalias 'tab-close-other 'tab-bar-close-other-tabs)
-(defalias 'tab-close-group 'tab-bar-close-group-tabs)
-(defalias 'tab-undo 'tab-bar-undo-close-tab)
-(defalias 'tab-select 'tab-bar-select-tab)
-(defalias 'tab-switch 'tab-bar-switch-to-tab)
-(defalias 'tab-next 'tab-bar-switch-to-next-tab)
-(defalias 'tab-previous 'tab-bar-switch-to-prev-tab)
-(defalias 'tab-last 'tab-bar-switch-to-last-tab)
-(defalias 'tab-recent 'tab-bar-switch-to-recent-tab)
-(defalias 'tab-move 'tab-bar-move-tab)
-(defalias 'tab-move-to 'tab-bar-move-tab-to)
-(defalias 'tab-rename 'tab-bar-rename-tab)
-(defalias 'tab-group 'tab-bar-change-tab-group)
-(defalias 'tab-list 'tab-switcher)
+(defalias 'tab-new #'tab-bar-new-tab)
+(defalias 'tab-new-to #'tab-bar-new-tab-to)
+(defalias 'tab-duplicate #'tab-bar-duplicate-tab)
+(defalias 'tab-detach #'tab-bar-detach-tab)
+(defalias 'tab-window-detach #'tab-bar-move-window-to-tab)
+(defalias 'tab-close #'tab-bar-close-tab)
+(defalias 'tab-close-other #'tab-bar-close-other-tabs)
+(defalias 'tab-close-group #'tab-bar-close-group-tabs)
+(defalias 'tab-undo #'tab-bar-undo-close-tab)
+(defalias 'tab-select #'tab-bar-select-tab)
+(defalias 'tab-switch #'tab-bar-switch-to-tab)
+(defalias 'tab-next #'tab-bar-switch-to-next-tab)
+(defalias 'tab-previous #'tab-bar-switch-to-prev-tab)
+(defalias 'tab-last #'tab-bar-switch-to-last-tab)
+(defalias 'tab-recent #'tab-bar-switch-to-recent-tab)
+(defalias 'tab-move #'tab-bar-move-tab)
+(defalias 'tab-move-to #'tab-bar-move-tab-to)
+(defalias 'tab-rename #'tab-bar-rename-tab)
+(defalias 'tab-group #'tab-bar-change-tab-group)
+(defalias 'tab-list #'tab-switcher)
(keymap-set tab-prefix-map "n" #'tab-duplicate)
(keymap-set tab-prefix-map "N" #'tab-new-to)
diff --git a/lisp/transient.el b/lisp/transient.el
index 0919c2c3ef0..01c492c68c1 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -6,7 +6,7 @@
;; URL: https://github.com/magit/transient
;; Keywords: extensions
-;; Package-Version: 0.3.7
+;; Package-Version: 0.3.7.50
;; Package-Requires: ((emacs "26.1"))
;; SPDX-License-Identifier: GPL-3.0-or-later
@@ -2199,11 +2199,11 @@ value. Otherwise return CHILDREN as is."
(delayed (if transient--exitp
(apply-partially #'transient--post-exit this-command)
#'transient--resume-override))
- post-command abort-minibuffer)
+ outside-interactive post-command abort-minibuffer)
(unless abort-only
(setq post-command
(lambda () "@transient--delay-post-command"
- (let ((act (and (not (eq (this-command-keys-vector) []))
+ (let ((act (and (not (equal (this-command-keys-vector) []))
(or (eq this-command command)
;; `execute-extended-command' was
;; used to call another command
@@ -2211,7 +2211,9 @@ value. Otherwise return CHILDREN as is."
(equal
(ignore-errors
(string-to-multibyte (this-command-keys)))
- (format "\M-x%s\r" this-command))))))
+ (format "\M-x%s\r" this-command))
+ ;; Minibuffer used outside `interactive'.
+ (and outside-interactive 'post-cmd)))))
(transient--debug 'post-command-hook "act: %s" act)
(when act
(remove-hook 'transient--post-command-hook post-command)
@@ -2220,12 +2222,15 @@ value. Otherwise return CHILDREN as is."
(add-hook 'transient--post-command-hook post-command))
(setq abort-minibuffer
(lambda () "@transient--delay-post-command"
- (let ((act (and (or (memq this-command transient--abort-commands)
- (equal (this-command-keys) ""))
- (= (minibuffer-depth) depth))))
+ (let ((act (and (= (minibuffer-depth) depth)
+ (or (memq this-command transient--abort-commands)
+ (equal (this-command-keys) "")
+ (prog1 nil
+ (setq outside-interactive t))))))
(transient--debug
'abort-minibuffer
- "mini: %s|%s, act %s" (minibuffer-depth) depth act)
+ "mini: %s|%s, act: %s" (minibuffer-depth) depth
+ (or act (and outside-interactive '->post-cmd)))
(when act
(remove-hook 'transient--post-command-hook post-command)
(remove-hook 'minibuffer-exit-hook abort-minibuffer)
@@ -2236,7 +2241,7 @@ value. Otherwise return CHILDREN as is."
(transient--debug 'post-command)
(transient--with-emergency-exit
(cond
- ((and (eq (this-command-keys-vector) [])
+ ((and (equal (this-command-keys-vector) [])
(= (minibuffer-depth)
(1+ transient--minibuffer-depth)))
(transient--suspend-override)
@@ -2407,6 +2412,10 @@ If there is no parent prefix, then behave like `transient--do-exit'."
(transient--stack-zap)
transient--exit)
+(defun transient--do-leave ()
+ "Call the command without exporting variables and exit the transient."
+ transient--stay)
+
(defun transient--do-push-button ()
"Call the command represented by the activated button.
Use that command's pre-command to determine transient behavior."
@@ -3376,7 +3385,7 @@ have a history of their own.")
(insert ?\n)
(insert (propertize " " 'display
`(space :align-to (,(nth (1+ c) cc)))))))
- (insert (make-string (- (nth c cc) (current-column)) ?\s))
+ (insert (make-string (max 1 (- (nth c cc) (current-column))) ?\s))
(when-let ((cell (nth r (nth c columns))))
(insert cell))
(when (= c (1- cs))
@@ -4119,7 +4128,10 @@ we stop there."
'face 'transient-value))
(cl-defmethod transient-prompt ((obj transient-lisp-variable))
- (format "Set %s: " (oref obj variable)))
+ (if (and (slot-boundp obj 'prompt)
+ (oref obj prompt))
+ (cl-call-next-method obj)
+ (format "Set %s: " (oref obj variable))))
(defun transient-lisp-variable--reader (prompt initial-input _history)
(read--expression prompt initial-input))
diff --git a/lisp/treesit.el b/lisp/treesit.el
index e7bd12d362e..545659e9967 100644
--- a/lisp/treesit.el
+++ b/lisp/treesit.el
@@ -1597,6 +1597,32 @@ BACKWARD and ALL are the same as in `treesit-search-forward'."
(goto-char current-pos)))
node))
+(defun treesit-transpose-sexps (&optional arg)
+ "Tree-sitter `transpose-sexps' function.
+Arg is the same as in `transpose-sexps'.
+
+Locate the node closest to POINT, and transpose that node with
+its sibling node ARG nodes away.
+
+Return a pair of positions as described by
+`transpose-sexps-function' for use in `transpose-subr' and
+friends."
+ (let* ((parent (treesit-node-parent (treesit-node-at (point))))
+ (child (treesit-node-child parent 0 t)))
+ (named-let loop ((prev child)
+ (next (treesit-node-next-sibling child t)))
+ (when (and prev next)
+ (if (< (point) (treesit-node-end next))
+ (if (= arg -1)
+ (cons (treesit-node-start prev)
+ (treesit-node-end prev))
+ (when-let ((n (treesit-node-child
+ parent (+ arg (treesit-node-index prev t)) t)))
+ (cons (treesit-node-end n)
+ (treesit-node-start n))))
+ (loop (treesit-node-next-sibling prev t)
+ (treesit-node-next-sibling next t)))))))
+
;;; Navigation, defun, things
;;
;; Emacs lets you define "things" by a regexp that matches the type of
@@ -1739,6 +1765,15 @@ this function depends on `treesit-defun-type-regexp' and
(when treesit-defun-skipper
(funcall treesit-defun-skipper))))
+(defvar-local treesit-text-type-regexp "\\`comment\\'"
+ "A regexp that matches the node type of textual nodes.
+
+A textual node is a node that is not normal code, such as
+comments and multiline string literals. For example,
+\"(line|block)_comment\" in the case of a comment, or
+\"text_block\" in the case of a string. This is used by
+`prog-fill-reindent-defun' and friends.")
+
(defun treesit-default-defun-skipper ()
"Skips spaces after navigating a defun.
This function tries to move to the beginning of a line, either by
@@ -2201,6 +2236,9 @@ before calling this function."
(when treesit-defun-name-function
(setq-local add-log-current-defun-function
#'treesit-add-log-current-defun))
+
+ (setq-local transpose-sexps-function #'treesit-transpose-sexps)
+
;; Imenu.
(when treesit-simple-imenu-settings
(setq-local imenu-create-index-function
diff --git a/lisp/url/url-future.el b/lisp/url/url-future.el
index 56787f7c5ec..737eea32c6a 100644
--- a/lisp/url/url-future.el
+++ b/lisp/url/url-future.el
@@ -53,7 +53,7 @@
(define-inline url-future-errored-p (url-future)
(inline-quote (eq (url-future-status ,url-future) 'error)))
-(define-inline url-future-cancelled-p (url-future)
+(define-inline url-future-canceled-p (url-future)
(inline-quote (eq (url-future-status ,url-future) 'cancel)))
(defun url-future-finish (url-future &optional status)
@@ -96,5 +96,8 @@
(signal 'error 'url-future-already-done)
(url-future-finish url-future 'cancel)))
+(define-obsolete-function-alias 'url-future-cancelled-p
+ #'url-future-canceled-p "30.1")
+
(provide 'url-future)
;;; url-future.el ends here
diff --git a/lisp/use-package/bind-key.el b/lisp/use-package/bind-key.el
index 1ce717019f1..c3890c4d0aa 100644
--- a/lisp/use-package/bind-key.el
+++ b/lisp/use-package/bind-key.el
@@ -447,7 +447,7 @@ This binds keys in such a way that bindings are not overridden by
other modes. See `override-global-mode'."
(macroexp-progn (bind-keys-form args 'override-global-map)))
-(defun get-binding-description (elem)
+(defun bind-key--get-binding-description (elem)
(cond
((listp elem)
(cond
@@ -474,7 +474,7 @@ other modes. See `override-global-mode'."
(t
"#<byte-compiled lambda>")))
-(defun compare-keybindings (l r)
+(defun bind-key--compare-keybindings (l r)
(let* ((regex bind-key-segregation-regexp)
(lgroup (and (string-match regex (caar l))
(match-string 0 (caar l))))
@@ -517,7 +517,7 @@ other modes. See `override-global-mode'."
(setq personal-keybindings
(sort personal-keybindings
(lambda (l r)
- (car (compare-keybindings l r))))))
+ (car (bind-key--compare-keybindings l r))))))
(if (not (eq (cdar last-binding) (cdar binding)))
(princ (format "\n\n%s: %s\n%s\n\n"
@@ -525,7 +525,7 @@ other modes. See `override-global-mode'."
(make-string (+ 21 (car bind-key-column-widths)
(cdr bind-key-column-widths)) ?-)))
(if (and last-binding
- (cdr (compare-keybindings last-binding binding)))
+ (cdr (bind-key--compare-keybindings last-binding binding)))
(princ "\n")))
(let* ((key-name (caar binding))
@@ -534,10 +534,10 @@ other modes. See `override-global-mode'."
(read-kbd-macro key-name)))
(command (nth 1 binding))
(was-command (nth 2 binding))
- (command-desc (get-binding-description command))
+ (command-desc (bind-key--get-binding-description command))
(was-command-desc (and was-command
- (get-binding-description was-command)))
- (at-present-desc (get-binding-description at-present)))
+ (bind-key--get-binding-description was-command)))
+ (at-present-desc (bind-key--get-binding-description at-present)))
(let ((line
(format
(format "%%-%ds%%-%ds%%s\n" (car bind-key-column-widths)
@@ -555,6 +555,11 @@ other modes. See `override-global-mode'."
(setq last-binding binding)))))
+(define-obsolete-function-alias 'get-binding-description
+ 'bind-key--get-binding-description "30.1")
+(define-obsolete-function-alias 'compare-keybindings
+ 'bind-key--compare-keybindings "30.1")
+
(provide 'bind-key)
;; Local Variables:
diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el
index afaaa44e908..918a210cee9 100644
--- a/lisp/vc/vc-git.el
+++ b/lisp/vc/vc-git.el
@@ -136,12 +136,19 @@ If nil, use the value of `vc-annotate-switches'. If t, use no switches."
;;;###autoload(put 'vc-git-annotate-switches 'safe-local-variable (lambda (switches) (equal switches "-w")))
(defcustom vc-git-log-switches nil
- "String or list of strings specifying switches for Git log under VC."
+ "String or list of strings giving Git log switches for non-shortlogs."
:type '(choice (const :tag "None" nil)
(string :tag "Argument String")
(repeat :tag "Argument List" :value ("") string))
:version "28.1")
+(defcustom vc-git-shortlog-switches nil
+ "String or list of strings giving Git log switches for shortlogs."
+ :type '(choice (const :tag "None" nil)
+ (string :tag "Argument String")
+ (repeat :tag "Argument List" :value ("") string))
+ :version "30.1")
+
(defcustom vc-git-resolve-conflicts t
"When non-nil, mark conflicted file as resolved upon saving.
That is performed after all conflict markers in it have been
@@ -308,6 +315,23 @@ Good example of file name that needs this: \"test[56].xx\".")
(string-trim-right (match-string 1 version-string) "\\.")
"0")))))
+(defun vc-git--git-path (&optional path)
+ "Resolve .git/PATH for the current working tree.
+In particular, handle the case where this is a linked working
+tree, such that .git is a plain file.
+
+See the --git-dir and --git-path options to git-rev-parse(1)."
+ (if (and path (not (string-empty-p path)))
+ ;; Canonicalize in this branch because --git-dir always returns
+ ;; an absolute file name.
+ (expand-file-name
+ (string-trim-right
+ (vc-git--run-command-string nil "rev-parse"
+ "--git-path" path)))
+ (concat (string-trim-right
+ (vc-git--run-command-string nil "rev-parse" "--git-dir"))
+ "/")))
+
(defun vc-git--git-status-to-vc-state (code-list)
"Convert CODE-LIST to a VC status.
@@ -752,12 +776,32 @@ or an empty string if none."
:help "Show the contents of the current stash"))
map))
+(defun vc-git--cmds-in-progress ()
+ "Return a list of Git commands in progress in this worktree."
+ (let ((gitdir (vc-git--git-path))
+ cmds)
+ ;; See contrib/completion/git-prompt.sh in git.git.
+ (when (or (file-directory-p
+ (expand-file-name "rebase-merge" gitdir))
+ (file-exists-p
+ (expand-file-name "rebase-apply/rebasing" gitdir)))
+ (push 'rebase cmds))
+ (when (file-exists-p
+ (expand-file-name "rebase-apply/applying" gitdir))
+ (push 'am cmds))
+ (when (file-exists-p (expand-file-name "MERGE_HEAD" gitdir))
+ (push 'merge cmds))
+ (when (file-exists-p (expand-file-name "BISECT_START" gitdir))
+ (push 'bisect cmds))
+ cmds))
+
(defun vc-git-dir-extra-headers (dir)
(let ((str (with-output-to-string
(with-current-buffer standard-output
(vc-git--out-ok "symbolic-ref" "HEAD"))))
(stash-list (vc-git-stash-list))
(default-directory dir)
+ (in-progress (vc-git--cmds-in-progress))
branch remote remote-url stash-button stash-string)
(if (string-match "^\\(refs/heads/\\)?\\(.+\\)$" str)
@@ -832,9 +876,9 @@ or an empty string if none."
(propertize remote-url
'face 'vc-dir-header-value)))
;; For now just a heading, key bindings can be added later for various bisect actions
- (when (file-exists-p (expand-file-name ".git/BISECT_START" (vc-git-root dir)))
+ (when (memq 'bisect in-progress)
(propertize "\nBisect : in progress" 'face 'vc-dir-status-warning))
- (when (file-exists-p (expand-file-name ".git/rebase-apply" (vc-git-root dir)))
+ (when (memq 'rebase in-progress)
(propertize "\nRebase : in progress" 'face 'vc-dir-status-warning))
(if stash-list
(concat
@@ -1013,33 +1057,58 @@ It is based on `log-edit-mode', and has Git-specific extensions."
;; message. Handle also remote files.
(if (eq system-type 'windows-nt)
(let ((default-directory (file-name-directory file1)))
- (make-nearby-temp-file "git-msg")))))
+ (make-nearby-temp-file "git-msg"))))
+ to-stash)
(when vc-git-patch-string
(unless (zerop (vc-git-command nil t nil "diff" "--cached" "--quiet"))
- ;; Check that all staged changes also exist in the patch.
- ;; This is needed to allow adding/removing files that are
- ;; currently staged to the index. So remove the whole file diff
- ;; from the patch because commit will take it from the index.
+ ;; Check that what's already staged is compatible with what
+ ;; we want to commit (bug#60126).
+ ;;
+ ;; 1. If the changes to a file in the index are identical to
+ ;; the changes to that file we want to commit, remove the
+ ;; changes from our patch, and let the commit take them
+ ;; from the index. This is necessary for adding and
+ ;; removing files to work.
+ ;;
+ ;; 2. If the changes to a file in the index are different to
+ ;; changes to that file we want to commit, then we have to
+ ;; unstage the changes or abort.
+ ;;
+ ;; 3. If there are changes to a file in the index but we don't
+ ;; want to commit any changes to that file, we need to
+ ;; stash those changes before committing.
(with-temp-buffer
(vc-git-command (current-buffer) t nil "diff" "--cached")
(goto-char (point-min))
- (let ((pos (point)) file-diff file-beg)
+ (let ((pos (point)) file-name file-header file-diff file-beg)
(while (not (eobp))
+ (when (and (looking-at "^diff --git a/\\(.+\\) b/\\(.+\\)")
+ (string= (match-string 1) (match-string 2)))
+ (setq file-name (match-string 1)))
(forward-line 1) ; skip current "diff --git" line
+ (setq file-header (buffer-substring pos (point)))
(search-forward "diff --git" nil 'move)
(move-beginning-of-line 1)
(setq file-diff (buffer-substring pos (point)))
- (if (and (setq file-beg (string-search
- file-diff vc-git-patch-string))
- ;; Check that file diff ends with an empty string
- ;; or the beginning of the next file diff.
- (string-match-p "\\`\\'\\|\\`diff --git"
- (substring
- vc-git-patch-string
- (+ file-beg (length file-diff)))))
- (setq vc-git-patch-string
- (string-replace file-diff "" vc-git-patch-string))
- (user-error "Index not empty"))
+ (cond ((and (setq file-beg (string-search
+ file-diff vc-git-patch-string))
+ ;; Check that file diff ends with an empty string
+ ;; or the beginning of the next file diff.
+ (string-match-p "\\`\\'\\|\\`diff --git"
+ (substring
+ vc-git-patch-string
+ (+ file-beg (length file-diff)))))
+ (setq vc-git-patch-string
+ (string-replace file-diff "" vc-git-patch-string)))
+ ((string-match (format "^%s" (regexp-quote file-header))
+ vc-git-patch-string)
+ (if (and file-name
+ (yes-or-no-p
+ (format "Unstage already-staged changes to %s?"
+ file-name)))
+ (vc-git-command nil 0 file-name "reset" "-q" "--")
+ (user-error "Index not empty")))
+ (t (push file-name to-stash)))
(setq pos (point))))))
(unless (string-empty-p vc-git-patch-string)
(let ((patch-file (make-nearby-temp-file "git-patch")))
@@ -1047,7 +1116,8 @@ It is based on `log-edit-mode', and has Git-specific extensions."
(insert vc-git-patch-string))
(unwind-protect
(vc-git-command nil 0 patch-file "apply" "--cached")
- (delete-file patch-file)))))
+ (delete-file patch-file))))
+ (when to-stash (vc-git--stash-staged-changes files)))
(cl-flet ((boolean-arg-fn
(argument)
(lambda (value) (when (equal value "yes") (list argument)))))
@@ -1073,7 +1143,58 @@ It is based on `log-edit-mode', and has Git-specific extensions."
args)
(unless vc-git-patch-string
(if only (list "--only" "--") '("-a"))))))
- (if (and msg-file (file-exists-p msg-file)) (delete-file msg-file))))
+ (if (and msg-file (file-exists-p msg-file)) (delete-file msg-file))
+ (when to-stash
+ (let ((cached (make-nearby-temp-file "git-cached")))
+ (unwind-protect
+ (progn (with-temp-file cached
+ (vc-git-command t 0 nil "stash" "show" "-p"))
+ (vc-git-command nil 0 cached "apply" "--cached"))
+ (delete-file cached))
+ (vc-git-command nil 0 nil "stash" "drop")))))
+
+(defun vc-git--stash-staged-changes (files)
+ "Stash only the staged changes to FILES."
+ ;; This is necessary because even if you pass a list of file names
+ ;; to 'git stash push', it will stash any and all staged changes.
+ (unless (zerop
+ (vc-git-command nil t files "diff" "--cached" "--quiet"))
+ (cl-flet
+ ((git-string (&rest args)
+ (string-trim-right
+ (with-output-to-string
+ (apply #'vc-git-command standard-output 0 nil args)))))
+ (let ((cached (make-nearby-temp-file "git-cached"))
+ (message "Previously staged changes")
+ tree)
+ ;; Use a temporary index to create a tree object corresponding
+ ;; to the staged changes to FILES.
+ (unwind-protect
+ (progn
+ (with-temp-file cached
+ (vc-git-command t 0 files "diff" "--cached" "--"))
+ (let* ((index (make-nearby-temp-file "git-index"))
+ (process-environment
+ (cons (format "GIT_INDEX_FILE=%s" index)
+ process-environment)))
+ (unwind-protect
+ (progn
+ (vc-git-command nil 0 nil "read-tree" "HEAD")
+ (vc-git-command nil 0 cached "apply" "--cached")
+ (setq tree (git-string "write-tree")))
+ (delete-file index))))
+ (delete-file cached))
+ ;; Prepare stash commit object, which has a special structure.
+ (let* ((tree-commit (git-string "commit-tree" "-m" message
+ "-p" "HEAD" tree))
+ (stash-commit (git-string "commit-tree" "-m" message
+ "-p" "HEAD" "-p" tree-commit
+ tree)))
+ ;; Push the new stash entry.
+ (vc-git-command nil 0 nil "update-ref" "--create-reflog"
+ "-m" message "refs/stash" stash-commit)
+ ;; Unstage the changes we've now stashed.
+ (vc-git-command nil 0 files "reset" "--"))))))
(defun vc-git-find-revision (file rev buffer)
(let* (process-file-side-effects
@@ -1202,8 +1323,7 @@ This prompts for a branch to merge from."
(completing-read "Merge from branch: "
(if (or (member "FETCH_HEAD" branches)
(not (file-readable-p
- (expand-file-name ".git/FETCH_HEAD"
- root))))
+ (vc-git--git-path "FETCH_HEAD"))))
branches
(cons "FETCH_HEAD" branches))
nil t)))
@@ -1248,8 +1368,7 @@ This prompts for a branch to merge from."
(unless (or
(not (eq vc-git-resolve-conflicts 'unstage-maybe))
;; Doing a merge, so bug#20292 doesn't apply.
- (file-exists-p (expand-file-name ".git/MERGE_HEAD"
- (vc-git-root buffer-file-name)))
+ (file-exists-p (vc-git--git-path "MERGE_HEAD"))
(vc-git-conflicted-files (vc-git-root buffer-file-name)))
(vc-git-command nil 0 nil "reset"))
(vc-resynch-buffer buffer-file-name t t)
@@ -1326,7 +1445,8 @@ If LIMIT is a revision string, use it as an end-revision."
,(format "--pretty=tformat:%s"
(car vc-git-root-log-format))
"--abbrev-commit"))
- (ensure-list vc-git-log-switches)
+ (ensure-list
+ (if shortlog vc-git-shortlog-switches vc-git-log-switches))
(when (numberp limit)
(list "-n" (format "%s" limit)))
(when start-revision
@@ -1341,16 +1461,16 @@ If LIMIT is a revision string, use it as an end-revision."
(defun vc-git-log-outgoing (buffer remote-location)
(vc-setup-buffer buffer)
- (vc-git-command
- buffer 'async nil
- "log"
- "--no-color" "--graph" "--decorate" "--date=short"
- (format "--pretty=tformat:%s" (car vc-git-root-log-format))
- "--abbrev-commit"
- (concat (if (string= remote-location "")
- "@{upstream}"
- remote-location)
- "..HEAD")))
+ (apply #'vc-git-command buffer 'async nil
+ `("log"
+ "--no-color" "--graph" "--decorate" "--date=short"
+ ,(format "--pretty=tformat:%s" (car vc-git-root-log-format))
+ "--abbrev-commit"
+ ,@(ensure-list vc-git-shortlog-switches)
+ ,(concat (if (string= remote-location "")
+ "@{upstream}"
+ remote-location)
+ "..HEAD"))))
(defun vc-git-log-incoming (buffer remote-location)
(vc-setup-buffer buffer)
@@ -1360,15 +1480,15 @@ If LIMIT is a revision string, use it as an end-revision."
;; so remove everything except a repository name.
(replace-regexp-in-string
"/.*" "" remote-location)))
- (vc-git-command
- buffer 'async nil
- "log"
- "--no-color" "--graph" "--decorate" "--date=short"
- (format "--pretty=tformat:%s" (car vc-git-root-log-format))
- "--abbrev-commit"
- (concat "HEAD.." (if (string= remote-location "")
- "@{upstream}"
- remote-location))))
+ (apply #'vc-git-command buffer 'async nil
+ `("log"
+ "--no-color" "--graph" "--decorate" "--date=short"
+ ,(format "--pretty=tformat:%s" (car vc-git-root-log-format))
+ "--abbrev-commit"
+ ,@(ensure-list vc-git-shortlog-switches)
+ ,(concat "HEAD.." (if (string= remote-location "")
+ "@{upstream}"
+ remote-location)))))
(defun vc-git-log-search (buffer pattern)
"Search the log of changes for PATTERN and output results into BUFFER.
@@ -1379,6 +1499,7 @@ Display all entries that match log messages in long format.
With a prefix argument, ask for a command to run that will output
log entries."
(let ((args `("log" "--no-color" "-i"
+ ,@(ensure-list vc-git-log-switches)
,(format "--grep=%s" (or pattern "")))))
(when current-prefix-arg
(setq args (cdr (split-string
@@ -1426,11 +1547,11 @@ log entries."
`((,log-view-message-re (1 'change-log-acknowledgment)))
;; Handle the case:
;; user: foo@bar
- '(("^Author:[ \t]+\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)"
+ '(("^\\(?:Author\\|Commit\\):[ \t]+\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)"
(1 'change-log-email))
;; Handle the case:
;; user: FirstName LastName <foo@bar>
- ("^Author:[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)[>)]"
+ ("^\\(?:Author\\|Commit\\):[ \t]+\\([^<(]+?\\)[ \t]*[(<]\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)[>)]"
(1 'change-log-name)
(2 'change-log-email))
("^ +\\(?:\\(?:[Aa]cked\\|[Ss]igned-[Oo]ff\\)-[Bb]y:\\)[ \t]+\\([A-Za-z0-9_.+-]+@[A-Za-z0-9_.-]+\\)"
@@ -1441,7 +1562,7 @@ log entries."
("^Merge: \\([0-9a-z]+\\) \\([0-9a-z]+\\)"
(1 'change-log-acknowledgment)
(2 'change-log-acknowledgment))
- ("^\\(?:Date: \\|AuthorDate: \\)\\(.+\\)" (1 'change-log-date))
+ ("^\\(?:Date: \\|AuthorDate: \\|CommitDate: \\)\\(.+\\)" (1 'change-log-date))
("^summary:[ \t]+\\(.+\\)" (1 'log-view-message)))))))
@@ -1463,7 +1584,11 @@ or BRANCH^ (where \"^\" can be repeated)."
(defun vc-git-expanded-log-entry (revision)
(with-temp-buffer
- (apply #'vc-git-command t nil nil (list "log" revision "-1" "--no-color" "--"))
+ (apply #'vc-git-command t nil nil
+ `("log"
+ ,revision
+ "-1" "--no-color" ,@(ensure-list vc-git-log-switches)
+ "--"))
(goto-char (point-min))
(unless (eobp)
;; Indent the expanded log entry.
@@ -1662,7 +1787,8 @@ This requires git 1.8.4 or later, for the \"-L\" option of \"git log\"."
(if branchp "branch" "tag"))))
(if branchp
(vc-git-command nil 0 nil "checkout" "-b" name
- (when (and start-point (not (eq start-point "")))
+ (when (and start-point
+ (not (equal start-point "")))
start-point))
(vc-git-command nil 0 nil "tag" name)))))
diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el
index 690c907c77e..130214b840a 100644
--- a/lisp/vc/vc.el
+++ b/lisp/vc/vc.el
@@ -3369,7 +3369,7 @@ If nil, no default will be used. This option may be set locally."
(declare-function message--name-table "message" (orig-string))
(declare-function mml-attach-buffer "mml"
- (buffer &optional type description disposition))
+ (buffer &optional type description disposition filename))
(declare-function log-view-get-marked "log-view" ())
(defun vc-default-prepare-patch (_backend rev)
@@ -3410,6 +3410,19 @@ of the current file."
(and-let* ((file (buffer-file-name)))
(vc-working-revision file)))))
+(defun vc--subject-to-file-name (subject)
+ "Generate a file name for a patch with subject line SUBJECT."
+ (let* ((stripped
+ (replace-regexp-in-string "\\`\\[.*PATCH.*\\]\\s-*" ""
+ subject))
+ (truncated (if (length> stripped 50)
+ (substring stripped 0 50)
+ stripped)))
+ (concat
+ (string-trim (replace-regexp-in-string "\\W" "-" truncated)
+ "-+" "-+")
+ ".patch")))
+
;;;###autoload
(defun vc-prepare-patch (addressee subject revisions)
"Compose an Email sending patches for REVISIONS to ADDRESSEE.
@@ -3420,7 +3433,7 @@ revision, with SUBJECT derived from each revision subject.
When invoked with a numerical prefix argument, use the last N
revisions.
When invoked interactively in a Log View buffer with
-marked revisions, use those these."
+marked revisions, use those."
(interactive
(let ((revs (vc-prepare-patch-prompt-revisions)) to)
(require 'message)
@@ -3466,11 +3479,17 @@ marked revisions, use those these."
(rfc822-goto-eoh)
(forward-line)
(save-excursion
- (dolist (patch patches)
- (mml-attach-buffer (buffer-name (plist-get patch :buffer))
- "text/x-patch"
- (plist-get patch :subject)
- "attachment")))
+ (let ((i 0))
+ (dolist (patch patches)
+ (let* ((patch-subject (plist-get patch :subject))
+ (filename
+ (vc--subject-to-file-name patch-subject)))
+ (mml-attach-buffer
+ (buffer-name (plist-get patch :buffer))
+ "text/x-patch"
+ patch-subject
+ "attachment"
+ (format "%04d-%s" (cl-incf i) filename))))))
(open-line 2)))))
(defun vc-default-responsible-p (_backend _file)
diff --git a/lisp/whitespace.el b/lisp/whitespace.el
index 558be1841ab..7a30274a330 100644
--- a/lisp/whitespace.el
+++ b/lisp/whitespace.el
@@ -1014,34 +1014,11 @@ See also `whitespace-newline' and `whitespace-display-mappings'."
;;;###autoload
-(define-minor-mode global-whitespace-mode
- "Toggle whitespace visualization globally (Global Whitespace mode).
-
-See also `whitespace-style', `whitespace-newline' and
-`whitespace-display-mappings'."
- :lighter " WS"
+(define-globalized-minor-mode global-whitespace-mode
+ whitespace-mode
+ whitespace-turn-on-if-enabled
:init-value nil
- :global t
- :group 'whitespace
- (cond
- (noninteractive ; running a batch job
- (setq global-whitespace-mode nil))
- (global-whitespace-mode ; global-whitespace-mode on
- (save-current-buffer
- (add-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
- (add-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
- (dolist (buffer (buffer-list)) ; adjust all local mode
- (set-buffer buffer)
- (unless whitespace-mode
- (whitespace-turn-on-if-enabled)))))
- (t ; global-whitespace-mode off
- (save-current-buffer
- (remove-hook 'find-file-hook 'whitespace-turn-on-if-enabled)
- (remove-hook 'after-change-major-mode-hook 'whitespace-turn-on-if-enabled)
- (dolist (buffer (buffer-list)) ; adjust all local mode
- (set-buffer buffer)
- (unless whitespace-mode
- (whitespace-turn-off)))))))
+ :group 'whitespace)
(defvar whitespace-enable-predicate
(lambda ()
@@ -1067,7 +1044,7 @@ This variable is normally modified via `add-function'.")
(defun whitespace-turn-on-if-enabled ()
(when (funcall whitespace-enable-predicate)
- (whitespace-turn-on)))
+ (whitespace-mode)))
;;;###autoload
(define-minor-mode global-whitespace-newline-mode
@@ -2511,7 +2488,7 @@ purposes)."
(setq whitespace-display-table-was-local t)
;; Save the old table so we can restore it when
;; `whitespace-mode' is switched off again.
- (when (or whitespace-mode global-whitespace-mode)
+ (when whitespace-mode
(setq whitespace-display-table
(copy-sequence buffer-display-table)))
;; Assure `buffer-display-table' is unique
diff --git a/m4/explicit_bzero.m4 b/m4/explicit_bzero.m4
deleted file mode 100644
index 3b4ef8c3cc5..00000000000
--- a/m4/explicit_bzero.m4
+++ /dev/null
@@ -1,23 +0,0 @@
-dnl Copyright 2017-2022 Free Software Foundation, Inc.
-dnl This file is free software; the Free Software Foundation
-dnl gives unlimited permission to copy and/or distribute it,
-dnl with or without modifications, as long as this notice is preserved.
-
-AC_DEFUN([gl_FUNC_EXPLICIT_BZERO],
-[
- AC_REQUIRE([gl_STRING_H_DEFAULTS])
-
- dnl Persuade glibc <string.h> to declare explicit_bzero.
- AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])
-
- AC_CHECK_FUNCS_ONCE([explicit_bzero])
- if test $ac_cv_func_explicit_bzero = no; then
- HAVE_EXPLICIT_BZERO=0
- fi
-])
-
-AC_DEFUN([gl_PREREQ_EXPLICIT_BZERO],
-[
- AC_CHECK_FUNCS([explicit_memset])
- AC_CHECK_FUNCS_ONCE([memset_s])
-])
diff --git a/m4/gnulib-common.m4 b/m4/gnulib-common.m4
index d17cbec58cb..8f5cc1617ab 100644
--- a/m4/gnulib-common.m4
+++ b/m4/gnulib-common.m4
@@ -105,14 +105,10 @@ AC_DEFUN([gl_COMMON_BODY], [
# define _GL_ATTR_warn_unused_result _GL_GNUC_PREREQ (3, 4)
#endif
-#ifdef __has_c_attribute
-# if ((defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710 \
- && _GL_GNUC_PREREQ (4, 6))
-# pragma GCC diagnostic ignored "-Wpedantic"
-# endif
-# define _GL_HAS_C_ATTRIBUTE(attr) __has_c_attribute (__##attr##__)
-#else
-# define _GL_HAS_C_ATTRIBUTE(attr) 0
+/* Disable GCC -Wpedantic if using __has_c_attribute and this is not C23+. */
+#if (defined __has_c_attribute && _GL_GNUC_PREREQ (4, 6) \
+ && (defined __STDC_VERSION__ ? __STDC_VERSION__ : 0) <= 201710)
+# pragma GCC diagnostic ignored "-Wpedantic"
#endif
]dnl There is no _GL_ATTRIBUTE_ALIGNED; use stdalign's alignas instead.
@@ -202,11 +198,15 @@ AC_DEFUN([gl_COMMON_BODY], [
- enumeration, enumeration item,
- typedef,
in C++ also: namespace, class, template specialization. */
-#if _GL_HAS_C_ATTRIBUTE (deprecated)
-# define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
-#elif _GL_HAS_ATTRIBUTE (deprecated)
+#ifdef __has_c_attribute
+# if __has_c_attribute (__deprecated__)
+# define _GL_ATTRIBUTE_DEPRECATED [[__deprecated__]]
+# endif
+#endif
+#if !defined _GL_ATTRIBUTE_DEPRECATED && _GL_HAS_ATTRIBUTE (deprecated)
# define _GL_ATTRIBUTE_DEPRECATED __attribute__ ((__deprecated__))
-#else
+#endif
+#ifndef _GL_ATTRIBUTE_DEPRECATED
# define _GL_ATTRIBUTE_DEPRECATED
#endif
@@ -240,11 +240,15 @@ AC_DEFUN([gl_COMMON_BODY], [
'default' label. The compiler should not warn in this case. */
/* Applies to: Empty statement (;), inside a 'switch' statement. */
/* Always expands to something. */
-#if _GL_HAS_C_ATTRIBUTE (fallthrough)
-# define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
-#elif _GL_HAS_ATTRIBUTE (fallthrough)
+#ifdef __has_c_attribute
+# if __has_c_attribute (__fallthrough__)
+# define _GL_ATTRIBUTE_FALLTHROUGH [[__fallthrough__]]
+# endif
+#endif
+#if !defined _GL_ATTRIBUTE_FALLTHROUGH && _GL_HAS_ATTRIBUTE (fallthrough)
# define _GL_ATTRIBUTE_FALLTHROUGH __attribute__ ((__fallthrough__))
-#else
+#endif
+#ifndef _GL_ATTRIBUTE_FALLTHROUGH
# define _GL_ATTRIBUTE_FALLTHROUGH ((void) 0)
#endif
@@ -308,9 +312,12 @@ AC_DEFUN([gl_COMMON_BODY], [
/* In C++ and C2x, this is spelled [[__maybe_unused__]].
GCC's syntax is __attribute__ ((__unused__)).
clang supports both syntaxes. */
-#if _GL_HAS_C_ATTRIBUTE (maybe_unused)
-# define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
-#else
+#ifdef __has_c_attribute
+# if __has_c_attribute (__maybe_unused__)
+# define _GL_ATTRIBUTE_MAYBE_UNUSED [[__maybe_unused__]]
+# endif
+#endif
+#ifndef _GL_ATTRIBUTE_MAYBE_UNUSED
# define _GL_ATTRIBUTE_MAYBE_UNUSED _GL_ATTRIBUTE_UNUSED
#endif
/* Alternative spelling of this macro, for convenience and for
@@ -323,11 +330,15 @@ AC_DEFUN([gl_COMMON_BODY], [
discard the return value. The compiler may warn if the caller does not use
the return value, unless the caller uses something like ignore_value. */
/* Applies to: function, enumeration, class. */
-#if _GL_HAS_C_ATTRIBUTE (nodiscard)
-# define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
-#elif _GL_HAS_ATTRIBUTE (warn_unused_result)
+#ifdef __has_c_attribute
+# if __has_c_attribute (__nodiscard__)
+# define _GL_ATTRIBUTE_NODISCARD [[__nodiscard__]]
+# endif
+#endif
+#if !defined _GL_ATTRIBUTE_NODISCARD && _GL_HAS_ATTRIBUTE (warn_unused_result)
# define _GL_ATTRIBUTE_NODISCARD __attribute__ ((__warn_unused_result__))
-#else
+#endif
+#ifndef _GL_ATTRIBUTE_NODISCARD
# define _GL_ATTRIBUTE_NODISCARD
#endif
diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4
index 1a8bf8b7cdf..9ba977711fa 100644
--- a/m4/gnulib-comp.m4
+++ b/m4/gnulib-comp.m4
@@ -82,7 +82,6 @@ AC_DEFUN([gl_EARLY],
# Code from module errno:
# Code from module euidaccess:
# Code from module execinfo:
- # Code from module explicit_bzero:
# Code from module extensions:
# Code from module extern-inline:
# Code from module faccessat:
@@ -137,6 +136,7 @@ AC_DEFUN([gl_EARLY],
# Code from module memmem-simple:
# Code from module mempcpy:
# Code from module memrchr:
+ # Code from module memset_explicit:
# Code from module minmax:
# Code from module mkostemp:
# Code from module mktime:
@@ -285,12 +285,6 @@ AC_DEFUN([gl_INIT],
gl_CONDITIONAL_HEADER([execinfo.h])
AC_PROG_MKDIR_P
gl_CONDITIONAL([GL_COND_OBJ_EXECINFO], [$GL_GENERATE_EXECINFO_H])
- gl_FUNC_EXPLICIT_BZERO
- gl_CONDITIONAL([GL_COND_OBJ_EXPLICIT_BZERO], [test $HAVE_EXPLICIT_BZERO = 0])
- AM_COND_IF([GL_COND_OBJ_EXPLICIT_BZERO], [
- gl_PREREQ_EXPLICIT_BZERO
- ])
- gl_STRING_MODULE_INDICATOR([explicit_bzero])
AC_REQUIRE([gl_EXTERN_INLINE])
gl_FUNC_FACCESSAT
gl_CONDITIONAL([GL_COND_OBJ_FACCESSAT],
@@ -422,6 +416,12 @@ AC_DEFUN([gl_INIT],
gl_PREREQ_MEMRCHR
])
gl_STRING_MODULE_INDICATOR([memrchr])
+ gl_FUNC_MEMSET_EXPLICIT
+ gl_CONDITIONAL([GL_COND_OBJ_MEMSET_EXPLICIT], [test $HAVE_MEMSET_EXPLICIT = 0])
+ AM_COND_IF([GL_COND_OBJ_MEMSET_EXPLICIT], [
+ gl_PREREQ_MEMSET_EXPLICIT
+ ])
+ gl_STRING_MODULE_INDICATOR([memset_explicit])
gl_MINMAX
gl_FUNC_MKOSTEMP
gl_CONDITIONAL([GL_COND_OBJ_MKOSTEMP], [test $HAVE_MKOSTEMP = 0])
@@ -1248,7 +1248,6 @@ AC_DEFUN([gl_FILE_LIST], [
lib/euidaccess.c
lib/execinfo.c
lib/execinfo.in.h
- lib/explicit_bzero.c
lib/faccessat.c
lib/fchmodat.c
lib/fcntl.c
@@ -1318,6 +1317,7 @@ AC_DEFUN([gl_FILE_LIST], [
lib/memmem.c
lib/mempcpy.c
lib/memrchr.c
+ lib/memset_explicit.c
lib/mini-gmp-gnulib.c
lib/mini-gmp.c
lib/mini-gmp.h
@@ -1432,7 +1432,6 @@ AC_DEFUN([gl_FILE_LIST], [
m4/errno_h.m4
m4/euidaccess.m4
m4/execinfo.m4
- m4/explicit_bzero.m4
m4/extensions.m4
m4/extern-inline.m4
m4/faccessat.m4
@@ -1476,6 +1475,7 @@ AC_DEFUN([gl_FILE_LIST], [
m4/memmem.m4
m4/mempcpy.m4
m4/memrchr.m4
+ m4/memset_explicit.m4
m4/minmax.m4
m4/mkostemp.m4
m4/mktime.m4
diff --git a/m4/memset_explicit.m4 b/m4/memset_explicit.m4
new file mode 100644
index 00000000000..3d4dcb30955
--- /dev/null
+++ b/m4/memset_explicit.m4
@@ -0,0 +1,20 @@
+dnl Copyright 2022 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_MEMSET_EXPLICIT],
+[
+ AC_REQUIRE([gl_STRING_H_DEFAULTS])
+
+ AC_CHECK_FUNCS_ONCE([memset_explicit])
+ if test $ac_cv_func_memset_explicit = no; then
+ HAVE_MEMSET_EXPLICIT=0
+ fi
+])
+
+AC_DEFUN([gl_PREREQ_MEMSET_EXPLICIT],
+[
+ AC_CHECK_FUNCS([explicit_memset])
+ AC_CHECK_FUNCS_ONCE([memset_s])
+])
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index 9e09b96e165..6069d4a7523 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -5,7 +5,7 @@
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
-# serial 34
+# serial 35
# Written by Paul Eggert.
@@ -21,7 +21,8 @@ AC_DEFUN_ONCE([gl_STRING_H],
dnl guaranteed by C89.
gl_WARN_ON_USE_PREPARE([[#include <string.h>
]],
- [ffsl ffsll memmem mempcpy memrchr rawmemchr stpcpy stpncpy strchrnul
+ [explicit_bzero ffsl ffsll memmem mempcpy memrchr memset_explicit
+ rawmemchr stpcpy stpncpy strchrnul
strdup strncat strndup strnlen strpbrk strsep strcasestr strtok_r
strerror_r strerrorname_np sigabbrev_np sigdescr_np strsignal strverscmp])
@@ -54,6 +55,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS],
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMMEM])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMPCPY])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMRCHR])
+ gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MEMSET_EXPLICIT])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_RAWMEMCHR])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STPCPY])
gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STPNCPY])
@@ -107,6 +109,7 @@ AC_DEFUN([gl_STRING_H_DEFAULTS],
HAVE_FFSLL=1; AC_SUBST([HAVE_FFSLL])
HAVE_DECL_MEMMEM=1; AC_SUBST([HAVE_DECL_MEMMEM])
HAVE_MEMPCPY=1; AC_SUBST([HAVE_MEMPCPY])
+ HAVE_MEMSET_EXPLICIT=1; AC_SUBST([HAVE_MEMSET_EXPLICIT])
HAVE_DECL_MEMRCHR=1; AC_SUBST([HAVE_DECL_MEMRCHR])
HAVE_RAWMEMCHR=1; AC_SUBST([HAVE_RAWMEMCHR])
HAVE_STPCPY=1; AC_SUBST([HAVE_STPCPY])
diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp
index 4abea2ec597..9e178ac1435 100644
--- a/msdos/sed2v2.inp
+++ b/msdos/sed2v2.inp
@@ -67,7 +67,7 @@
/^#undef PACKAGE_NAME/s/^.*$/#define PACKAGE_NAME ""/
/^#undef PACKAGE_STRING/s/^.*$/#define PACKAGE_STRING ""/
/^#undef PACKAGE_TARNAME/s/^.*$/#define PACKAGE_TARNAME ""/
-/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "29.0.60"/
+/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "30.0.50"/
/^#undef SYSTEM_TYPE/s/^.*$/#define SYSTEM_TYPE "ms-dos"/
/^#undef HAVE_DECL_GETENV/s/^.*$/#define HAVE_DECL_GETENV 1/
/^#undef SYS_SIGLIST_DECLARED/s/^.*$/#define SYS_SIGLIST_DECLARED 1/
diff --git a/nt/README.W32 b/nt/README.W32
index 840da905dab..30f33ca706f 100644
--- a/nt/README.W32
+++ b/nt/README.W32
@@ -1,7 +1,7 @@
Copyright (C) 2001-2022 Free Software Foundation, Inc.
See the end of the file for license conditions.
- Emacs version 29.0.60 for MS-Windows
+ Emacs version 30.0.50 for MS-Windows
This README file describes how to set up and run a precompiled
distribution of the latest version of GNU Emacs for MS-Windows. You
diff --git a/src/alloc.c b/src/alloc.c
index 9a7c759dc1d..e7edc0595b3 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -80,6 +80,37 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <valgrind/memcheck.h>
#endif
+/* AddressSanitizer exposes additional functions for manually marking
+ memory as poisoned/unpoisoned. When ASan is enabled and the needed
+ header is available, memory is poisoned when:
+
+ * An ablock is freed (lisp_align_free), or ablocks are initially
+ allocated (lisp_align_malloc).
+ * An interval_block is initially allocated (make_interval).
+ * A dead INTERVAL is put on the interval free list
+ (sweep_intervals).
+ * A sdata is marked as dead (sweep_strings, pin_string).
+ * An sblock is initially allocated (allocate_string_data).
+ * A string_block is initially allocated (allocate_string).
+ * A dead string is put on string_free_list (sweep_strings).
+ * A float_block is initially allocated (make_float).
+ * A dead float is put on float_free_list.
+ * A cons_block is initially allocated (Fcons).
+ * A dead cons is put on cons_free_list (sweep_cons).
+ * A dead vector is put on vector_free_list (setup_on_free_list),
+ or a new vector block is allocated (allocate_vector_from_block).
+ Accordingly, objects reused from the free list are unpoisoned.
+
+ This feature can be disabled wtih the run-time flag
+ `allow_user_poisoning' set to zero. */
+#if ADDRESS_SANITIZER && defined HAVE_SANITIZER_ASAN_INTERFACE_H \
+ && !defined GC_ASAN_POISON_OBJECTS
+# define GC_ASAN_POISON_OBJECTS 1
+# include <sanitizer/asan_interface.h>
+#else
+# define GC_ASAN_POISON_OBJECTS 0
+#endif
+
/* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects.
We turn that on by default when ENABLE_CHECKING is defined;
define GC_CHECK_MARKED_OBJECTS to zero to disable. */
@@ -1157,6 +1188,16 @@ struct ablocks
(1 & (intptr_t) ABLOCKS_BUSY (abase) ? abase : ((void **) (abase))[-1])
#endif
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_ABLOCK(b) \
+ __asan_poison_memory_region (&(b)->x, sizeof ((b)->x))
+# define ASAN_UNPOISON_ABLOCK(b) \
+ __asan_unpoison_memory_region (&(b)->x, sizeof ((b)->x))
+#else
+# define ASAN_POISON_ABLOCK(b) ((void) 0)
+# define ASAN_UNPOISON_ABLOCK(b) ((void) 0)
+#endif
+
/* The list of free ablock. */
static struct ablock *free_ablock;
@@ -1235,6 +1276,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
{
abase->blocks[i].abase = abase;
abase->blocks[i].x.next_free = free_ablock;
+ ASAN_POISON_ABLOCK (&abase->blocks[i]);
free_ablock = &abase->blocks[i];
}
intptr_t ialigned = aligned;
@@ -1247,6 +1289,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type)
eassert ((intptr_t) ABLOCKS_BUSY (abase) == aligned);
}
+ ASAN_UNPOISON_ABLOCK (free_ablock);
abase = ABLOCK_ABASE (free_ablock);
ABLOCKS_BUSY (abase)
= (struct ablocks *) (2 + (intptr_t) ABLOCKS_BUSY (abase));
@@ -1278,6 +1321,7 @@ lisp_align_free (void *block)
#endif
/* Put on free list. */
ablock->x.next_free = free_ablock;
+ ASAN_POISON_ABLOCK (ablock);
free_ablock = ablock;
/* Update busy count. */
intptr_t busy = (intptr_t) ABLOCKS_BUSY (abase) - 2;
@@ -1290,9 +1334,12 @@ lisp_align_free (void *block)
bool aligned = busy;
struct ablock **tem = &free_ablock;
struct ablock *atop = &abase->blocks[aligned ? ABLOCKS_SIZE : ABLOCKS_SIZE - 1];
-
while (*tem)
{
+#if GC_ASAN_POISON_OBJECTS
+ __asan_unpoison_memory_region (&(*tem)->x,
+ sizeof ((*tem)->x));
+#endif
if (*tem >= (struct ablock *) abase && *tem < atop)
{
i++;
@@ -1421,6 +1468,24 @@ static int interval_block_index = INTERVAL_BLOCK_SIZE;
static INTERVAL interval_free_list;
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_INTERVAL_BLOCK(b) \
+ __asan_poison_memory_region ((b)->intervals, \
+ sizeof ((b)->intervals))
+# define ASAN_UNPOISON_INTERVAL_BLOCK(b) \
+ __asan_unpoison_memory_region ((b)->intervals, \
+ sizeof ((b)->intervals))
+# define ASAN_POISON_INTERVAL(i) \
+ __asan_poison_memory_region ((i), sizeof (*(i)))
+# define ASAN_UNPOISON_INTERVAL(i) \
+ __asan_unpoison_memory_region ((i), sizeof (*(i)))
+#else
+# define ASAN_POISON_INTERVAL_BLOCK(b) ((void) 0)
+# define ASAN_UNPOISON_INTERVAL_BLOCK(b) ((void) 0)
+# define ASAN_POISON_INTERVAL(i) ((void) 0)
+# define ASAN_UNPOISON_INTERVAL(i) ((void) 0)
+#endif
+
/* Return a new interval. */
INTERVAL
@@ -1433,6 +1498,7 @@ make_interval (void)
if (interval_free_list)
{
val = interval_free_list;
+ ASAN_UNPOISON_INTERVAL (val);
interval_free_list = INTERVAL_PARENT (interval_free_list);
}
else
@@ -1443,10 +1509,12 @@ make_interval (void)
= lisp_malloc (sizeof *newi, false, MEM_TYPE_NON_LISP);
newi->next = interval_block;
+ ASAN_POISON_INTERVAL_BLOCK (newi);
interval_block = newi;
interval_block_index = 0;
}
val = &interval_block->intervals[interval_block_index++];
+ ASAN_UNPOISON_INTERVAL (val);
}
MALLOC_UNBLOCK_INPUT;
@@ -1687,6 +1755,41 @@ init_strings (void)
staticpro (&empty_multibyte_string);
}
+#if GC_ASAN_POISON_OBJECTS
+/* Prepare s for denoting a free sdata struct, i.e, poison all bytes
+ in the flexible array member, except the first SDATA_OFFSET bytes.
+ This is only effective for strings of size n where n > sdata_size(n).
+ */
+# define ASAN_PREPARE_DEAD_SDATA(s, size) \
+ do { \
+ __asan_poison_memory_region ((s), sdata_size ((size))); \
+ __asan_unpoison_memory_region (&(((s))->string), \
+ sizeof (struct Lisp_String *)); \
+ __asan_unpoison_memory_region (&SDATA_NBYTES ((s)), \
+ sizeof (SDATA_NBYTES ((s)))); \
+ } while (false)
+/* Prepare s for storing string data for NBYTES bytes. */
+# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) \
+ __asan_unpoison_memory_region ((s), sdata_size ((nbytes)))
+# define ASAN_POISON_SBLOCK_DATA(b, size) \
+ __asan_poison_memory_region ((b)->data, (size))
+# define ASAN_POISON_STRING_BLOCK(b) \
+ __asan_poison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
+# define ASAN_UNPOISON_STRING_BLOCK(b) \
+ __asan_unpoison_memory_region ((b)->strings, STRING_BLOCK_SIZE)
+# define ASAN_POISON_STRING(s) \
+ __asan_poison_memory_region ((s), sizeof (*(s)))
+# define ASAN_UNPOISON_STRING(s) \
+ __asan_unpoison_memory_region ((s), sizeof (*(s)))
+#else
+# define ASAN_PREPARE_DEAD_SDATA(s, size) ((void) 0)
+# define ASAN_PREPARE_LIVE_SDATA(s, nbytes) ((void) 0)
+# define ASAN_POISON_SBLOCK_DATA(b, size) ((void) 0)
+# define ASAN_POISON_STRING_BLOCK(b) ((void) 0)
+# define ASAN_UNPOISON_STRING_BLOCK(b) ((void) 0)
+# define ASAN_POISON_STRING(s) ((void) 0)
+# define ASAN_UNPOISON_STRING(s) ((void) 0)
+#endif
#ifdef GC_CHECK_STRING_BYTES
@@ -1805,12 +1908,14 @@ allocate_string (void)
NEXT_FREE_LISP_STRING (s) = string_free_list;
string_free_list = s;
}
+ ASAN_POISON_STRING_BLOCK (b);
}
check_string_free_list ();
/* Pop a Lisp_String off the free-list. */
s = string_free_list;
+ ASAN_UNPOISON_STRING (s);
string_free_list = NEXT_FREE_LISP_STRING (s);
MALLOC_UNBLOCK_INPUT;
@@ -1870,6 +1975,7 @@ allocate_string_data (struct Lisp_String *s,
#endif
b = lisp_malloc (size + GC_STRING_EXTRA, clearit, MEM_TYPE_NON_LISP);
+ ASAN_POISON_SBLOCK_DATA (b, size);
#ifdef DOUG_LEA_MALLOC
if (!mmap_lisp_allowed_p ())
@@ -1891,6 +1997,8 @@ allocate_string_data (struct Lisp_String *s,
{
/* Not enough room in the current sblock. */
b = lisp_malloc (SBLOCK_SIZE, false, MEM_TYPE_NON_LISP);
+ ASAN_POISON_SBLOCK_DATA (b, SBLOCK_SIZE);
+
data = b->data;
b->next = NULL;
b->next_free = data;
@@ -1903,10 +2011,19 @@ allocate_string_data (struct Lisp_String *s,
}
data = b->next_free;
+
if (clearit)
- memset (SDATA_DATA (data), 0, nbytes);
+ {
+#if GC_ASAN_POISON_OBJECTS
+ /* We are accessing SDATA_DATA (data) before it gets
+ * normally unpoisoned, so do it manually. */
+ __asan_unpoison_memory_region (SDATA_DATA (data), nbytes);
+#endif
+ memset (SDATA_DATA (data), 0, nbytes);
+ }
}
+ ASAN_PREPARE_LIVE_SDATA (data, nbytes);
data->string = s;
b->next_free = (sdata *) ((char *) data + needed + GC_STRING_EXTRA);
eassert ((uintptr_t) b->next_free % alignof (sdata) == 0);
@@ -1998,12 +2115,16 @@ sweep_strings (void)
int i, nfree = 0;
struct Lisp_String *free_list_before = string_free_list;
+ ASAN_UNPOISON_STRING_BLOCK (b);
+
next = b->next;
for (i = 0; i < STRING_BLOCK_SIZE; ++i)
{
struct Lisp_String *s = b->strings + i;
+ ASAN_UNPOISON_STRING (s);
+
if (s->u.s.data)
{
/* String was not on free-list before. */
@@ -2040,6 +2161,8 @@ sweep_strings (void)
/* Put the string on the free-list. */
NEXT_FREE_LISP_STRING (s) = string_free_list;
+ ASAN_POISON_STRING (s);
+ ASAN_PREPARE_DEAD_SDATA (data, SDATA_NBYTES (data));
string_free_list = s;
++nfree;
}
@@ -2048,6 +2171,8 @@ sweep_strings (void)
{
/* S was on the free-list before. Put it there again. */
NEXT_FREE_LISP_STRING (s) = string_free_list;
+ ASAN_POISON_STRING (s);
+
string_free_list = s;
++nfree;
}
@@ -2174,6 +2299,7 @@ compact_small_strings (void)
if (from != to)
{
eassert (tb != b || to < from);
+ ASAN_PREPARE_LIVE_SDATA (to, nbytes);
memmove (to, from, size + GC_STRING_EXTRA);
to->string->u.s.data = SDATA_DATA (to);
}
@@ -2525,6 +2651,7 @@ pin_string (Lisp_Object string)
memcpy (s->u.s.data, data, size);
old_sdata->string = NULL;
SDATA_NBYTES (old_sdata) = size;
+ ASAN_PREPARE_DEAD_SDATA (old_sdata, size);
}
s->u.s.size_byte = -3;
}
@@ -2582,6 +2709,24 @@ struct float_block
#define XFLOAT_UNMARK(fptr) \
UNSETMARKBIT (FLOAT_BLOCK (fptr), FLOAT_INDEX ((fptr)))
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_FLOAT_BLOCK(fblk) \
+ __asan_poison_memory_region ((fblk)->floats, \
+ sizeof ((fblk)->floats))
+# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) \
+ __asan_unpoison_memory_region ((fblk)->floats, \
+ sizeof ((fblk)->floats))
+# define ASAN_POISON_FLOAT(p) \
+ __asan_poison_memory_region ((p), sizeof (struct Lisp_Float))
+# define ASAN_UNPOISON_FLOAT(p) \
+ __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Float))
+#else
+# define ASAN_POISON_FLOAT_BLOCK(fblk) ((void) 0)
+# define ASAN_UNPOISON_FLOAT_BLOCK(fblk) ((void) 0)
+# define ASAN_POISON_FLOAT(p) ((void) 0)
+# define ASAN_UNPOISON_FLOAT(p) ((void) 0)
+#endif
+
/* Current float_block. */
static struct float_block *float_block;
@@ -2606,6 +2751,7 @@ make_float (double float_value)
if (float_free_list)
{
XSETFLOAT (val, float_free_list);
+ ASAN_UNPOISON_FLOAT (float_free_list);
float_free_list = float_free_list->u.chain;
}
else
@@ -2616,9 +2762,11 @@ make_float (double float_value)
= lisp_align_malloc (sizeof *new, MEM_TYPE_FLOAT);
new->next = float_block;
memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
+ ASAN_POISON_FLOAT_BLOCK (new);
float_block = new;
float_block_index = 0;
}
+ ASAN_UNPOISON_FLOAT (&float_block->floats[float_block_index]);
XSETFLOAT (val, &float_block->floats[float_block_index]);
float_block_index++;
}
@@ -2690,6 +2838,19 @@ static int cons_block_index = CONS_BLOCK_SIZE;
static struct Lisp_Cons *cons_free_list;
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_CONS_BLOCK(b) \
+ __asan_poison_memory_region ((b)->conses, sizeof ((b)->conses))
+# define ASAN_POISON_CONS(p) \
+ __asan_poison_memory_region ((p), sizeof (struct Lisp_Cons))
+# define ASAN_UNPOISON_CONS(p) \
+ __asan_unpoison_memory_region ((p), sizeof (struct Lisp_Cons))
+#else
+# define ASAN_POISON_CONS_BLOCK(b) ((void) 0)
+# define ASAN_POISON_CONS(p) ((void) 0)
+# define ASAN_UNPOISON_CONS(p) ((void) 0)
+#endif
+
/* Explicitly free a cons cell by putting it on the free-list. */
void
@@ -2700,6 +2861,7 @@ free_cons (struct Lisp_Cons *ptr)
cons_free_list = ptr;
ptrdiff_t nbytes = sizeof *ptr;
tally_consing (-nbytes);
+ ASAN_POISON_CONS (ptr);
}
DEFUN ("cons", Fcons, Scons, 2, 2, 0,
@@ -2712,6 +2874,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
if (cons_free_list)
{
+ ASAN_UNPOISON_CONS (cons_free_list);
XSETCONS (val, cons_free_list);
cons_free_list = cons_free_list->u.s.u.chain;
}
@@ -2722,10 +2885,12 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0,
struct cons_block *new
= lisp_align_malloc (sizeof *new, MEM_TYPE_CONS);
memset (new->gcmarkbits, 0, sizeof new->gcmarkbits);
+ ASAN_POISON_CONS_BLOCK (new);
new->next = cons_block;
cons_block = new;
cons_block_index = 0;
}
+ ASAN_UNPOISON_CONS (&cons_block->conses[cons_block_index]);
XSETCONS (val, &cons_block->conses[cons_block_index]);
cons_block_index++;
}
@@ -2980,6 +3145,19 @@ static struct large_vector *large_vectors;
Lisp_Object zero_vector;
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) \
+ __asan_poison_memory_region ((v)->contents, (bytes))
+# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) \
+ __asan_unpoison_memory_region ((v)->contents, (bytes))
+# define ASAN_UNPOISON_VECTOR_BLOCK(b) \
+ __asan_unpoison_memory_region ((b)->data, sizeof ((b)->data))
+#else
+# define ASAN_POISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
+# define ASAN_UNPOISON_VECTOR_CONTENTS(v, bytes) ((void) 0)
+# define ASAN_UNPOISON_VECTOR_BLOCK(b) ((void) 0)
+#endif
+
/* Common shortcut to setup vector on a free list. */
static void
@@ -2992,6 +3170,7 @@ setup_on_free_list (struct Lisp_Vector *v, ptrdiff_t nbytes)
ptrdiff_t vindex = VINDEX (nbytes);
eassert (vindex < VECTOR_MAX_FREE_LIST_INDEX);
set_next_vector (v, vector_free_lists[vindex]);
+ ASAN_POISON_VECTOR_CONTENTS (v, nbytes - header_size);
vector_free_lists[vindex] = v;
}
@@ -3039,6 +3218,7 @@ allocate_vector_from_block (ptrdiff_t nbytes)
if (vector_free_lists[index])
{
vector = vector_free_lists[index];
+ ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
vector_free_lists[index] = next_vector (vector);
return vector;
}
@@ -3052,12 +3232,18 @@ allocate_vector_from_block (ptrdiff_t nbytes)
{
/* This vector is larger than requested. */
vector = vector_free_lists[index];
+ ASAN_UNPOISON_VECTOR_CONTENTS (vector, nbytes - header_size);
vector_free_lists[index] = next_vector (vector);
/* Excess bytes are used for the smaller vector,
which should be set on an appropriate free list. */
restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes;
eassert (restbytes % roundup_size == 0);
+#if GC_ASAN_POISON_OBJECTS
+ /* Ensure that accessing excess bytes does not trigger ASan. */
+ __asan_unpoison_memory_region (ADVANCE (vector, nbytes),
+ restbytes);
+#endif
setup_on_free_list (ADVANCE (vector, nbytes), restbytes);
return vector;
}
@@ -3233,6 +3419,7 @@ sweep_vectors (void)
for (vector = (struct Lisp_Vector *) block->data;
VECTOR_IN_BLOCK (vector, block); vector = next)
{
+ ASAN_UNPOISON_VECTOR_BLOCK (block);
if (XVECTOR_MARKED_P (vector))
{
XUNMARK_VECTOR (vector);
@@ -3608,6 +3795,23 @@ struct symbol_block
struct symbol_block *next;
};
+#if GC_ASAN_POISON_OBJECTS
+# define ASAN_POISON_SYMBOL_BLOCK(s) \
+ __asan_poison_memory_region ((s)->symbols, sizeof ((s)->symbols))
+# define ASAN_UNPOISON_SYMBOL_BLOCK(s) \
+ __asan_unpoison_memory_region ((s)->symbols, sizeof ((s)->symbols))
+# define ASAN_POISON_SYMBOL(sym) \
+ __asan_poison_memory_region ((sym), sizeof (*(sym)))
+# define ASAN_UNPOISON_SYMBOL(sym) \
+ __asan_unpoison_memory_region ((sym), sizeof (*(sym)))
+
+#else
+# define ASAN_POISON_SYMBOL_BLOCK(s) ((void) 0)
+# define ASAN_UNPOISON_SYMBOL_BLOCK(s) ((void) 0)
+# define ASAN_POISON_SYMBOL(sym) ((void) 0)
+# define ASAN_UNPOISON_SYMBOL(sym) ((void) 0)
+#endif
+
/* Current symbol block and index of first unused Lisp_Symbol
structure in it. */
@@ -3661,6 +3865,7 @@ Its value is void, and its function definition and property list are nil. */)
if (symbol_free_list)
{
+ ASAN_UNPOISON_SYMBOL (symbol_free_list);
XSETSYMBOL (val, symbol_free_list);
symbol_free_list = symbol_free_list->u.s.next;
}
@@ -3670,10 +3875,13 @@ Its value is void, and its function definition and property list are nil. */)
{
struct symbol_block *new
= lisp_malloc (sizeof *new, false, MEM_TYPE_SYMBOL);
+ ASAN_POISON_SYMBOL_BLOCK (new);
new->next = symbol_block;
symbol_block = new;
symbol_block_index = 0;
}
+
+ ASAN_UNPOISON_SYMBOL (&symbol_block->symbols[symbol_block_index]);
XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]);
symbol_block_index++;
}
@@ -4561,6 +4769,11 @@ static struct Lisp_String *
live_string_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_STRING);
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_address_is_poisoned (p))
+ return NULL;
+#endif
+
struct string_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->strings[0];
@@ -4577,6 +4790,10 @@ live_string_holding (struct mem_node *m, void *p)
|| off == offsetof (struct Lisp_String, u.s.data))
{
struct Lisp_String *s = p = cp -= off;
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_region_is_poisoned (s, sizeof (*s)))
+ return NULL;
+#endif
if (s->u.s.data)
return s;
}
@@ -4598,6 +4815,11 @@ static struct Lisp_Cons *
live_cons_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_CONS);
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_address_is_poisoned (p))
+ return NULL;
+#endif
+
struct cons_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->conses[0];
@@ -4615,6 +4837,10 @@ live_cons_holding (struct mem_node *m, void *p)
|| off == offsetof (struct Lisp_Cons, u.s.u.cdr))
{
struct Lisp_Cons *s = p = cp -= off;
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_region_is_poisoned (s, sizeof (*s)))
+ return NULL;
+#endif
if (!deadp (s->u.s.car))
return s;
}
@@ -4637,6 +4863,10 @@ static struct Lisp_Symbol *
live_symbol_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_SYMBOL);
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_address_is_poisoned (p))
+ return NULL;
+#endif
struct symbol_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->symbols[0];
@@ -4662,6 +4892,10 @@ live_symbol_holding (struct mem_node *m, void *p)
|| off == offsetof (struct Lisp_Symbol, u.s.next))
{
struct Lisp_Symbol *s = p = cp -= off;
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_region_is_poisoned (s, sizeof (*s)))
+ return NULL;
+#endif
if (!deadp (s->u.s.function))
return s;
}
@@ -4684,6 +4918,11 @@ static struct Lisp_Float *
live_float_holding (struct mem_node *m, void *p)
{
eassert (m->type == MEM_TYPE_FLOAT);
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_address_is_poisoned (p))
+ return NULL;
+#endif
+
struct float_block *b = m->start;
char *cp = p;
ptrdiff_t offset = cp - (char *) &b->floats[0];
@@ -4698,8 +4937,12 @@ live_float_holding (struct mem_node *m, void *p)
&& (b != float_block
|| offset / sizeof b->floats[0] < float_block_index))
{
- p = cp - off;
- return p;
+ struct Lisp_Float *f = (struct Lisp_Float *) (cp - off);
+#if GC_ASAN_POISON_OBJECTS
+ if (__asan_region_is_poisoned (f, sizeof (*f)))
+ return NULL;
+#endif
+ return f;
}
}
return NULL;
@@ -6221,6 +6464,7 @@ garbage_collect (void)
#ifdef HAVE_X_WINDOWS
mark_xterm ();
+ mark_xselect ();
#endif
#ifdef HAVE_NS
@@ -6554,7 +6798,7 @@ mark_buffer (struct buffer *buffer)
if (!BUFFER_LIVE_P (buffer))
mark_object (BVAR (buffer, undo_list));
- if (buffer->overlays)
+ if (!itree_empty_p (buffer->overlays))
mark_overlays (buffer->overlays->root);
/* If this is an indirect buffer, mark its base buffer. */
@@ -7180,11 +7424,13 @@ sweep_conses (void)
struct Lisp_Cons *acons = &cblk->conses[pos];
if (!XCONS_MARKED_P (acons))
{
+ ASAN_UNPOISON_CONS (&cblk->conses[pos]);
this_free++;
cblk->conses[pos].u.s.u.chain = cons_free_list;
cons_free_list = &cblk->conses[pos];
cons_free_list->u.s.car = dead_object ();
- }
+ ASAN_POISON_CONS (&cblk->conses[pos]);
+ }
else
{
num_used++;
@@ -7202,6 +7448,7 @@ sweep_conses (void)
{
*cprev = cblk->next;
/* Unhook from the free list. */
+ ASAN_UNPOISON_CONS (&cblk->conses[0]);
cons_free_list = cblk->conses[0].u.s.u.chain;
lisp_align_free (cblk);
}
@@ -7228,6 +7475,7 @@ sweep_floats (void)
for (struct float_block *fblk; (fblk = *fprev); )
{
int this_free = 0;
+ ASAN_UNPOISON_FLOAT_BLOCK (fblk);
for (int i = 0; i < lim; i++)
{
struct Lisp_Float *afloat = &fblk->floats[i];
@@ -7235,6 +7483,7 @@ sweep_floats (void)
{
this_free++;
fblk->floats[i].u.chain = float_free_list;
+ ASAN_POISON_FLOAT (&fblk->floats[i]);
float_free_list = &fblk->floats[i];
}
else
@@ -7251,7 +7500,8 @@ sweep_floats (void)
{
*fprev = fblk->next;
/* Unhook from the free list. */
- float_free_list = fblk->floats[0].u.chain;
+ ASAN_UNPOISON_FLOAT (&fblk->floats[0]);
+ float_free_list = fblk->floats[0].u.chain;
lisp_align_free (fblk);
}
else
@@ -7277,13 +7527,14 @@ sweep_intervals (void)
for (struct interval_block *iblk; (iblk = *iprev); )
{
int this_free = 0;
-
+ ASAN_UNPOISON_INTERVAL_BLOCK (iblk);
for (int i = 0; i < lim; i++)
{
if (!iblk->intervals[i].gcmarkbit)
{
set_interval_parent (&iblk->intervals[i], interval_free_list);
interval_free_list = &iblk->intervals[i];
+ ASAN_POISON_INTERVAL (&iblk->intervals[i]);
this_free++;
}
else
@@ -7300,6 +7551,7 @@ sweep_intervals (void)
{
*iprev = iblk->next;
/* Unhook from the free list. */
+ ASAN_UNPOISON_INTERVAL (&iblk->intervals[0]);
interval_free_list = INTERVAL_PARENT (&iblk->intervals[0]);
lisp_free (iblk);
}
@@ -7329,6 +7581,8 @@ sweep_symbols (void)
for (sblk = symbol_block; sblk; sblk = *sprev)
{
+ ASAN_UNPOISON_SYMBOL_BLOCK (sblk);
+
int this_free = 0;
struct Lisp_Symbol *sym = sblk->symbols;
struct Lisp_Symbol *end = sym + lim;
@@ -7350,7 +7604,8 @@ sweep_symbols (void)
sym->u.s.next = symbol_free_list;
symbol_free_list = sym;
symbol_free_list->u.s.function = dead_object ();
- ++this_free;
+ ASAN_POISON_SYMBOL (sym);
+ ++this_free;
}
else
{
@@ -7369,6 +7624,7 @@ sweep_symbols (void)
{
*sprev = sblk->next;
/* Unhook from the free list. */
+ ASAN_UNPOISON_SYMBOL (&sblk->symbols[0]);
symbol_free_list = sblk->symbols[0].u.s.next;
lisp_free (sblk);
}
diff --git a/src/buffer.h b/src/buffer.h
index 80b3fd81e09..7c3d1903140 100644
--- a/src/buffer.h
+++ b/src/buffer.h
@@ -1266,8 +1266,7 @@ set_buffer_intervals (struct buffer *b, INTERVAL i)
INLINE bool
buffer_has_overlays (void)
{
- return current_buffer->overlays
- && (current_buffer->overlays->root != NULL);
+ return !itree_empty_p (current_buffer->overlays);
}
/* Functions for accessing a character or byte,
diff --git a/src/data.c b/src/data.c
index c6b85e17bc2..7ad06a9faa5 100644
--- a/src/data.c
+++ b/src/data.c
@@ -2619,6 +2619,7 @@ bool-vector. IDX starts at 0. */)
}
else if (RECORDP (array))
{
+ CHECK_IMPURE (array, XVECTOR (array));
if (idxval < 0 || idxval >= PVSIZE (array))
args_out_of_range (array, idx);
ASET (array, idxval, newelt);
diff --git a/src/dispnew.c b/src/dispnew.c
index 5a9ba8909e3..b845acdcbc4 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3188,7 +3188,7 @@ DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
- if (FRAME_VISIBLE_P (XFRAME (frame)))
+ if (FRAME_REDISPLAY_P (XFRAME (frame)))
redraw_frame (XFRAME (frame));
return Qnil;
diff --git a/src/emacs-module.h.in b/src/emacs-module.h.in
index 22096db7e85..c51d482d8a2 100644
--- a/src/emacs-module.h.in
+++ b/src/emacs-module.h.in
@@ -183,6 +183,21 @@ struct emacs_env_29
@module_env_snippet_29@
};
+struct emacs_env_30
+{
+@module_env_snippet_25@
+
+@module_env_snippet_26@
+
+@module_env_snippet_27@
+
+@module_env_snippet_28@
+
+@module_env_snippet_29@
+
+@module_env_snippet_30@
+};
+
/* Every module should define a function as follows. */
extern int emacs_module_init (struct emacs_runtime *runtime)
EMACS_NOEXCEPT
diff --git a/src/eval.c b/src/eval.c
index 99f3650fc9b..cff4b924778 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1367,7 +1367,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
error ("Invalid condition handler: %s",
SDATA (Fprin1_to_string (tem, Qt, Qnil)));
if (CONSP (tem) && EQ (XCAR (tem), QCsuccess))
- success_handler = XCDR (tem);
+ success_handler = tem;
else
clausenb++;
}
@@ -1430,7 +1430,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
if (!NILP (success_handler))
{
if (NILP (var))
- return Fprogn (success_handler);
+ return Fprogn (XCDR (success_handler));
Lisp_Object handler_var = var;
if (!NILP (Vinternal_interpreter_environment))
@@ -1442,7 +1442,7 @@ internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
specpdl_ref count = SPECPDL_INDEX ();
specbind (handler_var, result);
- return unbind_to (count, Fprogn (success_handler));
+ return unbind_to (count, Fprogn (XCDR (success_handler)));
}
return result;
}
diff --git a/src/fileio.c b/src/fileio.c
index 31353be5d5a..66ce6b30887 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -134,6 +134,7 @@ static dev_t timestamp_file_system;
is added here. */
static Lisp_Object Vwrite_region_annotation_buffers;
+static Lisp_Object emacs_readlinkat (int, char const *);
static Lisp_Object file_name_directory (Lisp_Object);
static bool a_write (int, Lisp_Object, ptrdiff_t, ptrdiff_t,
Lisp_Object *, struct coding_system *);
@@ -2219,7 +2220,7 @@ permissions. */)
report_file_error ("Copying permissions to", newname);
}
#else /* not WINDOWSNT */
- ifd = emacs_open (SSDATA (encoded_file), O_RDONLY, 0);
+ ifd = emacs_open (SSDATA (encoded_file), O_RDONLY | O_NONBLOCK, 0);
if (ifd < 0)
report_file_error ("Opening input file", file);
@@ -2705,31 +2706,19 @@ This is what happens in interactive use with M-x. */)
}
if (dirp)
call4 (Qcopy_directory, file, newname, Qt, Qnil);
- else
- {
- Lisp_Object symlink_target
- = (S_ISLNK (file_st.st_mode)
- ? check_emacs_readlinkat (AT_FDCWD, file, SSDATA (encoded_file))
- : Qnil);
- if (!NILP (symlink_target))
- Fmake_symbolic_link (symlink_target, newname, ok_if_already_exists);
- else if (S_ISFIFO (file_st.st_mode))
- {
- /* If it's a FIFO, calling `copy-file' will hang if it's a
- inter-file system move, so do it here. (It will signal
- an error in that case, but it won't hang in any case.) */
- if (!NILP (ok_if_already_exists))
- barf_or_query_if_file_exists (newname, false,
- "rename to it",
- FIXNUMP (ok_if_already_exists),
- false);
- if (rename (SSDATA (encoded_file), SSDATA (encoded_newname)) != 0)
- report_file_errno ("Renaming", list2 (file, newname), errno);
- return Qnil;
- }
+ else if (S_ISREG (file_st.st_mode))
+ Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt);
+ else if (S_ISLNK (file_st.st_mode))
+ {
+ Lisp_Object target = emacs_readlinkat (AT_FDCWD,
+ SSDATA (encoded_file));
+ if (!NILP (target))
+ Fmake_symbolic_link (target, newname, ok_if_already_exists);
else
- Fcopy_file (file, newname, ok_if_already_exists, Qt, Qt, Qt);
+ report_file_error ("Renaming", list2 (file, newname));
}
+ else
+ report_file_errno ("Renaming", list2 (file, newname), rename_errno);
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qdelete_by_moving_to_trash, Qnil);
diff --git a/src/fns.c b/src/fns.c
index b6e871ad49c..eeb65cadf3f 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -497,8 +497,13 @@ Symbols are also allowed; their print names are used instead. */)
int ws = sizeof (word_t);
const word_t *w1 = (const word_t *) SDATA (string1);
const word_t *w2 = (const word_t *) SDATA (string2);
- while (b < nb - ws + 1 && w1[b / ws] == w2[b / ws])
- b += ws;
+ while (b < nb - ws + 1)
+ {
+ if (UNALIGNED_LOAD_SIZE (w1, b / ws)
+ != UNALIGNED_LOAD_SIZE (w2, b / ws))
+ break;
+ b += ws;
+ }
}
/* Scan forward to the differing byte. */
diff --git a/src/frame.c b/src/frame.c
index 05106a6c759..7d902dabd4f 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1892,12 +1892,61 @@ other_frames (struct frame *f, bool invisible, bool force)
if (f != f1)
{
+ /* The following code is defined out because it is
+ responsible for a performance drop under X connections
+ over a network, and its purpose is unclear. XSync does
+ not handle events (or call any callbacks defined by
+ Emacs), and as such it should not note any "recent change
+ in visibility".
+
+ When writing new code, please try as hard as possible to
+ avoid calls that require a roundtrip to the X server.
+ When such calls are inevitable, use the XCB library to
+ handle multiple consecutive requests with a data reply in
+ a more asynchronous fashion. The following code
+ demonstrates why:
+
+ rc = XGetWindowProperty (dpyinfo->display, window, ...
+ status = XGrabKeyboard (dpyinfo->display, ...
+
+ here, `XGetWindowProperty' will wait for a reply from the
+ X server before returning, and thus allowing Emacs to
+ make the XGrabKeyboard request, which in itself also
+ requires waiting a reply. When XCB is available, this
+ code could be written:
+
+#ifdef HAVE_XCB
+ xcb_get_property_cookie_t cookie1;
+ xcb_get_property_reply_t *reply1;
+ xcb_grab_keyboard_cookie_t cookie2;
+ xcb_grab_keyboard_reply_t *reply2;
+
+ cookie1 = xcb_get_property (dpyinfo->xcb_connection, window, ...
+ cookie2 = xcb_grab_keyboard (dpyinfo->xcb_connection, ...
+ reply1 = xcb_get_property_reply (dpyinfo->xcb_connection,
+ cookie1);
+ reply2 = xcb_grab_keyboard_reply (dpyinfo->xcb_connection,
+ cookie2);
+#endif
+
+ In this code, the GetProperty and GrabKeyboard requests
+ are made simultaneously, and replies are then obtained
+ from the server at once, avoiding the extraneous
+ roundtrip to the X server after the call to
+ `XGetWindowProperty'.
+
+ However, please keep an alternative implementation
+ available for use when Emacs is built without XCB. */
+
+#if 0
/* Verify that we can still talk to the frame's X window, and
note any recent change in visibility. */
#ifdef HAVE_X_WINDOWS
if (FRAME_WINDOW_P (f1))
x_sync (f1);
#endif
+#endif
+
if (!FRAME_TOOLTIP_P (f1)
/* Tooltips and child frames count neither for
invisibility nor for deletions. */
diff --git a/src/frame.h b/src/frame.h
index d6fd62b2ac2..f29cc249ea8 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1010,6 +1010,20 @@ default_pixels_per_inch_y (void)
/* True if frame F is currently visible. */
#define FRAME_VISIBLE_P(f) (f)->visible
+/* True if frame F should be redisplayed. This is normally the same
+ as FRAME_VISIBLE_P (f). Under X, frames can continue to be
+ displayed to the user by the compositing manager even if they are
+ invisible, so this also checks whether or not the frame is reported
+ visible by the X server. */
+
+#ifndef HAVE_X_WINDOWS
+#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f))
+#else
+#define FRAME_REDISPLAY_P(f) (FRAME_VISIBLE_P (f) \
+ || (FRAME_X_P (f) \
+ && FRAME_X_VISIBLE (f)))
+#endif
+
/* True if frame F is currently visible but hidden. */
#define FRAME_OBSCURED_P(f) ((f)->visible > 1)
@@ -1718,7 +1732,6 @@ extern void x_wm_set_icon_position (struct frame *, int, int);
#if !defined USE_X_TOOLKIT
extern const char *x_get_resource_string (const char *, const char *);
#endif
-extern void x_sync (struct frame *);
#endif /* HAVE_X_WINDOWS */
#if !defined (HAVE_NS) && !defined (HAVE_PGTK)
diff --git a/src/gnutls.c b/src/gnutls.c
index 7f0aaf85a41..e58322934de 100644
--- a/src/gnutls.c
+++ b/src/gnutls.c
@@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
# endif
# if GNUTLS_VERSION_NUMBER >= 0x030200
+# define HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
# define HAVE_GNUTLS_CIPHER_GET_IV_SIZE
# endif
@@ -121,6 +122,11 @@ DEF_DLL_FN (int, gnutls_certificate_set_x509_crl_file,
DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file,
(gnutls_certificate_credentials_t, const char *, const char *,
gnutls_x509_crt_fmt_t));
+# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+DEF_DLL_FN (int, gnutls_certificate_set_x509_key_file2,
+ (gnutls_certificate_credentials_t, const char *, const char *,
+ gnutls_x509_crt_fmt_t, const char *, unsigned int));
+# endif
# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
DEF_DLL_FN (int, gnutls_certificate_set_x509_system_trust,
(gnutls_certificate_credentials_t));
@@ -314,6 +320,9 @@ init_gnutls_functions (void)
LOAD_DLL_FN (library, gnutls_certificate_set_verify_flags);
LOAD_DLL_FN (library, gnutls_certificate_set_x509_crl_file);
LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file);
+# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+ LOAD_DLL_FN (library, gnutls_certificate_set_x509_key_file2);
+# endif
# ifdef HAVE_GNUTLS_X509_SYSTEM_TRUST
LOAD_DLL_FN (library, gnutls_certificate_set_x509_system_trust);
# endif
@@ -455,6 +464,9 @@ init_gnutls_functions (void)
# define gnutls_certificate_set_verify_flags fn_gnutls_certificate_set_verify_flags
# define gnutls_certificate_set_x509_crl_file fn_gnutls_certificate_set_x509_crl_file
# define gnutls_certificate_set_x509_key_file fn_gnutls_certificate_set_x509_key_file
+# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+# define gnutls_certificate_set_x509_key_file2 fn_gnutls_certificate_set_x509_key_file2
+# endif
# define gnutls_certificate_set_x509_system_trust fn_gnutls_certificate_set_x509_system_trust
# define gnutls_certificate_set_x509_trust_file fn_gnutls_certificate_set_x509_trust_file
# define gnutls_certificate_type_get fn_gnutls_certificate_type_get
@@ -1774,6 +1786,72 @@ gnutls_verify_boot (Lisp_Object proc, Lisp_Object proplist)
return gnutls_make_error (ret);
}
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+
+/* Helper function for gnutls-boot.
+
+ The key :flags receives a list of symbols, each of which
+ corresponds to a GnuTLS C flag, the ORed result is to be passed to
+ the function `gnutls_certificate_set_x509_key_file2' as its last
+ argument. */
+static unsigned int
+key_file2_aux (Lisp_Object flags)
+{
+ unsigned int rv = 0;
+ Lisp_Object tail = flags;
+ FOR_EACH_TAIL_SAFE (tail)
+ {
+ Lisp_Object flag = XCAR (tail);
+ if (EQ (flag, Qgnutls_pkcs_plain))
+ rv |= GNUTLS_PKCS_PLAIN;
+ else if (EQ (flag, Qgnutls_pkcs_pkcs12_3des))
+ rv |= GNUTLS_PKCS_PKCS12_3DES;
+ else if (EQ (flag, Qgnutls_pkcs_pkcs12_arcfour))
+ rv |= GNUTLS_PKCS_PKCS12_ARCFOUR;
+ else if (EQ (flag, Qgnutls_pkcs_pkcs12_rc2_40))
+ rv |= GNUTLS_PKCS_PKCS12_RC2_40;
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_3des))
+ rv |= GNUTLS_PKCS_PBES2_3DES;
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_128))
+ rv |= GNUTLS_PKCS_PBES2_AES_128;
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_192))
+ rv |= GNUTLS_PKCS_PBES2_AES_192;
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_aes_256))
+ rv |= GNUTLS_PKCS_PBES2_AES_256;
+ else if (EQ (flag, Qgnutls_pkcs_null_password))
+ rv |= GNUTLS_PKCS_NULL_PASSWORD;
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_des))
+ rv |= GNUTLS_PKCS_PBES2_DES;
+#ifdef GNUTLS_PKCS_PBES1_DES_MD5
+ else if (EQ (flag, Qgnutls_pkcs_pbes1_des_md5))
+ rv |= GNUTLS_PKCS_PBES1_DES_MD5;
+#endif
+#ifdef GNUTLS_PKCS_PBES2_GOST_TC26Z
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_tc26z))
+ rv |= GNUTLS_PKCS_PBES2_GOST_TC26Z;
+#endif
+#ifdef GNUTLS_PKCS_PBES2_GOST_CPA
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpa))
+ rv |= GNUTLS_PKCS_PBES2_GOST_CPA;
+#endif
+#ifdef GNUTLS_PKCS_PBES2_GOST_CPB
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpb))
+ rv |= GNUTLS_PKCS_PBES2_GOST_CPB;
+#endif
+#ifdef GNUTLS_PKCS_PBES2_GOST_CPC
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpc))
+ rv |= GNUTLS_PKCS_PBES2_GOST_CPC;
+#endif
+#ifdef GNUTLS_PKCS_PBES2_GOST_CPD
+ else if (EQ (flag, Qgnutls_pkcs_pbes2_gost_cpd))
+ rv |= GNUTLS_PKCS_PBES2_GOST_CPD;
+#endif
+ }
+ return rv;
+}
+
+#endif /* HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2 */
+
DEFUN ("gnutls-boot", Fgnutls_boot, Sgnutls_boot, 3, 3, 0,
doc: /* Initialize GnuTLS client for process PROC with TYPE+PROPLIST.
Currently only client mode is supported. Return a success/failure
@@ -1813,6 +1891,22 @@ accept in Diffie-Hellman key exchange.
:complete-negotiation, if non-nil, will make negotiation complete
before returning even on non-blocking sockets.
+:pass, the password of the private key as per GnuTLS'
+gnutls_certificate_set_x509_key_file2. Specify as nil to have a NULL
+password.
+
+:flags, a list of symbols relating to :pass, each specifying a flag:
+GNUTLS_PKCS_PLAIN, GNUTLS_PKCS_PKCS12_3DES,
+GNUTLS_PKCS_PKCS12_ARCFOUR, GNUTLS_PKCS_PKCS12_RC2_40,
+GNUTLS_PKCS_PBES2_3DES, GNUTLS_PKCS_PBES2_AES_128,
+GNUTLS_PKCS_PBES2_AES_192, GNUTLS_PKCS_PBES2_AES_256,
+GNUTLS_PKCS_NULL_PASSWORD, GNUTLS_PKCS_PBES2_DES,
+GNUTLS_PKCS_PBES2_DES_MD5, GNUTLS_PKCS_PBES2_GOST_TC26Z,
+GNUTLS_PKCS_PBES2_GOST_CPA, GNUTLS_PKCS_PBES2_GOST_CPB,
+GNUTLS_PKCS_PBES2_GOST_CPC, GNUTLS_PKCS_PBES2_GOST_CPD. If not
+specified, or if nil, the bitflag with value 0 is used.
+Note that some of these are only supported since GnuTLS 3.6.3.
+
The debug level will be set for this process AND globally for GnuTLS.
So if you set it higher or lower at any point, it affects global
debugging.
@@ -1825,6 +1919,9 @@ Processes must be initialized with this function before other GnuTLS
functions are used. This function allocates resources which can only
be deallocated by calling `gnutls-deinit' or by calling it again.
+The :pass and :flags keys are ignored with old versions of GnuTLS, and
+:flags is ignored if :pass is not specified.
+
The callbacks alist can have a `verify' key, associated with a
verification function (UNUSED).
@@ -1842,16 +1939,22 @@ one trustfile (usually a CA bundle). */)
Lisp_Object global_init;
char const *priority_string_ptr = "NORMAL"; /* default priority string. */
char *c_hostname;
+ const char *c_pass;
/* Placeholders for the property list elements. */
Lisp_Object priority_string;
Lisp_Object trustfiles;
Lisp_Object crlfiles;
Lisp_Object keylist;
+ Lisp_Object pass;
+ Lisp_Object flags;
/* Lisp_Object callbacks; */
Lisp_Object loglevel;
Lisp_Object hostname;
Lisp_Object prime_bits;
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+ unsigned int aux_key_file;
+#endif
struct Lisp_Process *p = XPROCESS (proc);
CHECK_PROCESS (proc);
@@ -1877,6 +1980,13 @@ one trustfile (usually a CA bundle). */)
crlfiles = plist_get (proplist, QCcrlfiles);
loglevel = plist_get (proplist, QCloglevel);
prime_bits = plist_get (proplist, QCmin_prime_bits);
+ pass = plist_get (proplist, QCpass);
+ flags = plist_get (proplist, QCflags);
+
+ if (STRINGP (pass))
+ c_pass = SSDATA (pass);
+ else
+ c_pass = NULL;
if (!STRINGP (hostname))
{
@@ -2038,6 +2148,20 @@ one trustfile (usually a CA bundle). */)
keyfile = ansi_encode_filename (keyfile);
certfile = ansi_encode_filename (certfile);
# endif
+# ifdef HAVE_GNUTLS_CERTIFICATE_SET_X509_KEY_FILE2
+ if (!NILP (plist_member (proplist, QCpass)))
+ {
+ aux_key_file = key_file2_aux (flags);
+ ret
+ = gnutls_certificate_set_x509_key_file2 (x509_cred,
+ SSDATA (certfile),
+ SSDATA (keyfile),
+ file_format,
+ c_pass,
+ aux_key_file);
+ }
+ else
+# endif
ret = gnutls_certificate_set_x509_key_file
(x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
@@ -2282,7 +2406,7 @@ gnutls_symmetric_aead (bool encrypting, gnutls_cipher_algorithm_t gca,
Lisp_Object output;
if (GNUTLS_E_SUCCESS <= ret)
output = make_unibyte_string (storage, storage_length);
- explicit_bzero (storage, storage_length);
+ memset_explicit (storage, 0, storage_length);
gnutls_aead_cipher_deinit (acipher);
if (ret < GNUTLS_E_SUCCESS)
@@ -2862,8 +2986,26 @@ level in the ones. For builds without libgnutls, the value is -1. */);
DEFSYM (QCmin_prime_bits, ":min-prime-bits");
DEFSYM (QCloglevel, ":loglevel");
DEFSYM (QCcomplete_negotiation, ":complete-negotiation");
+ DEFSYM (QCpass, ":pass");
+ DEFSYM (QCflags, ":flags");
DEFSYM (QCverify_flags, ":verify-flags");
DEFSYM (QCverify_error, ":verify-error");
+ DEFSYM (Qgnutls_pkcs_plain, "GNUTLS_PKCS_PLAIN");
+ DEFSYM (Qgnutls_pkcs_pkcs12_3des, "GNUTLS_PKCS_PKCS12_3DES");
+ DEFSYM (Qgnutls_pkcs_pkcs12_arcfour, "GNUTLS_PKCS_PKCS12_ARCFOUR");
+ DEFSYM (Qgnutls_pkcs_pkcs12_rc2_40, "GNUTLS_PKCS_PKCS12_RC2_40");
+ DEFSYM (Qgnutls_pkcs_pbes2_3des, "GNUTLS_PKCS_PBES2_3DES");
+ DEFSYM (Qgnutls_pkcs_pbes2_aes_128, "GNUTLS_PKCS_PBES2_AES_128");
+ DEFSYM (Qgnutls_pkcs_pbes2_aes_192, "GNUTLS_PKCS_PBES2_AES_192");
+ DEFSYM (Qgnutls_pkcs_pbes2_aes_256, "GNUTLS_PKCS_PBES2_AES_256");
+ DEFSYM (Qgnutls_pkcs_null_password, "GNUTLS_PKCS_NULL_PASSWORD");
+ DEFSYM (Qgnutls_pkcs_pbes2_des, "GNUTLS_PKCS_PBES2_DES");
+ DEFSYM (Qgnutls_pkcs_pbes1_des_md5, "GNUTLS_PKCS_PBES1_DES_MD5");
+ DEFSYM (Qgnutls_pkcs_pbes2_gost_tc26z, "GNUTLS_PKCS_PBES2_GOST_TC26Z");
+ DEFSYM (Qgnutls_pkcs_pbes2_gost_cpa, "GNUTLS_PKCS_PBES2_GOST_CPA");
+ DEFSYM (Qgnutls_pkcs_pbes2_gost_cpb, "GNUTLS_PKCS_PBES2_GOST_CPB");
+ DEFSYM (Qgnutls_pkcs_pbes2_gost_cpc, "GNUTLS_PKCS_PBES2_GOST_CPC");
+ DEFSYM (Qgnutls_pkcs_pbes2_gost_cpd, "GNUTLS_PKCS_PBES2_GOST_CPD");
DEFSYM (QCcipher_id, ":cipher-id");
DEFSYM (QCcipher_aead_capable, ":cipher-aead-capable");
diff --git a/src/gtkutil.c b/src/gtkutil.c
index a6bba096a43..592bb497749 100644
--- a/src/gtkutil.c
+++ b/src/gtkutil.c
@@ -2103,7 +2103,7 @@ xg_frame_restack (struct frame *f1, struct frame *f2, bool above_flag)
gdk_window_restack (gwin1, gwin2, above_flag);
#ifndef HAVE_PGTK
- x_sync (f1);
+ XSync (FRAME_X_DISPLAY (f1), False);
#else
gdk_flush ();
#endif
@@ -4793,7 +4793,7 @@ xg_update_scrollbar_pos (struct frame *f,
here to get some events. */
#ifndef HAVE_PGTK
- x_sync (f);
+ XSync (FRAME_X_DISPLAY (f), False);
#else
gdk_flush ();
#endif
@@ -4894,7 +4894,7 @@ xg_update_horizontal_scrollbar_pos (struct frame *f,
}
#ifndef HAVE_PGTK
- x_sync (f);
+ XSync (FRAME_X_DISPLAY (f), False);
#else
gdk_flush ();
#endif
diff --git a/src/itree.c b/src/itree.c
index f582a6112a7..5079e2389f8 100644
--- a/src/itree.c
+++ b/src/itree.c
@@ -1376,7 +1376,7 @@ itree_iterator_first_node (struct itree_tree *tree,
return node;
}
-/* Start a iterator enumerating all intervals in [BEGIN,END) in the
+/* Start an iterator enumerating all intervals in [BEGIN,END) in the
given ORDER. */
struct itree_iterator *
diff --git a/src/itree.h b/src/itree.h
index c0c7060ac71..f1e2bf3bfde 100644
--- a/src/itree.h
+++ b/src/itree.h
@@ -25,6 +25,8 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "lisp.h"
+INLINE_HEADER_BEGIN
+
/* The tree and node structs are mainly here, so they can be
allocated.
@@ -114,6 +116,11 @@ extern void itree_node_set_region (struct itree_tree *, struct itree_node *,
ptrdiff_t, ptrdiff_t);
extern struct itree_tree *itree_create (void);
extern void itree_destroy (struct itree_tree *);
+INLINE bool
+itree_empty_p (struct itree_tree *tree)
+{
+ return !tree || !tree->root;
+}
extern intmax_t itree_size (struct itree_tree *);
extern void itree_clear (struct itree_tree *);
extern void itree_insert (struct itree_tree *, struct itree_node *,
@@ -178,4 +185,6 @@ struct itree_iterator
#define ITREE_FOREACH_NARROW(beg, end) \
itree_iterator_narrow (itree_iter_, beg, end)
+INLINE_HEADER_END
+
#endif
diff --git a/src/lisp.h b/src/lisp.h
index 0f70f60d75c..0dcf803e124 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -22,7 +22,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <alloca.h>
#include <setjmp.h>
-#include <stdalign.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
@@ -5296,6 +5295,26 @@ __lsan_ignore_object (void const *p)
}
#endif
+/* If built with USE_SANITIZER_UNALIGNED_LOAD defined, use compiler
+ provided ASan functions to perform unaligned loads, allowing ASan
+ to catch bugs which it might otherwise miss. */
+#if defined HAVE_SANITIZER_COMMON_INTERFACE_DEFS_H \
+ && defined ADDRESS_SANITIZER \
+ && defined USE_SANITIZER_UNALIGNED_LOAD
+# include <sanitizer/common_interface_defs.h>
+# if (SIZE_MAX == UINT64_MAX)
+# define UNALIGNED_LOAD_SIZE(a, i) \
+ (size_t) __sanitizer_unaligned_load64 ((void *) ((a) + (i)))
+# elif (SIZE_MAX == UINT32_MAX)
+# define UNALIGNED_LOAD_SIZE(a, i) \
+ (size_t) __sanitizer_unaligned_load32 ((void *) ((a) + (i)))
+# else
+# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
+# endif
+#else
+# define UNALIGNED_LOAD_SIZE(a, i) *((a) + (i))
+#endif
+
extern void xputenv (const char *);
extern char *egetenv_internal (const char *, ptrdiff_t);
diff --git a/src/module-env-29.h b/src/module-env-29.h
index 6ca03773181..e69de29bb2d 100644
--- a/src/module-env-29.h
+++ b/src/module-env-29.h
@@ -1,3 +0,0 @@
- /* Add module environment functions newly added in Emacs 29 here.
- Before Emacs 29 is released, remove this comment and start
- module-env-30.h on the master branch. */
diff --git a/src/module-env-30.h b/src/module-env-30.h
new file mode 100644
index 00000000000..6ca03773181
--- /dev/null
+++ b/src/module-env-30.h
@@ -0,0 +1,3 @@
+ /* Add module environment functions newly added in Emacs 29 here.
+ Before Emacs 29 is released, remove this comment and start
+ module-env-30.h on the master branch. */
diff --git a/src/nsterm.m b/src/nsterm.m
index c09f743ec7f..507f2a9e7da 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -6703,16 +6703,8 @@ ns_create_font_panel_buttons (id target, SEL select, SEL cancel_action)
- (void)resetCursorRects
{
- NSRect visible;
- NSCursor *currentCursor;
-
- /* On macOS 13, [resetCursorRects:] could be called even after the
- window is closed. */
- if (! emacsframe || ! FRAME_OUTPUT_DATA (emacsframe))
- return;
-
- visible = [self visibleRect];
- currentCursor = FRAME_POINTER_TYPE (emacsframe);
+ NSRect visible = [self visibleRect];
+ NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
NSTRACE ("[EmacsView resetCursorRects]");
if (currentCursor == nil)
diff --git a/src/pdumper.c b/src/pdumper.c
index 263343f60be..e1c55d07ac3 100644
--- a/src/pdumper.c
+++ b/src/pdumper.c
@@ -2862,7 +2862,7 @@ dump_buffer (struct dump_context *ctx, const struct buffer *in_buffer)
DUMP_FIELD_COPY (out, buffer, inhibit_buffer_hooks);
DUMP_FIELD_COPY (out, buffer, long_line_optimizations_p);
- if (buffer->overlays && buffer->overlays->root != NULL)
+ if (!itree_empty_p (buffer->overlays))
/* We haven't implemented the code to dump overlays. */
emacs_abort ();
else
diff --git a/src/sysdep.c b/src/sysdep.c
index 736723bdf3d..8402ffe308c 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -2653,10 +2653,11 @@ emacs_perror (char const *message)
int
renameat_noreplace (int srcfd, char const *src, int dstfd, char const *dst)
{
-#if defined SYS_renameat2 && defined RENAME_NOREPLACE
- return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
-#elif defined CYGWIN && defined RENAME_NOREPLACE
+#if HAVE_RENAMEAT2 && defined RENAME_NOREPLACE
return renameat2 (srcfd, src, dstfd, dst, RENAME_NOREPLACE);
+#elif defined SYS_renameat2 && defined RENAME_NOREPLACE
+ /* Linux kernel 3.15 (2014) or later, with glibc 2.27 (2018) or earlier. */
+ return syscall (SYS_renameat2, srcfd, src, dstfd, dst, RENAME_NOREPLACE);
#elif defined RENAME_EXCL
return renameatx_np (srcfd, src, dstfd, dst, RENAME_EXCL);
#else
diff --git a/src/xdisp.c b/src/xdisp.c
index c9b3b187fe2..db6dd3fab63 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12938,7 +12938,7 @@ clear_garbaged_frames (void)
{
struct frame *f = XFRAME (frame);
- if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
+ if (FRAME_REDISPLAY_P (f) && FRAME_GARBAGED_P (f))
{
if (f->resized_p
/* It makes no sense to redraw a non-selected TTY
@@ -12987,7 +12987,7 @@ echo_area_display (bool update_frame_p)
f = XFRAME (WINDOW_FRAME (w));
/* Don't display if frame is invisible or not yet initialized. */
- if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
+ if (!FRAME_REDISPLAY_P (f) || !f->glyphs_initialized_p)
return;
#ifdef HAVE_WINDOW_SYSTEM
@@ -13543,7 +13543,7 @@ prepare_menu_bars (void)
TTY frames to be completely redrawn, when there
are more than one of them, even though nothing
should be changed on display. */
- || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
+ || (FRAME_REDISPLAY_P (f) && FRAME_WINDOW_P (f))))
gui_consider_frame_title (frame);
}
}
@@ -16432,7 +16432,7 @@ redisplay_internal (void)
{
struct frame *f = XFRAME (frame);
- if (FRAME_VISIBLE_P (f))
+ if (FRAME_REDISPLAY_P (f))
{
++number_of_visible_frames;
/* Adjust matrices for visible frames only. */
@@ -16574,7 +16574,7 @@ redisplay_internal (void)
&& !w->update_mode_line
&& !current_buffer->clip_changed
&& !current_buffer->prevent_redisplay_optimizations_p
- && FRAME_VISIBLE_P (XFRAME (w->frame))
+ && FRAME_REDISPLAY_P (XFRAME (w->frame))
&& !FRAME_OBSCURED_P (XFRAME (w->frame))
&& !XFRAME (w->frame)->cursor_type_changed
&& !XFRAME (w->frame)->face_change
@@ -16852,7 +16852,7 @@ redisplay_internal (void)
if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
- if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+ if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
{
/* Don't allow freeing images and faces for this
frame as long as the frame's update wasn't
@@ -16878,7 +16878,7 @@ redisplay_internal (void)
if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
- if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
+ if (FRAME_REDISPLAY_P (f) && !FRAME_OBSCURED_P (f))
{
/* If fonts changed on visible frame, display again. */
if (f->fonts_changed)
@@ -16984,7 +16984,7 @@ redisplay_internal (void)
}
}
}
- else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
+ else if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
{
sf->inhibit_clear_image_cache = true;
displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
@@ -17035,7 +17035,7 @@ redisplay_internal (void)
unrequest_sigio ();
STOP_POLLING;
- if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
+ if (FRAME_REDISPLAY_P (sf) && !FRAME_OBSCURED_P (sf))
{
if (hscroll_retries <= MAX_HSCROLL_RETRIES
&& hscroll_windows (selected_window))
@@ -17134,7 +17134,7 @@ redisplay_internal (void)
FOR_EACH_FRAME (tail, frame)
{
- if (XFRAME (frame)->visible)
+ if (FRAME_REDISPLAY_P (XFRAME (frame)))
new_count++;
}
@@ -26329,16 +26329,17 @@ display_menu_bar (struct window *w)
it.first_visible_x = 0;
it.last_visible_x = FRAME_PIXEL_WIDTH (f);
#elif defined (HAVE_X_WINDOWS) /* X without toolkit. */
+ struct window *menu_window = NULL;
+ struct face *face = FACE_FROM_ID (f, MENU_FACE_ID);
+
if (FRAME_WINDOW_P (f))
{
/* Menu bar lines are displayed in the desired matrix of the
dummy window menu_bar_window. */
- struct window *menu_w;
- menu_w = XWINDOW (f->menu_bar_window);
- init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
+ menu_window = XWINDOW (f->menu_bar_window);
+ init_iterator (&it, menu_window, -1, -1,
+ menu_window->desired_matrix->rows,
MENU_FACE_ID);
- it.first_visible_x = 0;
- it.last_visible_x = FRAME_PIXEL_WIDTH (f);
}
else
#endif /* not USE_X_TOOLKIT and not USE_GTK */
@@ -26392,6 +26393,50 @@ display_menu_bar (struct window *w)
/* Compute the total height of the lines. */
compute_line_metrics (&it);
+ it.glyph_row->full_width_p = true;
+ it.glyph_row->continued_p = false;
+ it.glyph_row->truncated_on_left_p = false;
+ it.glyph_row->truncated_on_right_p = false;
+
+#if defined (HAVE_X_WINDOWS) && !defined (USE_X_TOOLKIT) && !defined (USE_GTK)
+ /* Make a 3D menu bar have a shadow at its right end. */
+ extend_face_to_end_of_line (&it);
+ if (face->box != FACE_NO_BOX)
+ {
+ struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
+ + it.glyph_row->used[TEXT_AREA] - 1);
+ int box_thickness = face->box_vertical_line_width;
+ last->right_box_line_p = true;
+ /* Add back the space for the right box line we subtracted in
+ init_iterator, since the right_box_line_p flag will make the
+ glyph wider. We actually add only as much space as is
+ available for the last glyph of the menu bar and whatever
+ space is left beyond it, since that glyph could be only
+ partially visible. */
+ if (box_thickness > 0)
+ last->pixel_width += max (0, (box_thickness
+ - (it.current_x - it.last_visible_x)));
+ }
+
+ /* With the non-toolkit version, modify the menu bar window height
+ accordingly. */
+ if (FRAME_WINDOW_P (it.f) && menu_window)
+ {
+ struct glyph_row *row;
+ int delta_height;
+
+ row = it.glyph_row;
+ delta_height
+ = ((row->y + row->height)
+ - WINDOW_BOX_HEIGHT_NO_MODE_LINE (menu_window));
+
+ if (delta_height != 0)
+ {
+ FRAME_MENU_BAR_HEIGHT (it.f) += delta_height;
+ adjust_frame_size (it.f, -1, -1, 3, false, Qmenu_bar_lines);
+ }
+ }
+#endif
}
/* Deep copy of a glyph row, including the glyphs. */
@@ -33213,7 +33258,7 @@ display_and_set_cursor (struct window *w, bool on,
windows and frames; in the latter case, the frame or window may
be in the midst of changing its size, and x and y may be off the
window. */
- if (! FRAME_VISIBLE_P (f)
+ if (! FRAME_REDISPLAY_P (f)
|| vpos >= w->current_matrix->nrows
|| hpos >= w->current_matrix->matrix_w)
return;
@@ -33374,7 +33419,7 @@ gui_update_cursor (struct frame *f, bool on_p)
void
gui_clear_cursor (struct window *w)
{
- if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
+ if (FRAME_REDISPLAY_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
update_window_cursor (w, false);
}
diff --git a/src/xfns.c b/src/xfns.c
index 36b51a30112..1cc5aec1eb4 100644
--- a/src/xfns.c
+++ b/src/xfns.c
@@ -43,7 +43,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef USE_XCB
#include <xcb/xcb.h>
#include <xcb/xproto.h>
-#include <xcb/xcb_aux.h>
#endif
#include "bitmaps/gray.xbm"
@@ -1368,7 +1367,7 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
XCreateFontCursor is not a request that waits for a reply,
and as such can return IDs that will not actually be used by
the server. */
- x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
/* Free any successfully created cursors. */
for (i = 0; i < mouse_cursor_max; i++)
@@ -2643,12 +2642,18 @@ append_wm_protocols (struct x_display_info *dpyinfo,
if (existing)
XFree (existing);
- if (!found_wm_ping)
- protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
+ if (!dpyinfo->untrusted)
+ {
+ /* Untrusted clients cannot use these protocols which require
+ communicating with the window manager. */
+
+ if (!found_wm_ping)
+ protos[num_protos++] = dpyinfo->Xatom_net_wm_ping;
#if !defined HAVE_GTK3 && defined HAVE_XSYNC
- if (!found_wm_sync_request && dpyinfo->xsync_supported_p)
- protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
+ if (!found_wm_sync_request && dpyinfo->xsync_supported_p)
+ protos[num_protos++] = dpyinfo->Xatom_net_wm_sync_request;
#endif
+ }
if (num_protos)
XChangeProperty (dpyinfo->display,
@@ -4736,6 +4741,7 @@ This function is an internal primitive--use `make-frame' instead. */)
#endif /* USE_LUCID && USE_TOOLKIT_SCROLL_BARS */
f->output_data.x->white_relief.pixel = -1;
f->output_data.x->black_relief.pixel = -1;
+ f->output_data.x->visibility_state = VisibilityFullyObscured;
fset_icon_name (f, gui_display_get_arg (dpyinfo,
parms,
@@ -5723,13 +5729,13 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
= xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) dpyinfo->root_window,
(xcb_atom_t) dpyinfo->Xatom_net_current_desktop,
- XCB_ATOM_CARDINAL, 0, 1);
+ XA_CARDINAL, 0, 1);
workarea_cookie
= xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) dpyinfo->root_window,
(xcb_atom_t) dpyinfo->Xatom_net_workarea,
- XCB_ATOM_CARDINAL, 0, UINT32_MAX);
+ XA_CARDINAL, 0, UINT32_MAX);
reply = xcb_get_property_reply (dpyinfo->xcb_connection,
current_desktop_cookie, &error);
@@ -5740,7 +5746,7 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
else
{
if (xcb_get_property_value_length (reply) != 4
- || reply->type != XCB_ATOM_CARDINAL || reply->format != 32)
+ || reply->type != XA_CARDINAL || reply->format != 32)
rc = false;
else
current_workspace = *(uint32_t *) xcb_get_property_value (reply);
@@ -5755,7 +5761,7 @@ x_get_net_workarea (struct x_display_info *dpyinfo, XRectangle *rect)
free (error), rc = false;
else
{
- if (rc && reply->type == XCB_ATOM_CARDINAL && reply->format == 32
+ if (rc && reply->type == XA_CARDINAL && reply->format == 32
&& (xcb_get_property_value_length (reply) / sizeof (uint32_t)
>= current_workspace + 4))
{
@@ -7079,8 +7085,8 @@ that mouse buttons are being held down, such as immediately after a
/* Catch errors since interning lots of targets can potentially
generate a BadAlloc error. */
x_catch_errors (FRAME_X_DISPLAY (f));
- XInternAtoms (FRAME_X_DISPLAY (f), target_names,
- ntargets, False, target_atoms);
+ x_intern_atoms (FRAME_DISPLAY_INFO (f), target_names,
+ ntargets, target_atoms);
x_check_errors (FRAME_X_DISPLAY (f),
"Failed to intern target atoms: %s");
x_uncatch_errors_after_check ();
@@ -7377,20 +7383,6 @@ If TERMINAL is omitted or nil, that stands for the selected frame's display. */
return Qnil;
}
-/* Wait for responses to all X commands issued so far for frame F. */
-
-void
-x_sync (struct frame *f)
-{
- block_input ();
-#ifndef USE_XCB
- XSync (FRAME_X_DISPLAY (f), False);
-#else
- xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
-#endif
- unblock_input ();
-}
-
/***********************************************************************
Window properties
@@ -7484,7 +7476,7 @@ silently ignored. */)
elsize = element_format == 32 ? sizeof (long) : element_format >> 3;
data = xnmalloc (nelements, elsize);
- x_fill_property_data (FRAME_X_DISPLAY (f), value, data, nelements,
+ x_fill_property_data (FRAME_DISPLAY_INFO (f), value, data, nelements,
element_format);
}
else
diff --git a/src/xftfont.c b/src/xftfont.c
index 6043ef9f94f..b9686db2a73 100644
--- a/src/xftfont.c
+++ b/src/xftfont.c
@@ -628,6 +628,12 @@ xftfont_shape (Lisp_Object lgstring, Lisp_Object direction)
static int
xftfont_end_for_frame (struct frame *f)
{
+ /* XftDrawDestroy tries to access dpyinfo->display, which could've
+ been destroyed by now, causing Emacs to crash. The alternative
+ is to leak the XftDraw, but that's better than a crash. */
+ if (!FRAME_X_DISPLAY (f))
+ return 0;
+
block_input ();
XftDraw *xft_draw;
diff --git a/src/xselect.c b/src/xselect.c
index 844ef7220a9..05548be311f 100644
--- a/src/xselect.c
+++ b/src/xselect.c
@@ -16,7 +16,6 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
-
/* Rewritten by jwz */
#include <config.h>
@@ -44,7 +43,7 @@ struct prop_location;
struct selection_data;
static void x_decline_selection_request (struct selection_input_event *);
-static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom, bool,
+static bool x_convert_selection (Lisp_Object, Lisp_Object, Atom,
struct x_display_info *, bool);
static bool waiting_for_other_props_on_window (Display *, Window);
static struct prop_location *expect_property_change (Display *, Window,
@@ -77,18 +76,20 @@ static void x_send_client_event (Lisp_Object, Lisp_Object, Lisp_Object,
#define TRACE0(fmt) (void) 0
#define TRACE1(fmt, a0) (void) 0
#define TRACE2(fmt, a0, a1) (void) 0
+#define TRACE3(fmt, a0, a1, a2) (void) 0
#endif
/* Bytes needed to represent 'long' data. This is as per libX11; it
is not necessarily sizeof (long). */
#define X_LONG_SIZE 4
-/* If this is a smaller number than the max-request-size of the display,
- emacs will use INCR selection transfer when the selection is larger
- than this. The max-request-size is usually around 64k, so if you want
- emacs to use incremental selection transfers when the selection is
- smaller than that, set this. I added this mostly for debugging the
- incremental transfer stuff, but it might improve server performance.
+/* If this is a smaller number than the max-request-size of the
+ display, Emacs will use INCR selection transfer when the selection
+ is larger than this. The max-request-size is usually around 64k,
+ so if you want emacs to use incremental selection transfers when
+ the selection is smaller than that, set this. I added this mostly
+ for debugging the incremental transfer stuff, but it might improve
+ server performance.
This value cannot exceed INT_MAX / max (X_LONG_SIZE, sizeof (long))
because it is multiplied by X_LONG_SIZE and by sizeof (long) in
@@ -101,7 +102,9 @@ static void x_send_client_event (Lisp_Object, Lisp_Object, Lisp_Object,
static int
selection_quantum (Display *display)
{
- long mrs = XExtendedMaxRequestSize (display);
+ long mrs;
+
+ mrs = XExtendedMaxRequestSize (display);
if (!mrs)
mrs = XMaxRequestSize (display);
@@ -281,10 +284,8 @@ x_own_selection (Lisp_Object selection_name, Lisp_Object selection_value,
timestamp = dpyinfo->last_user_time;
block_input ();
- x_catch_errors (display);
- XSetSelectionOwner (display, selection_atom, selecting_window, timestamp);
- x_check_errors (display, "Can't set selection: %s");
- x_uncatch_errors_after_check ();
+ XSetSelectionOwner (display, selection_atom, selecting_window,
+ timestamp);
unblock_input ();
/* Now update the local cache */
@@ -459,7 +460,7 @@ x_decline_selection_request (struct selection_input_event *event)
/* The reason for the error may be that the receiver has
died in the meantime. Handle that case. */
block_input ();
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, reply->requestor,
False, 0, &reply_base);
x_stop_ignoring_errors (dpyinfo);
@@ -472,19 +473,65 @@ x_decline_selection_request (struct selection_input_event *event)
struct selection_data
{
+ /* Pointer to the selection data. */
unsigned char *data;
+
+ /* A Lisp_Object containing the selection data. This is either
+ Qnil, or `data' is NULL. If non-nil, then this must be a string
+ whose contents will be written out verbatim. */
+ Lisp_Object string;
+
+ /* The size, in number of items, of the selection data.
+ The value is meaningless if string is non-nil. */
ptrdiff_t size;
+
+ /* The format of the selection data. */
int format;
+
+ /* The type of the selection data. */
Atom type;
- bool nofree;
+
+ /* The property describing the selection data. */
Atom property;
- /* This can be set to non-NULL during x_reply_selection_request, if
- the selection is waiting for an INCR transfer to complete. Don't
- free these; that's done by unexpect_property_change. */
- struct prop_location *wait_object;
+
+ /* The next piece of selection data in the current selection request
+ stack frame. This can be NULL. */
struct selection_data *next;
};
+/* Structure representing a single outstanding selection request (or
+ subrequest if MULTIPLE is being used.) */
+
+struct transfer
+{
+ /* The requestor of this transfer. */
+ Window requestor;
+
+ /* The current offset in items into the selection data, and the
+ number of items to send with each ChangeProperty request. */
+ size_t offset, items_per_request;
+
+ /* The display info associated with the transfer. */
+ struct x_display_info *dpyinfo;
+
+ /* The converted selection data. */
+ struct selection_data data;
+
+ /* The next and last selection transfers on this list. */
+ struct transfer *next, *last;
+
+ /* The atimer for the timeout. */
+ struct atimer *timeout;
+
+ /* The selection serial. */
+ unsigned int serial;
+
+ /* Flags. */
+ int flags;
+};
+
+#define SELECTED_EVENTS 1
+
struct x_selection_request
{
/* The last element in this stack. */
@@ -499,8 +546,8 @@ struct x_selection_request
/* Linked list of the above (in support of MULTIPLE targets). */
struct selection_data *converted_selections;
- /* "Data" to send a requestor for a failed MULTIPLE subtarget. */
- Atom conversion_fail_tag;
+ /* The serial used to handle X errors. */
+ unsigned int serial;
/* Whether or not conversion was successful. */
bool converted;
@@ -511,6 +558,50 @@ struct x_selection_request
struct x_selection_request *selection_request_stack;
+/* List of all outstanding selection transfers which are currently
+ being processed. */
+
+struct transfer outstanding_transfers;
+
+/* A counter for selection serials. */
+
+static unsigned int selection_serial;
+
+
+
+struct prop_location
+{
+ int identifier;
+ Display *display;
+ Window window;
+ Atom property;
+ int desired_state;
+ bool arrived;
+ struct prop_location *next;
+};
+
+static int prop_location_identifier;
+
+static Lisp_Object property_change_reply;
+
+static struct prop_location *property_change_reply_object;
+
+static struct prop_location *property_change_wait_list;
+
+static void
+set_property_change_object (struct prop_location *location)
+{
+ /* Input must be blocked so we don't get the event before we set
+ these. */
+ if (! input_blocked_p ())
+ emacs_abort ();
+
+ XSETCAR (property_change_reply, Qnil);
+ property_change_reply_object = location;
+}
+
+
+
static void
x_push_current_selection_request (struct selection_input_event *se,
struct x_display_info *dpyinfo)
@@ -523,7 +614,6 @@ x_push_current_selection_request (struct selection_input_event *se,
frame->request = se;
frame->dpyinfo = dpyinfo;
frame->converted_selections = NULL;
- frame->conversion_fail_tag = None;
selection_request_stack = frame;
}
@@ -554,7 +644,7 @@ x_selection_request_lisp_error (void)
for (cs = frame->converted_selections; cs; cs = next)
{
next = cs->next;
- if (! cs->nofree && cs->data)
+ if (cs->data)
xfree (cs->data);
xfree (cs);
}
@@ -564,250 +654,450 @@ x_selection_request_lisp_error (void)
x_decline_selection_request (frame->request);
}
-static void
-x_catch_errors_unwind (void)
+
+
+static size_t
+c_size_for_format (int format)
{
- block_input ();
- x_uncatch_errors ();
- unblock_input ();
+ switch (format)
+ {
+ case 8:
+ return sizeof (char);
+
+ case 16:
+ return sizeof (short);
+
+ case 32:
+ return sizeof (long);
+ }
+
+ emacs_abort ();
}
-
-/* This stuff is so that INCR selections are reentrant (that is, so we can
- be servicing multiple INCR selection requests simultaneously.) I haven't
- actually tested that yet. */
+static size_t
+x_size_for_format (int format)
+{
+ switch (format)
+ {
+ case 8:
+ return 1;
+
+ case 16:
+ return 2;
-/* Keep a list of the property changes that are awaited. */
+ case 32:
+ return 4;
+ }
-struct prop_location
+ emacs_abort ();
+}
+
+/* Return a pointer to the remaining part of the selection data, given
+ a pointer to a struct selection_data and an offset in items. Place
+ the number of items remaining in REMAINING. Garbage collection
+ must not happen, or the returned pointer becomes invalid. */
+
+static unsigned char *
+selection_data_for_offset (struct selection_data *data,
+ long offset, size_t *remaining)
{
- int identifier;
- Display *display;
- Window window;
- Atom property;
- int desired_state;
- bool arrived;
- struct prop_location *next;
-};
+ unsigned char *base;
+ size_t size;
-static int prop_location_identifier;
+ if (!NILP (data->string))
+ {
+ base = SDATA (data->string);
+ size = SBYTES (data->string);
+ }
+ else
+ {
+ base = data->data;
+ size = data->size;
+ }
-static Lisp_Object property_change_reply;
+ if (offset >= size)
+ {
+ *remaining = 0;
+ return NULL;
+ }
-static struct prop_location *property_change_reply_object;
+ base += (offset * c_size_for_format (data->format));
+ *remaining = size - offset;
+ return base;
+}
-static struct prop_location *property_change_wait_list;
+/* Return the size, in bytes transferred to the X server, of
+ data->size items of selection data in data->format-bit
+ quantities. */
-static void
-set_property_change_object (struct prop_location *location)
+static size_t
+selection_data_size (struct selection_data *data)
{
- /* Input must be blocked so we don't get the event before we set these. */
- if (! input_blocked_p ())
- emacs_abort ();
- XSETCAR (property_change_reply, Qnil);
- property_change_reply_object = location;
+ size_t scratch;
+
+ if (!NILP (data->string))
+ return SBYTES (data->string);
+
+ switch (data->format)
+ {
+ case 8:
+ return (size_t) data->size;
+
+ case 16:
+ if (INT_MULTIPLY_WRAPV (data->size, 2, &scratch))
+ return SIZE_MAX;
+
+ return scratch;
+
+ case 32:
+ if (INT_MULTIPLY_WRAPV (data->size, 4, &scratch))
+ return SIZE_MAX;
+
+ return scratch;
+ }
+
+ /* The specified format is invalid. */
+ emacs_abort ();
}
-
-/* Send the reply to a selection request event EVENT. */
+/* Return whether or not another outstanding selection transfer is
+ still selecting for events on the specified requestor window. */
-#ifdef TRACE_SELECTION
-static int x_reply_selection_request_cnt;
-#endif /* TRACE_SELECTION */
+static bool
+transfer_selecting_event (struct x_display_info *dpyinfo,
+ Window requestor)
+{
+ struct transfer *next;
+
+ next = outstanding_transfers.next;
+ for (; next != &outstanding_transfers; next = next->next)
+ {
+ if (next->requestor == requestor
+ && next->dpyinfo == dpyinfo)
+ return true;
+ }
+
+ return false;
+}
+
+/* Cancel the specified selection transfer. When called by
+ `start_transfer', the transfer may be partially formed. */
static void
-x_reply_selection_request (struct selection_input_event *event,
- struct x_display_info *dpyinfo)
+x_cancel_selection_transfer (struct transfer *transfer)
{
- XEvent reply_base;
- XSelectionEvent *reply = &(reply_base.xselection);
- Display *display = SELECTION_EVENT_DISPLAY (event);
- Window window = SELECTION_EVENT_REQUESTOR (event);
- ptrdiff_t bytes_remaining;
- int max_bytes = selection_quantum (display);
- specpdl_ref count = SPECPDL_INDEX ();
- struct selection_data *cs;
- struct x_selection_request *frame;
+ xfree (transfer->data.data);
- frame = selection_request_stack;
+ if (transfer->next)
+ {
+ transfer->next->last = transfer->last;
+ transfer->last->next = transfer->next;
+ }
- reply->type = SelectionNotify;
- reply->display = display;
- reply->requestor = window;
- reply->selection = SELECTION_EVENT_SELECTION (event);
- reply->time = SELECTION_EVENT_TIME (event);
- reply->target = SELECTION_EVENT_TARGET (event);
- reply->property = SELECTION_EVENT_PROPERTY (event);
- if (reply->property == None)
- reply->property = reply->target;
+ if (transfer->flags & SELECTED_EVENTS
+ && !transfer_selecting_event (transfer->dpyinfo,
+ transfer->requestor)
+ /* This can be called from x_delete_display. */
+ && transfer->dpyinfo->display)
+ {
+ /* Ignore errors generated by the change window request in case
+ the window has gone away. */
+ block_input ();
+ x_ignore_errors_for_next_request (transfer->dpyinfo, 0);
+ XSelectInput (transfer->dpyinfo->display,
+ transfer->requestor, NoEventMask);
+ x_stop_ignoring_errors (transfer->dpyinfo);
+ unblock_input ();
+ }
- block_input ();
- /* The protected block contains wait_for_property_change, which can
- run random lisp code (process handlers) or signal. Therefore, we
- put the x_uncatch_errors call in an unwind. */
- record_unwind_protect_void (x_catch_errors_unwind);
- x_catch_errors (display);
+ cancel_atimer (transfer->timeout);
+ xfree (transfer);
+}
- /* Loop over converted selections, storing them in the requested
- properties. If data is large, only store the first N bytes
- (section 2.7.2 of ICCCM). Note that we store the data for a
- MULTIPLE request in the opposite order; the ICCM says only that
- the conversion itself must be done in the same order. */
- for (cs = frame->converted_selections; cs; cs = cs->next)
+static void
+x_selection_transfer_timeout (struct atimer *atimer)
+{
+ struct transfer *transfer;
+
+ transfer = atimer->client_data;
+ x_cancel_selection_transfer (transfer);
+}
+
+/* Start a selection transfer to write the specified selection data to
+ its requestor. If the data is small enough, write it to the
+ requestor window and return. Otherwise, start INCR transfer and
+ begin listening for PropertyNotify events on the requestor. */
+
+static void
+x_start_selection_transfer (struct x_display_info *dpyinfo, Window requestor,
+ struct selection_data *data)
+{
+ struct transfer *transfer;
+ intmax_t timeout;
+ intmax_t secs;
+ int nsecs;
+ size_t remaining, max_size;
+ unsigned char *xdata;
+ unsigned long data_size;
+
+ timeout = max (0, x_selection_timeout);
+ secs = timeout / 1000;
+ nsecs = (timeout % 1000) * 1000000;
+
+ transfer = xzalloc (sizeof *transfer);
+ transfer->requestor = requestor;
+ transfer->dpyinfo = dpyinfo;
+
+ transfer->timeout = start_atimer (ATIMER_RELATIVE,
+ make_timespec (secs, nsecs),
+ x_selection_transfer_timeout,
+ transfer);
+
+ /* Note that DATA is copied into transfer. DATA->data is then set
+ to NULL, giving the struct transfer ownership over the selection
+ data. */
+
+ transfer->data = *data;
+ data->data = NULL;
+
+ /* Finally, transfer now holds a reference to data->string, if it is
+ present. GC cannot be allowed to happen until this function
+ returns. */
+ data->string = Qnil;
+
+ /* Now, try to write the selection data. If it is bigger than
+ selection_quantum (dpyinfo->display), start incremental transfer
+ and link the transfer onto the list of pending selections.
+ Otherwise, write the transfer at once. */
+
+ max_size = selection_quantum (dpyinfo->display);
+
+ TRACE3 (" x_start_selection_transfer: transferring to 0x%lx. "
+ "transfer consists of %zu bytes, quantum being %zu",
+ requestor, selection_data_size (&transfer->data),
+ max_size);
+
+ if (selection_data_size (&transfer->data) > max_size)
{
- if (cs->property == None)
- continue;
+ /* Begin incremental selection transfer. First, calculate how
+ many elements it is ok to write for every ChangeProperty
+ request. */
+ transfer->items_per_request
+ = (max_size / x_size_for_format (transfer->data.format));
+ TRACE1 (" x_start_selection_transfer: starting incremental"
+ " selection transfer, with %zu items per request",
+ transfer->items_per_request);
+
+ /* Next, link the transfer onto the list of pending selection
+ transfers. */
+ transfer->next = outstanding_transfers.next;
+ transfer->last = &outstanding_transfers;
+ transfer->next->last = transfer;
+ transfer->last->next = transfer;
+
+ /* Find a valid (non-zero) serial for the selection transfer.
+ Any asynchronously trapped errors will then cause the
+ selection transfer to be cancelled. */
+ transfer->serial = (++selection_serial
+ ? selection_serial
+ : ++selection_serial);
+
+ /* Now, write the INCR property to begin incremental selection
+ transfer. offset is currently 0. */
+
+ data_size = selection_data_size (&transfer->data);
+
+ /* Set SELECTED_EVENTS before the actual XSelectInput
+ request. */
+ transfer->flags |= SELECTED_EVENTS;
+
+ x_ignore_errors_for_next_request (dpyinfo, transfer->serial);
+ XChangeProperty (dpyinfo->display, requestor,
+ transfer->data.property,
+ dpyinfo->Xatom_INCR, 32, PropModeReplace,
+ (unsigned char *) &data_size, 1);
+
+ /* This assumes that Emacs is not selecting for any other events
+ from the requestor!
+
+ If the holder of some manager selections (i.e. the settings
+ manager) asks Emacs for selection data, things will subtly go
+ wrong. */
+ XSelectInput (dpyinfo->display, requestor, PropertyChangeMask);
+ x_stop_ignoring_errors (dpyinfo);
+ }
+ else
+ {
+ /* Write the property data now. */
+ xdata = selection_data_for_offset (&transfer->data,
+ 0, &remaining);
+ eassert (remaining <= INT_MAX);
+
+ TRACE1 (" x_start_selection_transfer: writing"
+ " %zu elements directly to requestor window",
+ remaining);
+
+ x_ignore_errors_for_next_request (dpyinfo, 0);
+ XChangeProperty (dpyinfo->display, requestor,
+ transfer->data.property,
+ transfer->data.type,
+ transfer->data.format,
+ PropModeReplace, xdata, remaining);
+ x_stop_ignoring_errors (dpyinfo);
+
+ /* Next, get rid of the transfer. */
+ x_cancel_selection_transfer (transfer);
+ }
+}
- bytes_remaining = cs->size;
- bytes_remaining *= cs->format >> 3;
- if (bytes_remaining <= max_bytes)
- {
- /* Send all the data at once, with minimal handshaking. */
- TRACE1 ("Sending all %"pD"d bytes", bytes_remaining);
- XChangeProperty (display, window, cs->property,
- cs->type, cs->format, PropModeReplace,
- cs->data, cs->size);
- }
- else
- {
- /* Send an INCR tag to initiate incremental transfer. */
- long value[1];
-
- TRACE2 ("Start sending %"pD"d bytes incrementally (%s)",
- bytes_remaining, XGetAtomName (display, cs->property));
- cs->wait_object
- = expect_property_change (display, window, cs->property,
- PropertyDelete);
-
- /* XChangeProperty expects an array of long even if long is
- more than 32 bits. */
- value[0] = min (bytes_remaining, X_LONG_MAX);
- XChangeProperty (display, window, cs->property,
- dpyinfo->Xatom_INCR, 32, PropModeReplace,
- (unsigned char *) value, 1);
- XSelectInput (display, window, PropertyChangeMask);
- }
+/* Write out the next piece of data that is part of the specified
+ selection transfer. If no more data remains to be written, write
+ the EOF property and complete the transfer. */
+
+static void
+x_continue_selection_transfer (struct transfer *transfer)
+{
+ size_t remaining;
+ unsigned char *xdata;
+
+ xdata = selection_data_for_offset (&transfer->data,
+ transfer->offset,
+ &remaining);
+ remaining = min (remaining, transfer->items_per_request);
+
+ if (!remaining)
+ {
+ /* The transfer is finished. Write zero-length property data to
+ signal EOF and remove the transfer. */
+ TRACE0 (" x_continue_selection_transfer: writing 0 items to"
+ " indicate EOF");
+ x_ignore_errors_for_next_request (transfer->dpyinfo, 0);
+ XChangeProperty (transfer->dpyinfo->display,
+ transfer->requestor,
+ transfer->data.property,
+ transfer->data.type,
+ transfer->data.format,
+ PropModeReplace,
+ NULL, 0);
+ x_stop_ignoring_errors (transfer->dpyinfo);
+ TRACE0 (" x_continue_selection_transfer: done sending incrementally");
+
+ x_cancel_selection_transfer (transfer);
+ }
+ else
+ {
+ TRACE2 (" x_continue_selection_transfer: writing %zu items"
+ "; current offset is %zu", remaining, transfer->offset);
+ eassert (remaining <= INT_MAX);
+
+ transfer->offset += remaining;
+
+ x_ignore_errors_for_next_request (transfer->dpyinfo,
+ transfer->serial);
+ XChangeProperty (transfer->dpyinfo->display,
+ transfer->requestor,
+ transfer->data.property,
+ transfer->data.type,
+ transfer->data.format,
+ PropModeReplace, xdata,
+ remaining);
+ x_stop_ignoring_errors (transfer->dpyinfo);
}
+}
- /* Now issue the SelectionNotify event. */
- XSendEvent (display, window, False, 0, &reply_base);
- XFlush (display);
+void
+x_remove_selection_transfers (struct x_display_info *dpyinfo)
+{
+ struct transfer *next, *last;
-#ifdef TRACE_SELECTION
- {
- char *sel = XGetAtomName (display, reply->selection);
- char *tgt = XGetAtomName (display, reply->target);
- TRACE3 ("Sent SelectionNotify: %s, target %s (%d)",
- sel, tgt, ++x_reply_selection_request_cnt);
- if (sel) XFree (sel);
- if (tgt) XFree (tgt);
- }
-#endif /* TRACE_SELECTION */
+ next = outstanding_transfers.next;
+ while (next != &outstanding_transfers)
+ {
+ last = next;
+ next = next->next;
- /* Finish sending the rest of each of the INCR values. This should
- be improved; there's a chance of deadlock if more than one
- subtarget in a MULTIPLE selection requires an INCR transfer, and
- the requestor and Emacs loop waiting on different transfers. */
- for (cs = frame->converted_selections; cs; cs = cs->next)
- if (cs->wait_object)
- {
- int format_bytes = cs->format / 8;
- bool had_errors_p = x_had_errors_p (display);
+ if (last->dpyinfo == dpyinfo)
+ x_cancel_selection_transfer (last);
+ }
+}
- /* Must set this inside block_input (). unblock_input may read
- events and setting property_change_reply in
- wait_for_property_change is then too late. */
- set_property_change_object (cs->wait_object);
- unblock_input ();
+/* Handle an X error generated trying to write to a window. SERIAL
+ identifies the outstanding incremental selection transfer, which is
+ immediately removed. */
- bytes_remaining = cs->size;
- bytes_remaining *= format_bytes;
+void
+x_handle_selection_error (unsigned int serial, XErrorEvent *error)
+{
+ struct transfer *next, *last;
- /* Wait for the requestor to ack by deleting the property.
- This can run Lisp code (process handlers) or signal. */
- if (! had_errors_p)
- {
- TRACE1 ("Waiting for ACK (deletion of %s)",
- XGetAtomName (display, cs->property));
- wait_for_property_change (cs->wait_object);
- }
- else
- unexpect_property_change (cs->wait_object);
+ if (error->error_code != BadWindow)
+ /* The error was not caused by the window going away. As such,
+ Emacs must deselect for PropertyChangeMask from the requestor
+ window, which isn't safe here. Return and wait for the timeout
+ to run. */
+ return;
- while (bytes_remaining)
- {
- int i = ((bytes_remaining < max_bytes)
- ? bytes_remaining
- : max_bytes) / format_bytes;
- block_input ();
-
- cs->wait_object
- = expect_property_change (display, window, cs->property,
- PropertyDelete);
-
- TRACE1 ("Sending increment of %d elements", i);
- TRACE1 ("Set %s to increment data",
- XGetAtomName (display, cs->property));
-
- /* Append the next chunk of data to the property. */
- XChangeProperty (display, window, cs->property,
- cs->type, cs->format, PropModeAppend,
- cs->data, i);
- bytes_remaining -= i * format_bytes;
- cs->data += i * ((cs->format == 32) ? sizeof (long)
- : format_bytes);
- XFlush (display);
- had_errors_p = x_had_errors_p (display);
- /* See comment above about property_change_reply. */
- set_property_change_object (cs->wait_object);
- unblock_input ();
-
- if (had_errors_p) break;
-
- /* Wait for the requestor to ack this chunk by deleting
- the property. This can run Lisp code or signal. */
- TRACE1 ("Waiting for increment ACK (deletion of %s)",
- XGetAtomName (display, cs->property));
- wait_for_property_change (cs->wait_object);
- }
+ next = outstanding_transfers.next;
+ while (next != &outstanding_transfers)
+ {
+ last = next;
+ next = next->next;
- /* Now write a zero-length chunk to the property to tell the
- requestor that we're done. */
- block_input ();
- if (! waiting_for_other_props_on_window (display, window))
- XSelectInput (display, window, 0);
-
- TRACE1 ("Set %s to a 0-length chunk to indicate EOF",
- XGetAtomName (display, cs->property));
- XChangeProperty (display, window, cs->property,
- cs->type, cs->format, PropModeReplace,
- cs->data, 0);
- TRACE0 ("Done sending incrementally");
- }
+ if (last->serial == serial)
+ {
+ /* Clear SELECTED_EVENTS, so x_cancel_selection_transfer
+ will not make X requests. That is unsafe inside an error
+ handler, and unnecessary because the window has already
+ gone. */
+ last->flags &= ~SELECTED_EVENTS;
+ x_cancel_selection_transfer (last);
+ }
+ }
+}
- /* rms, 2003-01-03: I think I have fixed this bug. */
- /* The window we're communicating with may have been deleted
- in the meantime (that's a real situation from a bug report).
- In this case, there may be events in the event queue still
- referring to the deleted window, and we'll get a BadWindow error
- in XTread_socket when processing the events. I don't have
- an idea how to fix that. gerd, 2001-01-98. */
- /* 2004-09-10: XSync and UNBLOCK so that possible protocol errors are
- delivered before uncatch errors. */
- XSync (display, False);
- unblock_input ();
+/* Send the reply to a selection request event EVENT. */
+
+static void
+x_reply_selection_request (struct selection_input_event *event,
+ struct x_display_info *dpyinfo)
+{
+ XEvent message;
+ struct selection_data *cs;
+ struct x_selection_request *frame;
- /* GTK queues events in addition to the queue in Xlib. So we
- UNBLOCK to enter the event loop and get possible errors delivered,
- and then BLOCK again because x_uncatch_errors requires it. */
block_input ();
- /* This calls x_uncatch_errors. */
- unbind_to (count, Qnil);
+ frame = selection_request_stack;
+
+ message.xselection.type = SelectionNotify;
+ message.xselection.display = dpyinfo->display;
+ message.xselection.requestor = SELECTION_EVENT_REQUESTOR (event);
+ message.xselection.selection = SELECTION_EVENT_SELECTION (event);
+ message.xselection.time = SELECTION_EVENT_TIME (event);
+ message.xselection.target = SELECTION_EVENT_TARGET (event);
+ message.xselection.property = SELECTION_EVENT_PROPERTY (event);
+
+ if (message.xselection.property == None)
+ message.xselection.property = message.xselection.target;
+
+ /* For each of the converted selections, start a write transfer from
+ Emacs to the requestor. */
+ for (cs = frame->converted_selections; cs; cs = cs->next)
+ x_start_selection_transfer (dpyinfo,
+ SELECTION_EVENT_REQUESTOR (event),
+ cs);
+
+
+ /* Send the SelectionNotify event to the requestor, telling it that
+ the property data has arrived. */
+ x_ignore_errors_for_next_request (dpyinfo, 0);
+ XSendEvent (dpyinfo->display, SELECTION_EVENT_REQUESTOR (event),
+ False, NoEventMask, &message);
+ x_stop_ignoring_errors (dpyinfo);
unblock_input ();
}
-
-/* Handle a SelectionRequest event EVENT.
- This is called from keyboard.c when such an event is found in the queue. */
+
+/* Handle a SelectionRequest event EVENT. This is called from
+ keyboard.c when such an event is found in the queue. */
static void
x_handle_selection_request (struct selection_input_event *event)
@@ -892,7 +1182,9 @@ x_handle_selection_request (struct selection_input_event *event)
ptrdiff_t j, nselections;
struct selection_data cs;
- if (property == None) goto DONE;
+ if (property == None)
+ goto DONE;
+
multprop
= x_get_window_property_as_lisp_data (dpyinfo, requestor, property,
QMULTIPLE, selection, true);
@@ -904,23 +1196,24 @@ x_handle_selection_request (struct selection_input_event *event)
/* Perform conversions. This can signal. */
for (j = 0; j < nselections; j++)
{
- Lisp_Object subtarget = AREF (multprop, 2*j);
+ Lisp_Object subtarget = AREF (multprop, 2 * j);
Atom subproperty = symbol_to_x_atom (dpyinfo,
AREF (multprop, 2*j+1));
bool subsuccess = false;
if (subproperty != None)
subsuccess = x_convert_selection (selection_symbol, subtarget,
- subproperty, true, dpyinfo,
+ subproperty, dpyinfo,
use_alternate);
if (!subsuccess)
- ASET (multprop, 2*j+1, Qnil);
+ ASET (multprop, 2 * j + 1, Qnil);
}
+
/* Save conversion results */
lisp_data_to_selection_data (dpyinfo, multprop, &cs);
- /* If cs.type is ATOM, change it to ATOM_PAIR. This is because
- the parameters to a MULTIPLE are ATOM_PAIRs. */
+ /* If cs.type is ATOM, change it to ATOM_PAIR. This is
+ because the parameters to a MULTIPLE are ATOM_PAIRs. */
if (cs.type == XA_ATOM)
cs.type = dpyinfo->Xatom_ATOM_PAIR;
@@ -929,27 +1222,29 @@ x_handle_selection_request (struct selection_input_event *event)
cs.type, cs.format, PropModeReplace,
cs.data, cs.size);
success = true;
+
+ xfree (cs.data);
}
else
{
if (property == None)
property = SELECTION_EVENT_TARGET (event);
+
success = x_convert_selection (selection_symbol,
target_symbol, property,
- false, dpyinfo,
- use_alternate);
+ dpyinfo, use_alternate);
}
DONE:
- if (pushed)
- selection_request_stack->converted = true;
-
if (success)
x_reply_selection_request (event, dpyinfo);
else
x_decline_selection_request (event);
+ if (pushed)
+ selection_request_stack->converted = true;
+
/* Run the `x-sent-selection-functions' abnormal hook. */
if (!NILP (Vx_sent_selection_functions)
&& !BASE_EQ (Vx_sent_selection_functions, Qunbound))
@@ -960,19 +1255,18 @@ x_handle_selection_request (struct selection_input_event *event)
REALLY_DONE:
unbind_to (count, Qnil);
+ return;
}
/* Perform the requested selection conversion, and write the data to
the converted_selections linked list, where it can be accessed by
- x_reply_selection_request. If FOR_MULTIPLE, write out
- the data even if conversion fails, using conversion_fail_tag.
+ x_reply_selection_request.
Return true if successful. */
static bool
-x_convert_selection (Lisp_Object selection_symbol,
- Lisp_Object target_symbol, Atom property,
- bool for_multiple, struct x_display_info *dpyinfo,
+x_convert_selection (Lisp_Object selection_symbol, Lisp_Object target_symbol,
+ Atom property, struct x_display_info *dpyinfo,
bool use_alternate)
{
Lisp_Object lisp_selection;
@@ -988,33 +1282,16 @@ x_convert_selection (Lisp_Object selection_symbol,
/* A nil return value means we can't perform the conversion. */
if (NILP (lisp_selection)
|| (CONSP (lisp_selection) && NILP (XCDR (lisp_selection))))
- {
- if (for_multiple)
- {
- cs = xmalloc (sizeof *cs);
- cs->data = ((unsigned char *)
- &selection_request_stack->conversion_fail_tag);
- cs->size = 1;
- cs->format = 32;
- cs->type = XA_ATOM;
- cs->nofree = true;
- cs->property = property;
- cs->wait_object = NULL;
- cs->next = frame->converted_selections;
- frame->converted_selections = cs;
- }
-
- return false;
- }
+ return false;
/* Otherwise, record the converted selection to binary. */
cs = xmalloc (sizeof *cs);
cs->data = NULL;
- cs->nofree = true;
+ cs->string = Qnil;
cs->property = property;
- cs->wait_object = NULL;
cs->next = frame->converted_selections;
frame->converted_selections = cs;
+
lisp_data_to_selection_data (dpyinfo, lisp_selection, cs);
return true;
}
@@ -1274,6 +1551,10 @@ void
x_handle_property_notify (const XPropertyEvent *event)
{
struct prop_location *rest;
+ struct transfer *next;
+#ifdef TRACE_SELECTION
+ char *name;
+#endif
for (rest = property_change_wait_list; rest; rest = rest->next)
{
@@ -1283,9 +1564,16 @@ x_handle_property_notify (const XPropertyEvent *event)
&& rest->display == event->display
&& rest->desired_state == event->state)
{
+#ifdef TRACE_SELECTION
+ name = XGetAtomName (event->display, event->atom);
+
TRACE2 ("Expected %s of property %s",
(event->state == PropertyDelete ? "deletion" : "change"),
- XGetAtomName (event->display, event->atom));
+ name ? name : "unknown");
+
+ if (name)
+ XFree (name);
+#endif
rest->arrived = true;
@@ -1297,6 +1585,26 @@ x_handle_property_notify (const XPropertyEvent *event)
return;
}
}
+
+ /* Look for a property change for an outstanding selection
+ transfer. */
+ next = outstanding_transfers.next;
+ while (next != &outstanding_transfers)
+ {
+ if (next->dpyinfo->display == event->display
+ && next->requestor == event->window
+ && next->data.property == event->atom
+ && event->state == PropertyDelete)
+ {
+ TRACE1 ("Expected PropertyDelete event arrived from the"
+ " requestor window %lx", next->requestor);
+
+ x_continue_selection_transfer (next);
+ return;
+ }
+
+ next = next->next;
+ }
}
static void
@@ -1450,10 +1758,10 @@ x_get_window_property (Display *display, Window window, Atom property,
/* Maximum value for TOTAL_SIZE. It cannot exceed PTRDIFF_MAX - 1
and SIZE_MAX - 1, for an extra byte at the end. And it cannot
exceed LONG_MAX * X_LONG_SIZE, for XGetWindowProperty. */
- ptrdiff_t total_size_max =
- ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX
- ? min (PTRDIFF_MAX, SIZE_MAX) - 1
- : LONG_MAX * x_long_size);
+ ptrdiff_t total_size_max
+ = ((min (PTRDIFF_MAX, SIZE_MAX) - 1) / x_long_size < LONG_MAX
+ ? min (PTRDIFF_MAX, SIZE_MAX) - 1
+ : LONG_MAX * x_long_size);
block_input ();
@@ -1946,10 +2254,14 @@ static void
lisp_data_to_selection_data (struct x_display_info *dpyinfo,
Lisp_Object obj, struct selection_data *cs)
{
- Lisp_Object type = Qnil;
+ Lisp_Object type;
+ char **name_buffer;
+
+ USE_SAFE_ALLOCA;
+
+ type = Qnil;
eassert (cs != NULL);
- cs->nofree = false;
if (CONSP (obj) && SYMBOLP (XCAR (obj)))
{
@@ -1959,8 +2271,10 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
obj = XCAR (obj);
}
+ /* This is not the same as declining. */
+
if (EQ (obj, QNULL) || (EQ (type, QNULL)))
- { /* This is not the same as declining */
+ {
cs->format = 32;
cs->size = 0;
cs->data = NULL;
@@ -1971,12 +2285,14 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
if (SCHARS (obj) < SBYTES (obj))
/* OBJ is a multibyte string containing a non-ASCII char. */
signal_error ("Non-ASCII string must be encoded in advance", obj);
+
if (NILP (type))
type = QSTRING;
+
cs->format = 8;
- cs->size = SBYTES (obj);
- cs->data = SDATA (obj);
- cs->nofree = true;
+ cs->size = -1;
+ cs->data = NULL;
+ cs->string = obj;
}
else if (SYMBOLP (obj))
{
@@ -2048,8 +2364,19 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
x_atoms = data;
cs->format = 32;
cs->size = size;
- for (i = 0; i < size; i++)
- x_atoms[i] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
+
+ if (size == 1)
+ x_atoms[0] = symbol_to_x_atom (dpyinfo, AREF (obj, i));
+ else
+ {
+ SAFE_NALLOCA (name_buffer, sizeof *x_atoms, size);
+
+ for (i = 0; i < size; i++)
+ name_buffer[i] = SSDATA (SYMBOL_NAME (AREF (obj, i)));
+
+ x_intern_atoms (dpyinfo, name_buffer, size,
+ x_atoms);
+ }
}
else
/* This vector is an INTEGER set, or something like it */
@@ -2091,6 +2418,8 @@ lisp_data_to_selection_data (struct x_display_info *dpyinfo,
signal_error (/* Qselection_error */ "Unrecognized selection data", obj);
cs->type = symbol_to_x_atom (dpyinfo, type);
+
+ SAFE_FREE ();
}
static Lisp_Object
@@ -2618,8 +2947,8 @@ x_check_property_data (Lisp_Object data)
XClientMessageEvent). */
void
-x_fill_property_data (Display *dpy, Lisp_Object data, void *ret,
- int nelements_max, int format)
+x_fill_property_data (struct x_display_info *dpyinfo, Lisp_Object data,
+ void *ret, int nelements_max, int format)
{
unsigned long val;
unsigned long *d32 = (unsigned long *) ret;
@@ -2654,7 +2983,7 @@ x_fill_property_data (Display *dpy, Lisp_Object data, void *ret,
else if (STRINGP (o))
{
block_input ();
- val = XInternAtom (dpy, SSDATA (o), False);
+ val = x_intern_cached_atom (dpyinfo, SSDATA (o), false);
unblock_input ();
}
else
@@ -2942,7 +3271,7 @@ x_send_client_event (Lisp_Object display, Lisp_Object dest, Lisp_Object from,
memset (event.xclient.data.l, 0, sizeof (event.xclient.data.l));
/* event.xclient.data can hold 20 chars, 10 shorts, or 5 longs. */
- x_fill_property_data (dpyinfo->display, values, event.xclient.data.b,
+ x_fill_property_data (dpyinfo, values, event.xclient.data.b,
5 * 32 / event.xclient.format,
event.xclient.format);
@@ -3002,10 +3331,11 @@ syms_of_xselect (void)
reading_selection_reply = Fcons (Qnil, Qnil);
staticpro (&reading_selection_reply);
-
staticpro (&property_change_reply);
- /* FIXME: Duplicate definition in nsselect.c. */
+ outstanding_transfers.next = &outstanding_transfers;
+ outstanding_transfers.last = &outstanding_transfers;
+
DEFVAR_LISP ("selection-converter-alist", Vselection_converter_alist,
doc: /* An alist associating X Windows selection-types with functions.
These functions are called to convert the selection, with three args:
@@ -3120,9 +3450,43 @@ Note that this does not affect setting or owning selections. */);
static void
syms_of_xselect_for_pdumper (void)
{
+ outstanding_transfers.next = &outstanding_transfers;
+ outstanding_transfers.last = &outstanding_transfers;
+
reading_selection_window = 0;
reading_which_selection = 0;
property_change_wait_list = 0;
prop_location_identifier = 0;
property_change_reply = Fcons (Qnil, Qnil);
}
+
+void
+mark_xselect (void)
+{
+ struct transfer *next;
+ struct x_selection_request *frame;
+ struct selection_data *cs;
+
+ /* Mark all the strings being used as selection data. A string that
+ is still reachable is always reachable via either the selection
+ request stack or the list of outstanding transfers. */
+
+ next = outstanding_transfers.next;
+
+ if (!next)
+ /* syms_of_xselect has not yet been called. */
+ return;
+
+ while (next != &outstanding_transfers)
+ {
+ mark_object (next->data.string);
+ next = next->next;
+ }
+
+ frame = selection_request_stack;
+ for (; frame; frame = frame->last)
+ {
+ for (cs = frame->converted_selections; cs; cs = cs->next)
+ mark_object (cs->string);
+ }
+}
diff --git a/src/xterm.c b/src/xterm.c
index a4ce228e9e6..1eef8e7a724 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -26,6 +26,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
contains subroutines comprising the redisplay interface, setting up
scroll bars and widgets, and handling input.
+ X WINDOW SYSTEM
+
+ The X Window System is a windowing system for bitmap graphics
+ displays which originated at MIT in 1984. Version 11, which is
+ currently supported by Emacs, first appeared in September 1987.
+
+ X has a long history and has been developed by many different
+ organizations over the years; at present, it is being primarily
+ developed by the X.Org Foundation. It is the main window system
+ that Emacs is developed and tested against, and X version 10 was
+ the first window system that Emacs was ported to. As a consequence
+ of its age and wide availability, X contains many idiosyncrasies,
+ but that has not prevented it from becoming the dominant free
+ window system, and the platform of reference for all GUI code in
+ Emacs.
+
Some of what is explained below also applies to the other window
systems that Emacs supports, to varying degrees. YMMV.
@@ -555,7 +571,56 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
drop happening with the primary selection and synthetic button
events (see `x_dnd_do_unsupported_drop'). That function implements
the OffiX drag-and-drop protocol by default. See
- `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details. */
+ `x-dnd-handle-unsupported-drop' in `x-dnd.el' for more details.
+
+ DISPLAY ERROR HANDLING
+
+ While error handling under X was originally designed solely as a
+ mechanism for the X server to report fatal errors to clients, most
+ clients (including Emacs) have adopted a system of "error traps" to
+ handle or discard these errors as they arrive. Discarding errors is
+ usually necessary when Emacs performs an X request that might fail:
+ for example, sending a message to a window that may no longer exist,
+ or might not exist at all. Handling errors is then necessary when
+ the detailed error must be reported to another piece of code: for
+ example, as a Lisp error.
+
+ It is not acceptable for Emacs to crash when it is sent invalid data
+ by another client, or by Lisp. As a result, errors must be caught
+ around Xlib functions generating requests containing resource
+ identifiers that could potentially be invalid, such as window or
+ atom identifiers provided in a client message from another program,
+ or a child window ID obtained through XTranslateCoordinates that may
+ refer to a window that has been deleted in the meantime.
+
+ There are two sets of functions used to perform this "error
+ trapping". Which one should be used depends on what kind of
+ processing must be done on the error. The first consists of the
+ functions `x_ignore_errors_for_next_request' and
+ `x_stop_ignoring_errors', which ignore errors generated by requests
+ made in between a call to the first function and a corresponding
+ call to the second. They should be used for simple asynchronous
+ requests that do not require a reply from the X server: using them
+ instead of the second set improves performance, as they simply
+ record a range of request serials to ignore errors from, instead of
+ synchronizing with the X server to handle errors.
+
+ The second set consists of the following functions:
+
+ - x_catch_errors_with_handler
+ - x_catch_errors
+ - x_uncatch_errors_after_check
+ - x_uncatch_errors
+ - x_check_errors
+ - x_had_errors_p
+ - x_clear_errors
+
+ Callers using this set should consult the comment(s) on top of the
+ aformentioned functions. They should not be used when the requests
+ being made do not require roundtrips to the X server, and obtaining
+ the details of any error generated is unecessary, as
+ `x_uncatch_errors' will always synchronize with the X server, which
+ is a potentially slow operation. */
#include <config.h>
#include <stdlib.h>
@@ -574,7 +639,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef USE_XCB
#include <xcb/xproto.h>
#include <xcb/xcb.h>
-#include <xcb/xcb_aux.h>
#endif
/* If we have Xfixes extension, use it for pointer blanking. */
@@ -1052,6 +1116,20 @@ static const struct x_atom_ref x_atom_refs[] =
/* Old OffiX (a.k.a. old KDE) drop protocol support. */
ATOM_REFS_INIT ("DndProtocol", Xatom_DndProtocol)
ATOM_REFS_INIT ("_DND_PROTOCOL", Xatom_DND_PROTOCOL)
+ /* Here are some atoms that are not actually used from C, just
+ defined to make replying to selection requests fast. */
+ ATOM_REFS_INIT ("text/plain;charset=utf-8", Xatom_text_plain_charset_utf_8)
+ ATOM_REFS_INIT ("LENGTH", Xatom_LENGTH)
+ ATOM_REFS_INIT ("FILE_NAME", Xatom_FILE_NAME)
+ ATOM_REFS_INIT ("CHARACTER_POSITION", Xatom_CHARACTER_POSITION)
+ ATOM_REFS_INIT ("LINE_NUMBER", Xatom_LINE_NUMBER)
+ ATOM_REFS_INIT ("COLUMN_NUMBER", Xatom_COLUMN_NUMBER)
+ ATOM_REFS_INIT ("OWNER_OS", Xatom_OWNER_OS)
+ ATOM_REFS_INIT ("HOST_NAME", Xatom_HOST_NAME)
+ ATOM_REFS_INIT ("USER", Xatom_USER)
+ ATOM_REFS_INIT ("CLASS", Xatom_CLASS)
+ ATOM_REFS_INIT ("NAME", Xatom_NAME)
+ ATOM_REFS_INIT ("SAVE_TARGETS", Xatom_SAVE_TARGETS)
};
enum
@@ -2509,7 +2587,7 @@ xm_send_drop_message (struct x_display_info *dpyinfo, Window source,
*((uint32_t *) &msg.xclient.data.b[12]) = dmsg->index_atom;
*((uint32_t *) &msg.xclient.data.b[16]) = dmsg->source_window;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -2536,7 +2614,7 @@ xm_send_top_level_enter_message (struct x_display_info *dpyinfo, Window source,
msg.xclient.data.b[18] = 0;
msg.xclient.data.b[19] = 0;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -2567,7 +2645,7 @@ xm_send_drag_motion_message (struct x_display_info *dpyinfo, Window source,
msg.xclient.data.b[18] = 0;
msg.xclient.data.b[19] = 0;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -2626,7 +2704,7 @@ xm_send_top_level_leave_message (struct x_display_info *dpyinfo, Window source,
msg.xclient.data.b[18] = 0;
msg.xclient.data.b[19] = 0;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -2921,7 +2999,7 @@ x_dnd_free_toplevels (bool display_alive)
if (n_windows)
{
eassume (dpyinfo);
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
for (i = 0; i < n_windows; ++i)
{
@@ -3058,7 +3136,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
0, 0);
get_property_cookies[i]
= xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
- (xcb_atom_t) dpyinfo->Xatom_wm_state, XCB_ATOM_ANY,
+ (xcb_atom_t) dpyinfo->Xatom_wm_state, 0,
0, 2);
xm_property_cookies[i]
= xcb_get_property (dpyinfo->xcb_connection, 0, (xcb_window_t) toplevels[i],
@@ -3069,7 +3147,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
= xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) toplevels[i],
(xcb_atom_t) dpyinfo->Xatom_net_frame_extents,
- XCB_ATOM_CARDINAL, 0, 4);
+ XA_CARDINAL, 0, 4);
get_geometry_cookies[i]
= xcb_get_geometry (dpyinfo->xcb_connection, (xcb_window_t) toplevels[i]);
@@ -3197,7 +3275,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
{
if (xcb_get_property_value_length (extent_property_reply) == 16
&& extent_property_reply->format == 32
- && extent_property_reply->type == XCB_ATOM_CARDINAL)
+ && extent_property_reply->type == XA_CARDINAL)
{
fextents = xcb_get_property_value (extent_property_reply);
frame_extents[0] = fextents[0];
@@ -3291,7 +3369,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
if (dpyinfo->xshape_supported_p)
{
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XShapeSelectInput (dpyinfo->display,
toplevels[i],
ShapeNotifyMask);
@@ -3456,7 +3534,7 @@ x_dnd_compute_toplevels (struct x_display_info *dpyinfo)
}
#endif
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSelectInput (dpyinfo->display, toplevels[i],
(attrs.your_event_mask
| StructureNotifyMask
@@ -3571,13 +3649,13 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) wdesc,
(xcb_atom_t) dpyinfo->Xatom_XdndProxy,
- XCB_ATOM_WINDOW, 0, 1);
+ XA_WINDOW, 0, 1);
if (proto_out)
xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) wdesc,
(xcb_atom_t) dpyinfo->Xatom_XdndAware,
- XCB_ATOM_ATOM, 0, 1);
+ XA_ATOM, 0, 1);
if (proxy_out)
{
@@ -3589,7 +3667,7 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
else
{
if (reply->format == 32
- && reply->type == XCB_ATOM_WINDOW
+ && reply->type == XA_WINDOW
&& (xcb_get_property_value_length (reply) >= 4))
*proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
@@ -3607,7 +3685,7 @@ x_dnd_get_proxy_proto (struct x_display_info *dpyinfo, Window wdesc,
else
{
if (reply->format == 32
- && reply->type == XCB_ATOM_ATOM
+ && reply->type == XA_ATOM
&& (xcb_get_property_value_length (reply) >= 4))
*proto_out = (int) *(xcb_atom_t *) xcb_get_property_value (reply);
@@ -3791,15 +3869,15 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
wmstate_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) window,
(xcb_atom_t) dpyinfo->Xatom_wm_state,
- XCB_ATOM_ANY, 0, 2);
+ 0, 0, 2);
xdnd_proto_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) window,
(xcb_atom_t) dpyinfo->Xatom_XdndAware,
- XCB_ATOM_ATOM, 0, 1);
+ XA_ATOM, 0, 1);
xdnd_proxy_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) window,
(xcb_atom_t) dpyinfo->Xatom_XdndProxy,
- XCB_ATOM_WINDOW, 0, 1);
+ XA_WINDOW, 0, 1);
xm_style_cookie = xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) window,
(xcb_atom_t) dpyinfo->Xatom_MOTIF_DRAG_RECEIVER_INFO,
@@ -3846,7 +3924,7 @@ x_dnd_get_wm_state_and_proto (struct x_display_info *dpyinfo,
else
{
if (reply->format == 32
- && reply->type == XCB_ATOM_WINDOW
+ && reply->type == XA_WINDOW
&& (xcb_get_property_value_length (reply) >= 4))
*proxy_out = *(xcb_window_t *) xcb_get_property_value (reply);
@@ -3962,6 +4040,12 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
if (owner != FRAME_X_WINDOW (f))
return;
+ /* mouse-drag-and-drop-region will immediately deactivate the mark
+ after this is set. Make sure the primary selection is not
+ clobbered in that case by setting `deactivate-mark' to
+ Qdont_save. */
+ Vdeactivate_mark = Qdont_save;
+
event.xbutton.window = child;
event.xbutton.subwindow = None;
event.xbutton.x = dest_x;
@@ -3975,7 +4059,7 @@ x_dnd_do_unsupported_drop (struct x_display_info *dpyinfo,
event.xbutton.type = ButtonPress;
event.xbutton.time = before + 1;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, child,
True, ButtonPressMask, &event);
@@ -4487,7 +4571,7 @@ x_dnd_send_enter (struct frame *f, Window target, Window toplevel,
so we don't have to set it again. */
x_dnd_init_type_lists = true;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -4559,7 +4643,7 @@ x_dnd_send_position (struct frame *f, Window target, Window toplevel,
return;
}
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
@@ -4586,7 +4670,7 @@ x_dnd_send_leave (struct frame *f, Window target, Window toplevel)
x_dnd_waiting_for_status_window = None;
x_dnd_pending_send_position.type = 0;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
}
@@ -4619,7 +4703,7 @@ x_dnd_send_drop (struct frame *f, Window target, Window toplevel,
if (supported >= 1)
msg.xclient.data.l[2] = timestamp;
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (FRAME_X_DISPLAY (f), target, False, NoEventMask, &msg);
x_stop_ignoring_errors (dpyinfo);
return true;
@@ -6731,7 +6815,7 @@ x_set_frame_alpha (struct frame *f)
Do this unconditionally as this function is called on reparent when
alpha has not changed on the frame. */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
if (!FRAME_PARENT_FRAME (f))
{
@@ -6907,6 +6991,7 @@ static void
x_sync_wait_for_frame_drawn_event (struct frame *f)
{
XEvent event;
+ struct x_display_info *dpyinfo;
if (!FRAME_X_WAITING_FOR_DRAW (f)
/* The compositing manager can't draw a frame if it is
@@ -6914,6 +6999,8 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
|| !FRAME_VISIBLE_P (f))
return;
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
/* Wait for the frame drawn message to arrive. */
if (x_if_event (FRAME_X_DISPLAY (f), &event,
x_sync_is_frame_drawn_event, (XPointer) f,
@@ -6929,6 +7016,11 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
"been disabled\n");
FRAME_X_OUTPUT (f)->use_vsync_p = false;
+ /* Remove the compositor bypass property from the outer
+ window. */
+ XDeleteProperty (dpyinfo->display, FRAME_OUTER_WINDOW (f),
+ dpyinfo->Xatom_net_wm_bypass_compositor);
+
/* Also change the frame parameter to reflect the new
state. */
store_frame_param (f, Quse_frame_synchronization, Qnil);
@@ -6942,7 +7034,7 @@ x_sync_wait_for_frame_drawn_event (struct frame *f)
}
}
else
- x_sync_note_frame_times (FRAME_DISPLAY_INFO (f), f, &event);
+ x_sync_note_frame_times (dpyinfo, f, &event);
FRAME_X_WAITING_FOR_DRAW (f) = false;
}
@@ -7553,6 +7645,46 @@ x_after_update_window_line (struct window *w, struct glyph_row *desired_row)
#endif
}
+/* Generate a premultiplied pixel value for COLOR with ALPHA applied
+ on the given display. COLOR will be modified. The display must
+ use a visual that supports an alpha channel.
+
+ This is possibly dead code on builds which do not support
+ XRender. */
+
+#ifndef USE_CAIRO
+
+static unsigned long
+x_premultiply_pixel (struct x_display_info *dpyinfo,
+ XColor *color, double alpha)
+{
+ unsigned long pixel;
+
+ eassert (dpyinfo->alpha_bits);
+
+ /* Multiply the RGB channels. */
+ color->red *= alpha;
+ color->green *= alpha;
+ color->blue *= alpha;
+
+ /* First, allocate a fully opaque pixel. */
+ pixel = x_make_truecolor_pixel (dpyinfo, color->red,
+ color->green,
+ color->blue);
+
+ /* Next, erase the alpha component. */
+ pixel &= ~dpyinfo->alpha_mask;
+
+ /* And add an alpha channel. */
+ pixel |= (((unsigned long) (alpha * 65535)
+ >> (16 - dpyinfo->alpha_bits))
+ << dpyinfo->alpha_offset);
+
+ return pixel;
+}
+
+#endif
+
static void
x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
struct draw_fringe_bitmap_params *p)
@@ -7642,18 +7774,15 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
if (FRAME_DISPLAY_INFO (f)->alpha_bits
&& f->alpha_background < 1.0)
{
+ /* Extend the background color with an alpha channel
+ according to f->alpha_background. */
bg.pixel = background;
x_query_colors (f, &bg, 1);
- bg.red *= f->alpha_background;
- bg.green *= f->alpha_background;
- bg.blue *= f->alpha_background;
- background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
- bg.red, bg.green, bg.blue);
- background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
- background |= (((unsigned long) (f->alpha_background * 0xffff)
- >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
- << FRAME_DISPLAY_INFO (f)->alpha_offset);
+ background
+ = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
+ &bg,
+ f->alpha_background);
}
/* Draw the bitmap. I believe these small pixmaps can be cached
@@ -8802,7 +8931,11 @@ x_color_cells (Display *dpy, int *ncells)
/* On frame F, translate pixel colors to RGB values for the NCOLORS
- colors in COLORS. Use cached information, if available. */
+ colors in COLORS. Use cached information, if available.
+
+ Pixel values are in unsigned normalized format, meaning that
+ extending missing bits is done straightforwardly without any
+ complex colorspace conversions. */
void
x_query_colors (struct frame *f, XColor *colors, int ncolors)
@@ -8850,6 +8983,7 @@ x_query_colors (struct frame *f, XColor *colors, int ncolors)
colors[i].green = (g * gmult) >> 16;
colors[i].blue = (b * bmult) >> 16;
}
+
return;
}
@@ -8892,16 +9026,10 @@ x_query_frame_background_color (struct frame *f, XColor *bgcolor)
{
bg.pixel = background;
x_query_colors (f, &bg, 1);
- bg.red *= f->alpha_background;
- bg.green *= f->alpha_background;
- bg.blue *= f->alpha_background;
- background = x_make_truecolor_pixel (FRAME_DISPLAY_INFO (f),
- bg.red, bg.green, bg.blue);
- background &= ~FRAME_DISPLAY_INFO (f)->alpha_mask;
- background |= (((unsigned long) (f->alpha_background * 0xffff)
- >> (16 - FRAME_DISPLAY_INFO (f)->alpha_bits))
- << FRAME_DISPLAY_INFO (f)->alpha_offset);
+ background
+ = x_premultiply_pixel (FRAME_DISPLAY_INFO (f),
+ &bg, f->alpha_background);
}
#endif
}
@@ -10991,6 +11119,31 @@ x_clear_frame (struct frame *f)
unblock_input ();
}
+/* Send a message to frame F telling the event loop to track whether
+ or not an hourglass is being displayed. This is required to ignore
+ the right events when the hourglass is mapped without callig XSync
+ after displaying or hiding the hourglass. */
+
+static void
+x_send_hourglass_message (struct frame *f, bool hourglass_enabled)
+{
+ struct x_display_info *dpyinfo;
+ XEvent msg;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+ memset (&msg, 0, sizeof msg);
+
+ msg.xclient.type = ClientMessage;
+ msg.xclient.message_type
+ = dpyinfo->Xatom_EMACS_TMP;
+ msg.xclient.format = 8;
+ msg.xclient.window = FRAME_X_WINDOW (f);
+ msg.xclient.data.b[0] = hourglass_enabled ? 1 : 0;
+
+ XSendEvent (dpyinfo->display, FRAME_X_WINDOW (f),
+ False, NoEventMask, &msg);
+}
+
/* RIF: Show hourglass cursor on frame F. */
static void
@@ -11011,14 +11164,14 @@ x_show_hourglass (struct frame *f)
if (popup_activated ())
return;
+ x_send_hourglass_message (f, true);
+
#ifdef USE_X_TOOLKIT
if (x->widget)
#else
if (FRAME_OUTER_WINDOW (f))
#endif
{
- x->hourglass_p = true;
-
if (!x->hourglass_window)
{
#ifndef USE_XCB
@@ -11085,15 +11238,11 @@ x_hide_hourglass (struct frame *f)
{
#ifndef USE_XCB
XUnmapWindow (FRAME_X_DISPLAY (f), x->hourglass_window);
- /* Sync here because XTread_socket looks at the
- hourglass_p flag that is reset to zero below. */
- XSync (FRAME_X_DISPLAY (f), False);
#else
xcb_unmap_window (FRAME_DISPLAY_INFO (f)->xcb_connection,
(xcb_window_t) x->hourglass_window);
- xcb_aux_sync (FRAME_DISPLAY_INFO (f)->xcb_connection);
#endif
- x->hourglass_p = false;
+ x_send_hourglass_message (f, false);
}
}
@@ -11217,21 +11366,32 @@ XTflash (struct frame *f)
static void
XTring_bell (struct frame *f)
{
- if (FRAME_X_DISPLAY (f))
+ struct x_display_info *dpyinfo;
+
+ if (!FRAME_X_DISPLAY (f))
+ return;
+
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (visible_bell)
+ XTflash (f);
+ else
{
- if (visible_bell)
- XTflash (f);
- else
- {
- block_input ();
+ /* When Emacs is untrusted, Bell requests sometimes generate
+ Access errors. This is not in the security extension
+ specification but seems to be a bug in the X consortium XKB
+ implementation. */
+
+ block_input ();
+ x_ignore_errors_for_next_request (dpyinfo, 0);
#ifdef HAVE_XKB
- XkbBell (FRAME_X_DISPLAY (f), None, 0, None);
+ XkbBell (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 0, None);
#else
- XBell (FRAME_X_DISPLAY (f), 0);
+ XBell (FRAME_X_DISPLAY (f), 0);
#endif
- XFlush (FRAME_X_DISPLAY (f));
- unblock_input ();
- }
+ XFlush (FRAME_X_DISPLAY (f));
+ x_stop_ignoring_errors (dpyinfo);
+ unblock_input ();
}
}
@@ -11477,7 +11637,7 @@ x_frame_highlight (struct frame *f)
the window-manager in use, tho something more is at play since I've been
using that same window-manager binary for ever. Let's not crash just
because of this (bug#9310). */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSetWindowBorder (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_pixel);
x_stop_ignoring_errors (dpyinfo);
@@ -11500,7 +11660,7 @@ x_frame_unhighlight (struct frame *f)
block_input ();
/* Same as above for XSetWindowBorder (bug#9310). */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSetWindowBorderPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
f->output_data.x->border_tile);
x_stop_ignoring_errors (dpyinfo);
@@ -11564,7 +11724,7 @@ x_new_focus_frame (struct x_display_info *dpyinfo, struct frame *frame)
x_frame_rehighlight (dpyinfo);
}
-#ifdef HAVE_XFIXES
+#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
/* True if the display in DPYINFO supports a version of Xfixes
sufficient for pointer blanking. */
@@ -11576,11 +11736,12 @@ x_fixes_pointer_blanking_supported (struct x_display_info *dpyinfo)
&& dpyinfo->xfixes_major >= 4);
}
-#endif /* HAVE_XFIXES */
+#endif /* HAVE_XFIXES && XFIXES_VERSION >= 40000 */
/* Toggle mouse pointer visibility on frame F using the XFixes
extension. */
-#ifdef HAVE_XFIXES
+#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
+
static void
xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
@@ -11591,6 +11752,7 @@ xfixes_toggle_visible_pointer (struct frame *f, bool invisible)
XFixesShowCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f));
f->pointer_invisible = invisible;
}
+
#endif /* HAVE_XFIXES */
/* Create invisible cursor on the X display referred by DPYINFO. */
@@ -11639,7 +11801,7 @@ x_toggle_visible_pointer (struct frame *f, bool invisible)
if (dpyinfo->invisible_cursor == None)
dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
-#ifndef HAVE_XFIXES
+#if !defined HAVE_XFIXES || XFIXES_VERSION < 40000
if (dpyinfo->invisible_cursor == None)
invisible = false;
#else
@@ -11672,7 +11834,7 @@ static void
XTtoggle_invisible_pointer (struct frame *f, bool invisible)
{
block_input ();
-#ifdef HAVE_XFIXES
+#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
if (FRAME_DISPLAY_INFO (f)->fixes_pointer_blanking
&& x_fixes_pointer_blanking_supported (FRAME_DISPLAY_INFO (f)))
xfixes_toggle_visible_pointer (f, invisible);
@@ -12261,6 +12423,13 @@ x_dnd_begin_drag_and_drop (struct frame *f, Time time, Atom xaction,
struct xi_device_t *device;
#endif
+ if (FRAME_DISPLAY_INFO (f)->untrusted)
+ /* Untrusted clients cannot send messages to trusted clients or
+ read the window tree, so drag and drop will likely not work at
+ all. */
+ error ("Drag-and-drop is not possible when the client is"
+ " not trusted by the X server.");
+
base = SPECPDL_INDEX ();
/* Bind this here to avoid juggling bindings and SAFE_FREE in
@@ -15032,9 +15201,7 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
XClientMessageEvent *ev = &event.xclient;
struct window *w = XWINDOW (window);
struct frame *f = XFRAME (w->frame);
- intptr_t iw = (intptr_t) w;
verify (INTPTR_WIDTH <= 64);
- int sign_shift = INTPTR_WIDTH - 32;
/* Don't do anything if too many scroll bar events have been
sent but not received. */
@@ -15051,15 +15218,11 @@ x_send_scroll_bar_event (Lisp_Object window, enum scroll_bar_part part,
ev->window = FRAME_X_WINDOW (f);
ev->format = 32;
- /* A 32-bit X client can pass a window pointer through the X server
- as-is.
-
- A 64-bit client is in trouble because a pointer does not fit in
- the 32 bits given for ClientMessage data and will be truncated by
- Xlib. So use two slots and hope that X12 will resolve such
- issues someday. */
- ev->data.l[0] = iw >> 31 >> 1;
- ev->data.l[1] = sign_shift <= 0 ? iw : iw << sign_shift >> sign_shift;
+ /* These messages formerly contained a pointer to the window, but
+ now that information is kept internally. The following two
+ fields are thus zero. */
+ ev->data.l[0] = 0;
+ ev->data.l[1] = 0;
ev->data.l[2] = part;
ev->data.l[3] = portion;
ev->data.l[4] = whole;
@@ -18490,7 +18653,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
x_dnd_waiting_for_status_window = None;
else
{
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSendEvent (dpyinfo->display, target,
False, NoEventMask,
&x_dnd_pending_send_position);
@@ -18604,6 +18767,16 @@ handle_one_xevent (struct x_display_info *dpyinfo,
}
}
+ if (event->xclient.message_type == dpyinfo->Xatom_EMACS_TMP
+ && event->xclient.format == 8)
+ {
+ /* This is actually an hourglass message. Set whether or
+ not events from here on have the hourglass enabled. */
+
+ if (any)
+ FRAME_X_OUTPUT (any)->hourglass_p = event->xclient.data.b[0];
+ }
+
if (event->xclient.message_type == dpyinfo->Xatom_wm_protocols
&& event->xclient.format == 32)
{
@@ -19192,7 +19365,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
= xcb_get_property (dpyinfo->xcb_connection, 0,
(xcb_window_t) FRAME_OUTER_WINDOW (f),
(xcb_atom_t) dpyinfo->Xatom_net_wm_window_opacity,
- XCB_ATOM_CARDINAL, 0, 1);
+ XA_CARDINAL, 0, 1);
opacity_reply
= xcb_get_property_reply (dpyinfo->xcb_connection,
opacity_cookie, &error);
@@ -19201,9 +19374,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
free (error), rc = false;
else
rc = (opacity_reply->format == 32
- && (opacity_reply->type == XCB_ATOM_CARDINAL
- || opacity_reply->type == XCB_ATOM_ATOM
- || opacity_reply->type == XCB_ATOM_WINDOW)
+ && (opacity_reply->type == XA_CARDINAL
+ || opacity_reply->type == XA_ATOM
+ || opacity_reply->type == XA_WINDOW)
&& (xcb_get_property_value_length (opacity_reply) >= 4));
if (rc)
@@ -21349,7 +21522,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
if (FRAME_PARENT_FRAME (f) || (hf && frame_ancestor_p (f, hf)))
{
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
RevertToParent, event->xbutton.time);
x_stop_ignoring_errors (dpyinfo);
@@ -21570,9 +21743,9 @@ handle_one_xevent (struct x_display_info *dpyinfo,
case VisibilityNotify:
f = x_top_window_to_frame (dpyinfo, event->xvisibility.window);
- if (f && (event->xvisibility.state == VisibilityUnobscured
- || event->xvisibility.state == VisibilityPartiallyObscured))
- SET_FRAME_VISIBLE (f, 1);
+
+ if (f)
+ FRAME_X_OUTPUT (f)->visibility_state = event->xvisibility.state;
goto OTHER;
@@ -23047,7 +23220,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
/* This can generate XI_BadDevice if the
device's attachment was destroyed
server-side. */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XISetFocus (dpyinfo->display, device->attachment,
/* Note that the input extension
only supports RevertToParent-type
@@ -23060,7 +23233,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
events to handle focus. Errors are still
caught here in case the window is not
viewable. */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
RevertToParent, xev->time);
x_stop_ignoring_errors (dpyinfo);
@@ -24069,7 +24242,7 @@ handle_one_xevent (struct x_display_info *dpyinfo,
#ifndef HAVE_GTK3
else if (x_input_grab_touch_events)
{
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XIAllowTouchEvents (dpyinfo->display, xev->deviceid,
xev->detail, xev->event, XIRejectTouch);
x_stop_ignoring_errors (dpyinfo);
@@ -25506,10 +25679,17 @@ x_clean_failable_requests (struct x_display_info *dpyinfo)
x_uncatch_errors_after_check is that this function does not sync to
catch errors if requests were made. It should be used instead of
those two functions for catching errors around requests that do not
- require a reply. */
+ require a reply.
+
+ As a special feature intended to support xselect.c,
+ SELECTION_SERIAL may be an arbitrary number greater than zero: when
+ that is the case, x_select_handle_selection_error is called with
+ the specified number to delete the selection request that
+ encountered the error. */
void
-x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
+x_ignore_errors_for_next_request (struct x_display_info *dpyinfo,
+ unsigned int selection_serial)
{
struct x_failable_request *request, *max;
unsigned long next_request;
@@ -25563,6 +25743,7 @@ x_ignore_errors_for_next_request (struct x_display_info *dpyinfo)
request->start = next_request;
request->end = 0;
+ request->selection_serial = selection_serial;
dpyinfo->next_failable_request++;
}
@@ -25984,9 +26165,11 @@ For details, see etc/PROBLEMS.\n",
if (!ioerror && dpyinfo)
{
/* Dump the list of error handlers for debugging
- purposes. */
+ purposes if the list exists. */
- fprintf (stderr, "X error handlers currently installed:\n");
+ if ((dpyinfo->failable_requests
+ != dpyinfo->next_failable_request) || x_error_message)
+ fprintf (stderr, "X error handlers currently installed:\n");
for (failable = dpyinfo->failable_requests;
failable < dpyinfo->next_failable_request;
@@ -26075,6 +26258,12 @@ x_error_handler (Display *display, XErrorEvent *event)
+ (last - fail));
}
+ /* If a selection transfer is the cause of this error,
+ remove the selection transfer now. */
+ if (fail->selection_serial)
+ x_handle_selection_error (fail->selection_serial,
+ event);
+
return 0;
}
}
@@ -26111,8 +26300,10 @@ x_error_handler (Display *display, XErrorEvent *event)
static void NO_INLINE
x_error_quitter (Display *display, XErrorEvent *event)
{
- char buf[256], buf1[400 + INT_STRLEN_BOUND (int)
- + INT_STRLEN_BOUND (unsigned long)];
+ char buf[256], buf1[800 + INT_STRLEN_BOUND (int)
+ + INT_STRLEN_BOUND (unsigned long)
+ + INT_STRLEN_BOUND (XID)
+ + INT_STRLEN_BOUND (int)];
/* Ignore BadName errors. They can happen because of fonts
or colors that are not defined. */
@@ -26125,8 +26316,12 @@ x_error_quitter (Display *display, XErrorEvent *event)
XGetErrorText (display, event->error_code, buf, sizeof (buf));
sprintf (buf1, "X protocol error: %s on protocol request %d\n"
- "Serial no: %lu\n", buf, event->request_code,
- event->serial);
+ "Serial no: %lu\n"
+ "Failing resource ID (if any): 0x%lx\n"
+ "Minor code: %d\n"
+ "This is a bug! Please report this to bug-gnu-emacs@gnu.org!\n",
+ buf, event->request_code, event->serial, event->resourceid,
+ event->minor_code);
x_connection_closed (display, buf1, false);
}
@@ -26627,38 +26822,43 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_gravity)
modified_left, modified_top);
#endif
- /* 'x_sync_with_move' is too costly for dragging child frames. */
- if (!FRAME_PARENT_FRAME (f)
- /* If no window manager exists, just calling XSync will be
- sufficient to ensure that the window geometry has been
- updated. */
- && NILP (Vx_no_window_manager))
- {
- x_sync_with_move (f, f->left_pos, f->top_pos,
- FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
-
- /* change_gravity is non-zero when this function is called from Lisp to
- programmatically move a frame. In that case, we call
- x_check_expected_move to discover if we have a "Type A" or "Type B"
- window manager, and, for a "Type A" window manager, adjust the position
- of the frame.
-
- We call x_check_expected_move if a programmatic move occurred, and
- either the window manager type (A/B) is unknown or it is Type A but we
- need to compute the top/left offset adjustment for this frame. */
-
- if (change_gravity != 0
- && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
- || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
- && (FRAME_X_OUTPUT (f)->move_offset_left == 0
- && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
- x_check_expected_move (f, modified_left, modified_top);
- }
- /* Instead, just wait for the last ConfigureWindow request to
- complete. No window manager is involved when moving child
- frames. */
- else
- XSync (FRAME_X_DISPLAY (f), False);
+ /* The following code is too slow over a latent network
+ connection. */
+ if (NILP (Vx_lax_frame_positioning))
+ {
+ /* 'x_sync_with_move' is too costly for dragging child frames. */
+ if (!FRAME_PARENT_FRAME (f)
+ /* If no window manager exists, just calling XSync will be
+ sufficient to ensure that the window geometry has been
+ updated. */
+ && NILP (Vx_no_window_manager))
+ {
+ x_sync_with_move (f, f->left_pos, f->top_pos,
+ FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN);
+
+ /* change_gravity is non-zero when this function is called from Lisp to
+ programmatically move a frame. In that case, we call
+ x_check_expected_move to discover if we have a "Type A" or "Type B"
+ window manager, and, for a "Type A" window manager, adjust the position
+ of the frame.
+
+ We call x_check_expected_move if a programmatic move occurred, and
+ either the window manager type (A/B) is unknown or it is Type A but we
+ need to compute the top/left offset adjustment for this frame. */
+
+ if (change_gravity != 0
+ && (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN
+ || (FRAME_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A
+ && (FRAME_X_OUTPUT (f)->move_offset_left == 0
+ && FRAME_X_OUTPUT (f)->move_offset_top == 0))))
+ x_check_expected_move (f, modified_left, modified_top);
+ }
+ /* Instead, just wait for the last ConfigureWindow request to
+ complete. No window manager is involved when moving child
+ frames. */
+ else
+ XSync (FRAME_X_DISPLAY (f), False);
+ }
unblock_input ();
}
@@ -26718,6 +26918,12 @@ x_wm_supports_1 (struct x_display_info *dpyinfo, Atom want_atom)
if (!NILP (Vx_no_window_manager))
return false;
+ /* If the window system says Emacs is untrusted, there will be no
+ way to send any information to the window manager, making any
+ hints useless. */
+ if (dpyinfo->untrusted)
+ return false;
+
block_input ();
x_catch_errors (dpy);
@@ -27188,13 +27394,12 @@ do_ewmh_fullscreen (struct frame *f)
static void
XTfullscreen_hook (struct frame *f)
{
- if (FRAME_VISIBLE_P (f))
- {
- block_input ();
- x_check_fullscreen (f);
- x_sync (f);
- unblock_input ();
- }
+ if (!FRAME_VISIBLE_P (f))
+ return;
+
+ block_input ();
+ x_check_fullscreen (f);
+ unblock_input ();
}
@@ -27288,10 +27493,7 @@ x_check_fullscreen (struct frame *f)
if (FRAME_VISIBLE_P (f))
x_wait_for_event (f, ConfigureNotify);
else
- {
- change_frame_size (f, width, height, false, true, false);
- x_sync (f);
- }
+ change_frame_size (f, width, height, false, true, false);
}
/* `x_net_wm_state' might have reset the fullscreen frame parameter,
@@ -27465,6 +27667,12 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
we have to make sure to do it here. */
SET_FRAME_GARBAGED (f);
+ /* The following code is too slow over a latent network
+ connection, so skip it when the user says so. */
+
+ if (!NILP (Vx_lax_frame_positioning))
+ return;
+
/* Now, strictly speaking, we can't be sure that this is accurate,
but the window manager will get around to dealing with the size
change request eventually, and we'll hear how it went when the
@@ -27505,8 +27713,6 @@ x_set_window_size_1 (struct frame *f, bool change_gravity,
adjust_frame_size (f, FRAME_PIXEL_TO_TEXT_WIDTH (f, width),
FRAME_PIXEL_TO_TEXT_HEIGHT (f, height),
5, 0, Qx_set_window_size_1);
-
- x_sync (f);
}
}
@@ -27560,7 +27766,7 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
&& deviceid != -1)
{
block_input ();
- x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
XIWarpPointer (FRAME_X_DISPLAY (f), deviceid, None,
FRAME_X_WINDOW (f), 0, 0, 0, 0, pix_x, pix_y);
x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
@@ -27857,7 +28063,7 @@ x_set_input_focus (struct x_display_info *dpyinfo, Window window,
{
eassert (device->use == XIMasterPointer);
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XISetFocus (dpyinfo->display, device->attachment,
/* Note that the input extension
only supports RevertToParent-type
@@ -27872,7 +28078,7 @@ x_set_input_focus (struct x_display_info *dpyinfo, Window window,
/* Otherwise, use the pointer device that the X server says is the
client pointer. */
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
XSetInputFocus (dpyinfo->display, window, RevertToParent, time);
x_stop_ignoring_errors (dpyinfo);
}
@@ -27892,12 +28098,17 @@ x_focus_frame (struct frame *f, bool noactivate)
struct x_display_info *dpyinfo;
Time time;
+ dpyinfo = FRAME_DISPLAY_INFO (f);
+
+ if (dpyinfo->untrusted)
+ /* The X server ignores all input focus related requests from
+ untrusted clients. */
+ return;
+
/* The code below is not reentrant wrt to dpyinfo->x_focus_frame and
friends being set. */
block_input ();
- dpyinfo = FRAME_DISPLAY_INFO (f);
-
if (FRAME_X_EMBEDDED_P (f))
/* For Xembedded frames, normally the embedder forwards key
events. See XEmbed Protocol Specification at
@@ -28009,7 +28220,7 @@ xembed_send_message (struct frame *f, Time t, enum xembed_message msg,
but I don't understand why: there is no way for clients to
survive the death of the parent anyway. */
- x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f));
+ x_ignore_errors_for_next_request (FRAME_DISPLAY_INFO (f), 0);
XSendEvent (FRAME_X_DISPLAY (f), FRAME_X_OUTPUT (f)->parent_desc,
False, NoEventMask, &event);
x_stop_ignoring_errors (FRAME_DISPLAY_INFO (f));
@@ -28160,6 +28371,7 @@ x_make_frame_visible (struct frame *f)
&& !FRAME_ICONIFIED_P (f)
&& !FRAME_X_EMBEDDED_P (f)
&& !FRAME_PARENT_FRAME (f)
+ && NILP (Vx_lax_frame_positioning)
&& f->win_gravity == NorthWestGravity
&& previously_visible)
{
@@ -28188,7 +28400,8 @@ x_make_frame_visible (struct frame *f)
}
/* Try to wait for a MapNotify event (that is what tells us when a
- frame becomes visible). */
+ frame becomes visible). Unless `x-lax-frame-positioning' is
+ non-nil: there, that is a little slow. */
#ifdef CYGWIN
/* On Cygwin, which uses input polling, we need to force input to
@@ -28206,7 +28419,8 @@ x_make_frame_visible (struct frame *f)
poll_suppress_count = old_poll_suppress_count;
#endif
- if (!FRAME_VISIBLE_P (f))
+ if (!FRAME_VISIBLE_P (f)
+ && NILP (Vx_lax_frame_positioning))
{
if (CONSP (frame_size_history))
frame_size_history_plain
@@ -28263,7 +28477,10 @@ x_make_frame_invisible (struct frame *f)
error ("Can't notify window manager of window withdrawal");
}
- x_sync (f);
+ /* Don't perform the synchronization if the network connection is
+ slow, and the user says it is unwanted. */
+ if (NILP (Vx_lax_frame_positioning))
+ XSync (FRAME_X_DISPLAY (f), False);
/* We can't distinguish this from iconification
just by the event that we get from the server.
@@ -28274,8 +28491,7 @@ x_make_frame_invisible (struct frame *f)
SET_FRAME_ICONIFIED (f, false);
if (CONSP (frame_size_history))
- frame_size_history_plain
- (f, build_string ("x_make_frame_invisible"));
+ frame_size_history_plain (f, build_string ("x_make_frame_invisible"));
unblock_input ();
}
@@ -28861,6 +29077,53 @@ x_get_atom_name (struct x_display_info *dpyinfo, Atom atom,
return value;
}
+/* Intern an array of atoms, and do so quickly, avoiding extraneous
+ roundtrips to the X server.
+
+ Avoid sending atoms that have already been found to the X server.
+ This cannot do anything that will end up triggering garbage
+ collection. */
+
+void
+x_intern_atoms (struct x_display_info *dpyinfo, char **names, int count,
+ Atom *atoms_return)
+{
+ int i, j, indices[256];
+ char *new_names[256];
+ Atom results[256], candidate;
+
+ if (count > 256)
+ /* Atoms array too big to inspect reasonably, just send it to the
+ server and back. */
+ XInternAtoms (dpyinfo->display, new_names, count, False, atoms_return);
+ else
+ {
+ for (i = 0, j = 0; i < count; ++i)
+ {
+ candidate = x_intern_cached_atom (dpyinfo, names[i],
+ true);
+
+ if (candidate)
+ atoms_return[i] = candidate;
+ else
+ {
+ indices[j++] = i;
+ new_names[j - 1] = names[i];
+ }
+ }
+
+ if (!j)
+ return;
+
+ /* Now, get the results back from the X server. */
+ XInternAtoms (dpyinfo->display, new_names, j, False,
+ results);
+
+ for (i = 0; i < j; ++i)
+ atoms_return[indices[i]] = results[i];
+ }
+}
+
#ifndef USE_GTK
/* Set up XEmbed for F, and change its save set to handle the parent
@@ -29409,6 +29672,7 @@ struct x_display_info *
x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
{
Display *dpy;
+ XKeyboardState keyboard_state;
struct terminal *terminal;
struct x_display_info *dpyinfo;
XrmDatabase xrdb;
@@ -29628,6 +29892,32 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
dpyinfo = xzalloc (sizeof *dpyinfo);
terminal = x_create_terminal (dpyinfo);
+ if (!NILP (Vx_detect_server_trust))
+ {
+ /* Detect whether or not the X server trusts this client, which
+ is done by making a SetKeyboardControl request and checking
+ for an Access error. */
+ XGrabServer (dpy);
+ XGetKeyboardControl (dpy, &keyboard_state);
+
+ x_catch_errors (dpy);
+
+ /* At this point, the display is not on x_display_list, so
+ x_uncatch_errors won't sync. However, that's okay because
+ x_had_errors_p will. */
+
+ if (keyboard_state.global_auto_repeat
+ == AutoRepeatModeOn)
+ XAutoRepeatOn (dpy);
+ else
+ XAutoRepeatOff (dpy);
+
+ if (x_had_errors_p (dpy))
+ dpyinfo->untrusted = true;
+ x_uncatch_errors_after_check ();
+ XUngrabServer (dpy);
+ }
+
dpyinfo->next_failable_request = dpyinfo->failable_requests;
{
@@ -29648,13 +29938,17 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
{
char *vendor = ServerVendor (dpy);
- /* Temporarily hide the partially initialized terminal. */
+ /* Temporarily hide the partially initialized terminal.
+ Use safe_call so that if a signal happens, a partially
+ initialized display (and display connection) is not
+ kept around. */
terminal_list = terminal->next_terminal;
unblock_input ();
- kset_system_key_alist
- (terminal->kboard,
- call1 (Qvendor_specific_keysyms,
- vendor ? build_string (vendor) : empty_unibyte_string));
+ kset_system_key_alist (terminal->kboard,
+ safe_call1 (Qvendor_specific_keysyms,
+ (vendor
+ ? build_string (vendor)
+ : empty_unibyte_string)));
block_input ();
terminal->next_terminal = terminal_list;
terminal_list = terminal;
@@ -30272,7 +30566,7 @@ x_term_init (Lisp_Object display_name, char *xrm_option, char *resource_name)
1, 0, 1);
dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo);
-#ifdef HAVE_XFIXES
+#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
dpyinfo->fixes_pointer_blanking = egetenv ("EMACS_XFIXES");
#endif
@@ -30600,8 +30894,13 @@ x_delete_display (struct x_display_info *dpyinfo)
last = ie;
}
+ /* Delete selection requests bound for dpyinfo from the keyboard
+ buffer. */
x_delete_selection_requests (dpyinfo);
+ /* And remove any outstanding selection transfers. */
+ x_remove_selection_transfers (dpyinfo);
+
if (next_noop_dpyinfo == dpyinfo)
next_noop_dpyinfo = dpyinfo->next;
@@ -31107,7 +31406,7 @@ x_catch_errors_for_lisp (struct x_display_info *dpyinfo)
if (!x_fast_protocol_requests)
x_catch_errors (dpyinfo->display);
else
- x_ignore_errors_for_next_request (dpyinfo);
+ x_ignore_errors_for_next_request (dpyinfo, 0);
}
void
@@ -31316,6 +31615,8 @@ syms_of_xterm (void)
DEFSYM (Qnow, "now");
DEFSYM (Qx_dnd_targets_list, "x-dnd-targets-list");
DEFSYM (Qx_auto_preserve_selections, "x-auto-preserve-selections");
+ DEFSYM (Qexpose, "expose");
+ DEFSYM (Qdont_save, "dont-save");
#ifdef USE_GTK
xg_default_icon_file = build_pure_c_string ("icons/hicolor/scalable/apps/emacs.svg");
@@ -31485,7 +31786,6 @@ always uses gtk_window_move and ignores the value of this variable. */);
This option is only effective when Emacs is built with XInput 2
support. */);
Vx_scroll_event_delta_factor = make_float (1.0);
- DEFSYM (Qexpose, "expose");
DEFVAR_BOOL ("x-gtk-use-native-input", x_gtk_use_native_input,
doc: /* Non-nil means to use GTK for input method support.
@@ -31699,4 +31999,26 @@ select text over slow X connections.
If that is still too slow, setting this variable to the symbol
`really-fast' will make Emacs return only cached values. */);
Vx_use_fast_mouse_position = Qnil;
+
+ DEFVAR_LISP ("x-detect-server-trust", Vx_detect_server_trust,
+ doc: /* If non-nil, Emacs should detect whether or not it is trusted by X.
+
+If non-nil, Emacs will make an X request at connection startup that is
+prohibited to untrusted clients under the X Security Extension and
+check whether or not a resulting Access error is generated by the X
+server. If the X server reports the error, Emacs will disable certain
+features that do not work for untrusted clients. */);
+ Vx_detect_server_trust = Qnil;
+
+ DEFVAR_LISP ("x-lax-frame-positioning", Vx_lax_frame_positioning,
+ doc: /* If non-nil, Emacs won't compensate for WM geometry behavior.
+
+Setting this to non-nil is useful when the compensation proves to be
+too slow, which is usually true when the X server is located over a
+network connection with high latency. Doing so will make frame
+creation and placement faster at the cost of reducing the accuracy of
+frame placement via frame parameters, `set-frame-position', and
+`set-frame-size', along with the actual state of a frame after
+`x_make_frame_invisible'. */);
+ Vx_lax_frame_positioning = Qnil;
}
diff --git a/src/xterm.h b/src/xterm.h
index ee429e9c68d..f06e1ec5bc6 100644
--- a/src/xterm.h
+++ b/src/xterm.h
@@ -21,6 +21,22 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define XTERM_H
#include <X11/Xlib.h>
+
+#ifdef HAVE_XFIXES
+#include <X11/extensions/Xfixes.h>
+
+#if defined HAVE_XINPUT2 && XFIXES_MAJOR < 5
+/* XI2 headers need PointerBarrier, which is not defined in old
+ versions of the fixes library. Define that type here. */
+typedef XID PointerBarrier;
+#endif
+#if defined HAVE_XCOMPOSITE && XFIXES_MAJOR < 2
+/* Recent Composite headers need XserverRegion, which is not defined
+ in old versions of the fixes library. Define that type here. */
+typedef XID XserverRegion;
+#endif
+#endif
+
#include <X11/cursorfont.h>
/* Include Xutil.h after keysym.h to work around a bug that prevents
@@ -318,6 +334,9 @@ struct x_failable_request
/* If this is zero, then the request has not yet been made.
Otherwise, this is the request that ends this sequence. */
unsigned long end;
+
+ /* Any selection event serial associated with this error trap. */
+ unsigned int selection_serial;
};
#ifdef HAVE_XFIXES
@@ -360,6 +379,10 @@ struct x_display_info
/* Number of frames that are on this display. */
int reference_count;
+ /* True if this display connection cannot communicate with the
+ window manager because it is not trusted by the X server. */
+ bool untrusted;
+
/* The Screen this connection is connected to. */
Screen *screen;
@@ -406,7 +429,7 @@ struct x_display_info
Unused if this display supports Xfixes extension. */
Cursor invisible_cursor;
-#ifdef HAVE_XFIXES
+#if defined HAVE_XFIXES && XFIXES_VERSION >= 40000
/* Whether or not to use Xfixes for pointer blanking. */
bool fixes_pointer_blanking;
#endif
@@ -537,6 +560,12 @@ struct x_display_info
KDE" protocol in x-dnd.el). */
Atom Xatom_DndProtocol, Xatom_DND_PROTOCOL;
+ /* Atoms to make x_intern_cached_atom fast. */
+ Atom Xatom_text_plain_charset_utf_8, Xatom_LENGTH, Xatom_FILE_NAME,
+ Xatom_CHARACTER_POSITION, Xatom_LINE_NUMBER, Xatom_COLUMN_NUMBER,
+ Xatom_OWNER_OS, Xatom_HOST_NAME, Xatom_USER, Xatom_CLASS,
+ Xatom_NAME, Xatom_SAVE_TARGETS;
+
/* The frame (if any) which has the X window that has keyboard focus.
Zero if none. This is examined by Ffocus_frame in xfns.c. Note
that a mere EnterNotify event can set this; if you need to know the
@@ -1261,6 +1290,11 @@ struct x_output
strictly an optimization to avoid extraneous synchronizing in
some cases. */
int root_x, root_y;
+
+ /* The frame visibility state. This starts out
+ VisibilityFullyObscured, but is set to something else in
+ handle_one_xevent. */
+ int visibility_state;
};
enum
@@ -1379,6 +1413,11 @@ extern void x_mark_frame_dirty (struct frame *f);
/* And its corresponding visual info. */
#define FRAME_X_VISUAL_INFO(f) (&FRAME_DISPLAY_INFO (f)->visual_info)
+/* Whether or not the frame is visible. Do not test this alone.
+ Instead, use FRAME_REDISPLAY_P. */
+#define FRAME_X_VISIBLE(f) (FRAME_X_OUTPUT (f)->visibility_state \
+ != VisibilityFullyObscured)
+
#ifdef HAVE_XRENDER
#define FRAME_X_PICTURE_FORMAT(f) FRAME_DISPLAY_INFO (f)->pict_format
#define FRAME_X_PICTURE(f) ((f)->output_data.x->picture)
@@ -1644,7 +1683,8 @@ extern bool x_had_errors_p (Display *);
extern void x_unwind_errors_to (int);
extern void x_uncatch_errors (void);
extern void x_uncatch_errors_after_check (void);
-extern void x_ignore_errors_for_next_request (struct x_display_info *);
+extern void x_ignore_errors_for_next_request (struct x_display_info *,
+ unsigned int);
extern void x_stop_ignoring_errors (struct x_display_info *);
extern void x_clear_errors (Display *);
extern void x_set_window_size (struct frame *, bool, int, int);
@@ -1717,6 +1757,11 @@ extern Lisp_Object x_handle_translate_coordinates (struct frame *, Lisp_Object,
extern Bool x_query_pointer (Display *, Window, Window *, Window *, int *,
int *, int *, int *, unsigned int *);
+extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
+ bool);
+extern void x_intern_atoms (struct x_display_info *, char **, int, Atom *);
+extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
+ ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
#ifdef HAVE_GTK3
extern void x_scroll_bar_configure (GdkEvent *);
@@ -1798,6 +1843,9 @@ extern void x_handle_property_notify (const XPropertyEvent *);
extern void x_handle_selection_notify (const XSelectionEvent *);
extern void x_handle_selection_event (struct selection_input_event *);
extern void x_clear_frame_selections (struct frame *);
+extern void x_remove_selection_transfers (struct x_display_info *);
+extern void x_handle_selection_error (unsigned int, XErrorEvent *);
+
extern Lisp_Object x_atom_to_symbol (struct x_display_info *, Atom);
extern Atom symbol_to_x_atom (struct x_display_info *, Lisp_Object);
@@ -1807,11 +1855,8 @@ extern bool x_handle_dnd_message (struct frame *,
struct input_event *,
bool, int, int);
extern int x_check_property_data (Lisp_Object);
-extern void x_fill_property_data (Display *,
- Lisp_Object,
- void *,
- int,
- int);
+extern void x_fill_property_data (struct x_display_info *, Lisp_Object,
+ void *, int, int);
extern Lisp_Object x_property_data_to_lisp (struct frame *,
const unsigned char *,
Atom,
@@ -1824,10 +1869,10 @@ extern Lisp_Object x_timestamp_for_selection (struct x_display_info *,
Lisp_Object);
extern void x_own_selection (Lisp_Object, Lisp_Object, Lisp_Object,
Lisp_Object, Time);
-extern Atom x_intern_cached_atom (struct x_display_info *, const char *,
- bool);
-extern char *x_get_atom_name (struct x_display_info *, Atom, bool *)
- ATTRIBUTE_MALLOC ATTRIBUTE_DEALLOC_FREE;
+
+extern void mark_xselect (void);
+
+/* Misc definitions. */
#ifdef USE_GTK
extern bool xg_set_icon (struct frame *, Lisp_Object);
diff --git a/test/lisp/elide-head-tests.el b/test/lisp/elide-head-tests.el
index 429ef266572..3d6e7686935 100644
--- a/test/lisp/elide-head-tests.el
+++ b/test/lisp/elide-head-tests.el
@@ -180,6 +180,90 @@
;; along with Mentor. If not, see <https://www.gnu.org/licenses>.
" "Mentor is distributed in the hope that")
+;; from GnuTLS [has a line break in snail mail address]
+(elide-head--add-test gpl3-6 "\
+# This file is part of GnuTLS.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
+# USA
+" "This program is distributed in the hope that")
+
+;; from GnuTLS [has a different line break in snail mail address]
+(elide-head--add-test gpl3-7 "\
+# This file is part of GnuTLS.
+#
+# The GnuTLS is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2.1 of
+# the License, or (at your option) any later version.
+#
+# The GnuTLS is distributed in the hope that it will be
+# useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+# of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with GnuTLS; if not, write to the Free
+# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA
+" "The GnuTLS is distributed in the hope that")
+
+;; from GnuTLS [has a typo in the 02111-1301 part]
+(elide-head--add-test gpl3-8 "\
+/* nettle, low-level cryptographics library
+ *
+ * Copyright (C) 2002 Niels Möller
+ * Copyright (C) 2014 Red Hat
+ *\s\s
+ * The nettle library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at your
+ * option) any later version.
+ *\s
+ * The nettle library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *\s
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with the nettle library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02111-1301, USA.
+ */
+" "The nettle library is distributed in the hope that")
+
+;; from GnuTLS-EXTRA [has a different line break in snail mail address]
+(elide-head--add-test gpl3-9 "\
+# This file is part of GnuTLS-EXTRA.
+#
+# GnuTLS-extra is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3 of the
+# License, or (at your option) any later version.
+#
+# GnuTLS-extra is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GnuTLS-EXTRA; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+" "GnuTLS-extra is distributed in the hope that")
+
;;; GPLv2
@@ -201,6 +285,28 @@
" "This program is distributed in the hope that")
+;;; Apache License
+
+(elide-head--add-test apache1-1 "\
+/*
+ * Copyright 2011-2016 The Pkcs11Interop Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the \"License\");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an \"AS IS\" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+" "Unless required by applicable law")
+
+
+
;;; Obsolete
(with-suppressed-warnings ((obsolete elide-head)
diff --git a/test/lisp/emacs-lisp/bytecomp-tests.el b/test/lisp/emacs-lisp/bytecomp-tests.el
index e7c308213e4..5c61ca10b9c 100644
--- a/test/lisp/emacs-lisp/bytecomp-tests.el
+++ b/test/lisp/emacs-lisp/bytecomp-tests.el
@@ -704,6 +704,59 @@ inner loops respectively."
(let ((bytecomp-tests--xx 1))
(set (make-local-variable 'bytecomp-tests--xx) 2)
bytecomp-tests--xx)
+
+ ;; Check for-effect optimisation of `condition-case' body form.
+ ;; With `condition-case' in for-effect context:
+ (let ((x (bytecomp-test-identity ?A))
+ (r nil))
+ (condition-case e
+ (characterp x) ; value (:success, var)
+ (error (setq r 'bad))
+ (:success (setq r (list 'good e))))
+ r)
+ (let ((x (bytecomp-test-identity ?B))
+ (r nil))
+ (condition-case nil
+ (characterp x) ; for-effect (:success, no var)
+ (error (setq r 'bad))
+ (:success (setq r 'good)))
+ r)
+ (let ((x (bytecomp-test-identity ?C))
+ (r nil))
+ (condition-case e
+ (characterp x) ; for-effect (no :success, var)
+ (error (setq r (list 'bad e))))
+ r)
+ (let ((x (bytecomp-test-identity ?D))
+ (r nil))
+ (condition-case nil
+ (characterp x) ; for-effect (no :success, no var)
+ (error (setq r 'bad)))
+ r)
+ ;; With `condition-case' in value context:
+ (let ((x (bytecomp-test-identity ?E)))
+ (condition-case e
+ (characterp x) ; for-effect (:success, var)
+ (error (list 'bad e))
+ (:success (list 'good e))))
+ (let ((x (bytecomp-test-identity ?F)))
+ (condition-case nil
+ (characterp x) ; for-effect (:success, no var)
+ (error 'bad)
+ (:success 'good)))
+ (let ((x (bytecomp-test-identity ?G)))
+ (condition-case e
+ (characterp x) ; value (no :success, var)
+ (error (list 'bad e))))
+ (let ((x (bytecomp-test-identity ?H)))
+ (condition-case nil
+ (characterp x) ; value (no :success, no var)
+ (error 'bad)))
+
+ (condition-case nil
+ (bytecomp-test-identity 3)
+ (error 'bad)
+ (:success)) ; empty handler
)
"List of expressions for cross-testing interpreted and compiled code.")
@@ -833,13 +886,19 @@ byte-compiled. Run with dynamic binding."
;; Should not warn that mt--test2 is not known to be defined.
(should-not (re-search-forward "my--test2" nil t))))
-(defmacro bytecomp--with-warning-test (re-warning &rest form)
+(defmacro bytecomp--with-warning-test (re-warning form)
(declare (indent 1))
`(with-current-buffer (get-buffer-create "*Compile-Log*")
(let ((inhibit-read-only t)) (erase-buffer))
- (byte-compile ,@form)
- (ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
- (should (re-search-forward ,(string-replace " " "[ \n]+" re-warning))))))
+ (let ((text-quoting-style 'grave)
+ (macroexp--warned
+ (make-hash-table :test #'equal :weakness 'key)) ; oh dear
+ (form ,form))
+ (ert-info ((prin1-to-string form) :prefix "form: ")
+ (byte-compile form)
+ (ert-info ((prin1-to-string (buffer-string)) :prefix "buffer: ")
+ (should (re-search-forward
+ (string-replace " " "[ \n]+" ,re-warning))))))))
(ert-deftest bytecomp-warn-wrong-args ()
(bytecomp--with-warning-test "remq.*3.*2"
@@ -863,6 +922,66 @@ byte-compiled. Run with dynamic binding."
(bytecomp--with-warning-test "defvar.*foo.*wider than.*characters"
`(defvar foo t ,bytecomp-tests--docstring)))
+(ert-deftest bytecomp-warn-quoted-condition ()
+ (bytecomp--with-warning-test
+ "Warning: `condition-case' condition should not be quoted: 'arith-error"
+ '(condition-case nil
+ (abc)
+ ('arith-error "ugh")))
+ (bytecomp--with-warning-test
+ "Warning: `ignore-error' condition argument should not be quoted: 'error"
+ '(ignore-error 'error (abc))))
+
+(ert-deftest bytecomp-warn-dodgy-args-eq ()
+ (dolist (fn '(eq eql))
+ (cl-flet ((msg (type arg)
+ (format
+ "`%s' called with literal %s that may never match (arg %d)"
+ fn type arg)))
+ (bytecomp--with-warning-test (msg "list" 1) `(,fn '(a) 'x))
+ (bytecomp--with-warning-test (msg "string" 2) `(,fn 'x "a"))
+ (bytecomp--with-warning-test (msg "vector" 2) `(,fn 'x [a]))
+ (bytecomp--with-warning-test (msg "function" 2) `(,fn 'x (lambda () 1)))
+ (bytecomp--with-warning-test (msg "function" 2) `(,fn 'x #'(lambda () 1)))
+ (unless (eq fn 'eql)
+ (bytecomp--with-warning-test (msg "integer" 2) `(,fn 'x #x10000000000))
+ (bytecomp--with-warning-test (msg "float" 2) `(,fn 'x 1.0))))))
+
+(ert-deftest bytecomp-warn-dodgy-args-memq ()
+ (dolist (fn '(memq memql remq delq assq rassq))
+ (cl-labels
+ ((msg1 (type)
+ (format
+ "`%s' called with literal %s that may never match (arg 1)"
+ fn type))
+ (msg2 (type)
+ (format
+ "`%s' called with literal %s that may never match (element 2 of arg 2)"
+ fn type))
+ (lst (elt)
+ (cond ((eq fn 'assq) `((a . 1) (,elt . 2) (c . 3)))
+ ((eq fn 'rassq) `((1 . a) (2 . ,elt) (3 . c)))
+ (t `(a ,elt c))))
+ (form2 (elt)
+ `(,fn 'x ',(lst elt))))
+
+ (bytecomp--with-warning-test (msg1 "list") `(,fn '(a) '(x)))
+ (bytecomp--with-warning-test (msg1 "string") `(,fn "a" '(x)))
+ (bytecomp--with-warning-test (msg1 "vector") `(,fn [a] '(x)))
+ (bytecomp--with-warning-test (msg1 "function") `(,fn (lambda () 1) '(x)))
+ (bytecomp--with-warning-test (msg1 "function") `(,fn #'(lambda () 1) '(x)))
+ (unless (eq fn 'memql)
+ (bytecomp--with-warning-test (msg1 "integer") `(,fn #x10000000000 '(x)))
+ (bytecomp--with-warning-test (msg1 "float") `(,fn 1.0 '(x))))
+
+ (bytecomp--with-warning-test (msg2 "list") (form2 '(b)))
+ (bytecomp--with-warning-test (msg2 "list") (form2 ''b))
+ (bytecomp--with-warning-test (msg2 "string") (form2 "b"))
+ (bytecomp--with-warning-test (msg2 "vector") (form2 [b]))
+ (unless (eq fn 'memql)
+ (bytecomp--with-warning-test (msg2 "integer") (form2 #x10000000000))
+ (bytecomp--with-warning-test (msg2 "float") (form2 1.0))))))
+
(defmacro bytecomp--define-warning-file-test (file re-warning &optional reverse)
`(ert-deftest ,(intern (format "bytecomp/%s" file)) ()
(with-current-buffer (get-buffer-create "*Compile-Log*")
@@ -1314,7 +1433,50 @@ literals (Bug#20852)."
(set-buffer (get-buffer-create "foo"))
nil))
'((suspicious set-buffer))
- "Warning: Use .with-current-buffer. rather than"))
+ "Warning: Use .with-current-buffer. rather than")
+
+ (test-suppression
+ '(defun zot ()
+ (let ((_ 1))
+ ))
+ '((empty-body let))
+ "Warning: `let' with empty body")
+
+ (test-suppression
+ '(defun zot ()
+ (let* ((_ 1))
+ ))
+ '((empty-body let*))
+ "Warning: `let\\*' with empty body")
+
+ (test-suppression
+ '(defun zot (x)
+ (when x
+ ))
+ '((empty-body when))
+ "Warning: `when' with empty body")
+
+ (test-suppression
+ '(defun zot (x)
+ (unless x
+ ))
+ '((empty-body unless))
+ "Warning: `unless' with empty body")
+
+ (test-suppression
+ '(defun zot (x)
+ (ignore-error arith-error
+ ))
+ '((empty-body ignore-error))
+ "Warning: `ignore-error' with empty body")
+
+ (test-suppression
+ '(defun zot (x)
+ (with-suppressed-warnings ((suspicious eq))
+ ))
+ '((empty-body with-suppressed-warnings))
+ "Warning: `with-suppressed-warnings' with empty body")
+ )
(ert-deftest bytecomp-tests--not-writable-directory ()
"Test that byte compilation works if the output directory isn't
diff --git a/test/lisp/emacs-lisp/cl-lib-tests.el b/test/lisp/emacs-lisp/cl-lib-tests.el
index b19494af746..759138569e4 100644
--- a/test/lisp/emacs-lisp/cl-lib-tests.el
+++ b/test/lisp/emacs-lisp/cl-lib-tests.el
@@ -404,7 +404,7 @@
(ert-deftest cl-lib-nth-value-test-multiple-values ()
"While CL multiple values are an alias to list, these won't work."
:expected-result :failed
- (should (eq (cl-nth-value 0 '(2 3)) '(2 3)))
+ (should (equal (cl-nth-value 0 '(2 3)) '(2 3)))
(should (= (cl-nth-value 0 1) 1))
(should (null (cl-nth-value 1 1)))
(should-error (cl-nth-value -1 (cl-values 2 3)) :type 'args-out-of-range)
@@ -431,7 +431,8 @@
(should (eq nums (cdr (cl-adjoin 3 nums))))
;; add only when not already there
(should (eq nums (cl-adjoin 2 nums)))
- (should (equal '(2 1 (2)) (cl-adjoin 2 '(1 (2)))))
+ (with-suppressed-warnings ((suspicious eq))
+ (should (equal '(2 1 (2)) (cl-adjoin 2 '(1 (2))))))
;; default test function is eql
(should (equal '(1.0 1 2) (cl-adjoin 1.0 nums)))
;; own :test function - returns true if match
diff --git a/test/lisp/emacs-lisp/multisession-tests.el b/test/lisp/emacs-lisp/multisession-tests.el
index 5807c27bd20..68d9c9646ff 100644
--- a/test/lisp/emacs-lisp/multisession-tests.el
+++ b/test/lisp/emacs-lisp/multisession-tests.el
@@ -94,7 +94,7 @@
(dotimes (i 100)
(cl-incf (multisession-value multisession--bar))))))))
(while (process-live-p proc)
- (ignore-error 'sqlite-locked-error
+ (ignore-error sqlite-locked-error
(message "multisession--bar %s" (multisession-value multisession--bar))
;;(cl-incf (multisession-value multisession--bar))
)
diff --git a/test/lisp/eshell/em-alias-tests.el b/test/lisp/eshell/em-alias-tests.el
index aca622220e3..0a26e8d2011 100644
--- a/test/lisp/eshell/em-alias-tests.el
+++ b/test/lisp/eshell/em-alias-tests.el
@@ -72,6 +72,15 @@
(eshell-match-command-output "show-all-args a" "a\n")
(eshell-match-command-output "show-all-args a b c" "a\nb\nc\n")))
+(ert-deftest em-alias-test/alias-all-args-var-splice ()
+ "Test alias with splicing the $* variable"
+ (with-temp-eshell
+ (eshell-insert-command "alias show-all-args 'echo args: $@*'")
+ (eshell-match-command-output "show-all-args" "args:\n")
+ (eshell-match-command-output "show-all-args a" "(\"args:\" \"a\")\n")
+ (eshell-match-command-output "show-all-args a b c"
+ "(\"args:\" \"a\" \"b\" \"c\")\n")))
+
(ert-deftest em-alias-test/alias-all-args-var-indices ()
"Test alias with the $* variable using indices"
(with-temp-eshell
diff --git a/test/lisp/eshell/em-extpipe-tests.el b/test/lisp/eshell/em-extpipe-tests.el
index 04e78279427..a2646a0296b 100644
--- a/test/lisp/eshell/em-extpipe-tests.el
+++ b/test/lisp/eshell/em-extpipe-tests.el
@@ -42,7 +42,7 @@
(shell-command-switch "-c"))
;; Strip `eshell-trap-errors'.
(should (equal ,expected
- (cadr (eshell-parse-command input))))))
+ (cadadr (eshell-parse-command input))))))
(with-substitute-for-temp (&rest body)
;; Substitute name of an actual temporary file and/or
;; buffer into `input'. The substitution logic is
diff --git a/test/lisp/eshell/em-script-tests.el b/test/lisp/eshell/em-script-tests.el
index b837d464ccd..f720f697c67 100644
--- a/test/lisp/eshell/em-script-tests.el
+++ b/test/lisp/eshell/em-script-tests.el
@@ -35,21 +35,43 @@
;;; Tests:
(ert-deftest em-script-test/source-script ()
- "Test sourcing script with no argumentss"
+ "Test sourcing a simple script."
(ert-with-temp-file temp-file :text "echo hi"
(with-temp-eshell
(eshell-match-command-output (format "source %s" temp-file)
"hi\n"))))
-(ert-deftest em-script-test/source-script-arg-vars ()
- "Test sourcing script with $0, $1, ... variables"
+(ert-deftest em-script-test/source-script/redirect ()
+ "Test sourcing a script and redirecting its output."
+ (ert-with-temp-file temp-file
+ :text "echo hi\necho bye"
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "source %s > #<%s>" temp-file bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "hibye")))))
+
+(ert-deftest em-script-test/source-script/redirect/dev-null ()
+ "Test sourcing a script and redirecting its output, including to /dev/null."
+ (ert-with-temp-file temp-file
+ :text "echo hi\necho bad > /dev/null\necho bye"
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "source %s > #<%s>" temp-file bufname)
+ "\\`\\'"))
+ (should (equal (buffer-string) "hibye")))))
+
+(ert-deftest em-script-test/source-script/arg-vars ()
+ "Test sourcing script with $0, $1, ... variables."
(ert-with-temp-file temp-file :text "printnl $0 \"$1 $2\""
(with-temp-eshell
(eshell-match-command-output (format "source %s one two" temp-file)
(format "%s\none two\n" temp-file)))))
-(ert-deftest em-script-test/source-script-all-args-var ()
- "Test sourcing script with the $* variable"
+(ert-deftest em-script-test/source-script/all-args-var ()
+ "Test sourcing script with the $* variable."
(ert-with-temp-file temp-file :text "printnl $*"
(with-temp-eshell
(eshell-match-command-output (format "source %s" temp-file)
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
index 6cc35ecdb1b..936397d8869 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -23,37 +23,41 @@
(require 'em-tramp)
(require 'tramp)
+(defmacro em-tramp-test/should-replace-command (form replacement)
+ "Check that calling FORM results in it being replaced with REPLACEMENT."
+ (declare (indent 1))
+ `(should (equal
+ (catch 'eshell-replace-command ,form)
+ (list 'eshell-with-copied-handles
+ (list 'eshell-trap-errors
+ ,replacement)
+ t))))
+
(ert-deftest em-tramp-test/su-default ()
"Test Eshell `su' command with no arguments."
- (should (equal
- (catch 'eshell-replace-command (eshell/su))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/su:root@%s:%s"
- tramp-default-host default-directory)))))))
+ (em-tramp-test/should-replace-command (eshell/su)
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:%s"
+ tramp-default-host default-directory)))))
(ert-deftest em-tramp-test/su-user ()
"Test Eshell `su' command with USER argument."
- (should (equal
- (catch 'eshell-replace-command (eshell/su "USER"))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/su:USER@%s:%s"
- tramp-default-host default-directory)))))))
+ (em-tramp-test/should-replace-command (eshell/su "USER")
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/su:USER@%s:%s"
+ tramp-default-host default-directory)))))
(ert-deftest em-tramp-test/su-login ()
"Test Eshell `su' command with -/-l/--login option."
(dolist (args '(("--login")
("-l")
("-")))
- (should (equal
- (catch 'eshell-replace-command (apply #'eshell/su args))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/su:root@%s:~/" tramp-default-host))))))))
+ (em-tramp-test/should-replace-command (apply #'eshell/su args)
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/su:root@%s:~/" tramp-default-host))))))
(defun mock-eshell-named-command (&rest args)
"Dummy function to test Eshell `sudo' command rewriting."
@@ -89,23 +93,19 @@
"Test Eshell `sudo' command with -s/--shell option."
(dolist (args '(("--shell")
("-s")))
- (should (equal
- (catch 'eshell-replace-command (apply #'eshell/sudo args))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/sudo:root@%s:%s"
- tramp-default-host default-directory))))))))
+ (em-tramp-test/should-replace-command (apply #'eshell/sudo args)
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/sudo:root@%s:%s"
+ tramp-default-host default-directory))))))
(ert-deftest em-tramp-test/sudo-user-shell ()
"Test Eshell `sudo' command with -s and -u options."
- (should (equal
- (catch 'eshell-replace-command (eshell/sudo "-u" "USER" "-s"))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/sudo:USER@%s:%s"
- tramp-default-host default-directory)))))))
+ (em-tramp-test/should-replace-command (eshell/sudo "-u" "USER" "-s")
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/sudo:USER@%s:%s"
+ tramp-default-host default-directory)))))
(ert-deftest em-tramp-test/doas-basic ()
"Test Eshell `doas' command with default user."
@@ -142,22 +142,18 @@
"Test Eshell `doas' command with -s/--shell option."
(dolist (args '(("--shell")
("-s")))
- (should (equal
- (catch 'eshell-replace-command (apply #'eshell/doas args))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/doas:root@%s:%s"
- tramp-default-host default-directory))))))))
+ (em-tramp-test/should-replace-command (apply #'eshell/doas args)
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/doas:root@%s:%s"
+ tramp-default-host default-directory))))))
(ert-deftest em-tramp-test/doas-user-shell ()
"Test Eshell `doas' command with -s and -u options."
- (should (equal
- (catch 'eshell-replace-command (eshell/doas "-u" "USER" "-s"))
- `(eshell-trap-errors
- (eshell-named-command
- "cd"
- (list ,(format "/doas:USER@%s:%s"
- tramp-default-host default-directory)))))))
+ (em-tramp-test/should-replace-command (eshell/doas "-u" "USER" "-s")
+ `(eshell-named-command
+ "cd"
+ (list ,(format "/doas:USER@%s:%s"
+ tramp-default-host default-directory)))))
;;; em-tramp-tests.el ends here
diff --git a/test/lisp/eshell/esh-cmd-tests.el b/test/lisp/eshell/esh-cmd-tests.el
index 92d785d7fdf..42d24967ff8 100644
--- a/test/lisp/eshell/esh-cmd-tests.el
+++ b/test/lisp/eshell/esh-cmd-tests.el
@@ -148,14 +148,21 @@ e.g. \"{(+ 1 2)} 3\" => 3"
"echo $name; for name in 3 { echo $name }; echo $name"
"env-value\n3\nenv-value\n"))))
+(ert-deftest esh-cmd-test/for-loop-pipe ()
+ "Test invocation of a for loop piped to another command."
+ (skip-unless (executable-find "rev"))
+ (with-temp-eshell
+ (eshell-match-command-output "for i in foo bar baz { echo $i } | rev"
+ "zabraboof")))
+
(ert-deftest esh-cmd-test/while-loop ()
"Test invocation of a while loop."
(with-temp-eshell
(let ((eshell-test-value '(0 1 2)))
(eshell-match-command-output
(concat "while $eshell-test-value "
- "{ setq eshell-test-value (cdr eshell-test-value) }")
- "(1 2)\n(2)\n"))))
+ "{ (pop eshell-test-value) }")
+ "0\n1\n2\n"))))
(ert-deftest esh-cmd-test/while-loop-lisp-form ()
"Test invocation of a while loop using a Lisp form."
@@ -176,6 +183,17 @@ e.g. \"{(+ 1 2)} 3\" => 3"
"{ setq eshell-test-value (1+ eshell-test-value) }")
"1\n2\n3\n"))))
+(ert-deftest esh-cmd-test/while-loop-pipe ()
+ "Test invocation of a while loop piped to another command."
+ (skip-unless (executable-find "rev"))
+ (with-temp-eshell
+ (let ((eshell-test-value '("foo" "bar" "baz")))
+ (eshell-match-command-output
+ (concat "while $eshell-test-value "
+ "{ (pop eshell-test-value) }"
+ " | rev")
+ "zabraboof"))))
+
(ert-deftest esh-cmd-test/until-loop ()
"Test invocation of an until loop."
(with-temp-eshell
@@ -253,6 +271,30 @@ This tests when `eshell-lisp-form-nil-is-failure' is nil."
(eshell-command-result-equal "if {[ foo = bar ]} {echo yes} {echo no}"
"no"))
+(ert-deftest esh-cmd-test/if-statement-pipe ()
+ "Test invocation of an if statement piped to another command."
+ (skip-unless (executable-find "rev"))
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-match-command-output "if $eshell-test-value {echo yes} | rev"
+ "\\`sey\n?"))
+ (let ((eshell-test-value nil))
+ (eshell-match-command-output "if $eshell-test-value {echo yes} | rev"
+ "\\`\n?"))))
+
+(ert-deftest esh-cmd-test/if-else-statement-pipe ()
+ "Test invocation of an if/else statement piped to another command."
+ (skip-unless (executable-find "rev"))
+ (with-temp-eshell
+ (let ((eshell-test-value t))
+ (eshell-match-command-output
+ "if $eshell-test-value {echo yes} {echo no} | rev"
+ "\\`sey\n?"))
+ (let ((eshell-test-value nil))
+ (eshell-match-command-output
+ "if $eshell-test-value {echo yes} {echo no} | rev"
+ "\\`on\n?"))))
+
(ert-deftest esh-cmd-test/unless-statement ()
"Test invocation of an unless statement."
(let ((eshell-test-value t))
diff --git a/test/lisp/eshell/esh-io-tests.el b/test/lisp/eshell/esh-io-tests.el
index 37b234eaf06..52501f5bb70 100644
--- a/test/lisp/eshell/esh-io-tests.el
+++ b/test/lisp/eshell/esh-io-tests.el
@@ -146,6 +146,45 @@
(should (equal (buffer-string) "new"))
(should (equal eshell-test-value "new")))))
+(ert-deftest esh-io-test/redirect-subcommands ()
+ "Check that redirecting subcommands applies to all subcommands."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command (format "{echo foo; echo bar} > #<%s>" bufname)))
+ (should (equal (buffer-string) "foobar"))))
+
+(ert-deftest esh-io-test/redirect-subcommands/override ()
+ "Check that redirecting subcommands applies to all subcommands.
+Include a redirect to another location in the subcommand to
+ensure only its statement is redirected."
+ (eshell-with-temp-buffer bufname "old"
+ (eshell-with-temp-buffer bufname-2 "also old"
+ (with-temp-eshell
+ (eshell-insert-command
+ (format "{echo foo; echo bar > #<%s>; echo baz} > #<%s>"
+ bufname-2 bufname)))
+ (should (equal (buffer-string) "bar")))
+ (should (equal (buffer-string) "foobaz"))))
+
+(ert-deftest esh-io-test/redirect-subcommands/dev-null ()
+ "Check that redirecting subcommands applies to all subcommands.
+Include a redirect to /dev/null to ensure it only applies to its
+statement."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command
+ (format "{echo foo; echo bar > /dev/null; echo baz} > #<%s>"
+ bufname)))
+ (should (equal (buffer-string) "foobaz"))))
+
+(ert-deftest esh-io-test/redirect-subcommands/interpolated ()
+ "Check that redirecting interpolated subcommands applies to all subcommands."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-insert-command
+ (format "echo ${echo foo; echo bar} > #<%s>" bufname)))
+ (should (equal (buffer-string) "foobar"))))
+
;; Redirecting specific handles
@@ -262,24 +301,56 @@ stdout originally pointed (the terminal)."
"stderr\n"))
(should (equal (buffer-string) "stdout\n"))))
-(ert-deftest esh-io-test/redirect-pipe ()
- "Check that \"redirecting\" to a pipe works."
- ;; `|' should only redirect stdout.
+
+;; Pipelines
+
+(ert-deftest esh-io-test/pipeline/default ()
+ "Check that `|' only pipes stdout."
+ (skip-unless (executable-find "rev"))
(eshell-command-result-equal "test-output | rev"
- "stderr\ntuodts\n")
- ;; `|&' should redirect stdout and stderr.
+ "stderr\ntuodts\n"))
+
+
+(ert-deftest esh-io-test/pipeline/all ()
+ "Check that `|&' only pipes stdout and stderr."
+ (skip-unless (executable-find "rev"))
(eshell-command-result-equal "test-output |& rev"
"tuodts\nrredts\n"))
+(ert-deftest esh-io-test/pipeline/subcommands ()
+ "Chek that all commands in a subcommand are properly piped."
+ (skip-unless (executable-find "rev"))
+ (with-temp-eshell
+ (eshell-match-command-output "{echo foo; echo bar} | rev"
+ "\\`raboof\n?")))
+
;; Virtual targets
-(ert-deftest esh-io-test/virtual-dev-eshell ()
+(ert-deftest esh-io-test/virtual/dev-null ()
+ "Check that redirecting to /dev/null works."
+ (with-temp-eshell
+ (eshell-match-command-output "echo hi > /dev/null" "\\`\\'")))
+
+(ert-deftest esh-io-test/virtual/dev-null/multiple ()
+ "Check that redirecting to /dev/null works alongside other redirections."
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "echo new > /dev/null > #<%s>" bufname) "\\`\\'"))
+ (should (equal (buffer-string) "new")))
+ (eshell-with-temp-buffer bufname "old"
+ (with-temp-eshell
+ (eshell-match-command-output
+ (format "echo new > #<%s> > /dev/null" bufname) "\\`\\'"))
+ (should (equal (buffer-string) "new"))))
+
+(ert-deftest esh-io-test/virtual/dev-eshell ()
"Check that redirecting to /dev/eshell works."
(with-temp-eshell
(eshell-match-command-output "echo hi > /dev/eshell" "hi")))
-(ert-deftest esh-io-test/virtual-dev-kill ()
+(ert-deftest esh-io-test/virtual/dev-kill ()
"Check that redirecting to /dev/kill works."
(with-temp-eshell
(eshell-insert-command "echo one > /dev/kill")
diff --git a/test/lisp/eshell/esh-var-tests.el b/test/lisp/eshell/esh-var-tests.el
index 96fde026a54..d95669fdaf8 100644
--- a/test/lisp/eshell/esh-var-tests.el
+++ b/test/lisp/eshell/esh-var-tests.el
@@ -60,6 +60,18 @@
(eshell-command-result-equal "echo $\"user-login-name\"-foo"
(concat user-login-name "-foo")))
+(ert-deftest esh-var-test/interp-list-var ()
+ "Interpolate list variable"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo $eshell-test-value"
+ '(1 2 3))))
+
+(ert-deftest esh-var-test/interp-list-var-concat ()
+ "Interpolate and concat list variable"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo a$'eshell-test-value'z"
+ '("a1" 2 "3z"))))
+
(ert-deftest esh-var-test/interp-var-indices ()
"Interpolate list variable with indices"
(let ((eshell-test-value '("zero" "one" "two" "three" "four")))
@@ -131,6 +143,26 @@
(eshell-command-result-equal "echo $#eshell-test-value" 1)
(eshell-command-result-equal "echo $#eshell-test-value[foo]" 3)))
+(ert-deftest esh-var-test/interp-var-splice ()
+ "Splice-interpolate list variable"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo a $@eshell-test-value z"
+ '("a" 1 2 3 "z"))))
+
+(ert-deftest esh-var-test/interp-var-splice-concat ()
+ "Splice-interpolate and concat list variable"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo it is a$@'eshell-test-value'z"
+ '("it" "is" "a1" 2 "3z"))
+ ;; This is a tricky case. We're concatenating a spliced list and
+ ;; a non-spliced list. The general rule is that splicing should
+ ;; work as though the user typed "$X[0] $X[1] ... $X[N]". That
+ ;; means that the last value of our splice should get concatenated
+ ;; into the first value of the non-spliced list.
+ (eshell-command-result-equal
+ "echo it is $@'eshell-test-value'$eshell-test-value"
+ '("it" "is" 1 2 (31 2 3)))))
+
(ert-deftest esh-var-test/interp-lisp ()
"Interpolate Lisp form evaluation"
(eshell-command-result-equal "+ $(+ 1 2) 3" 6))
@@ -197,6 +229,9 @@
(eshell-match-command-output "echo ${echo hi}-${*echo there}"
"hi-there\n")))
+
+;; Quoted variable interpolation
+
(ert-deftest esh-var-test/quoted-interp-var ()
"Interpolate variable inside double-quotes"
(eshell-command-result-equal "echo \"$user-login-name\""
@@ -209,6 +244,18 @@
(eshell-command-result-equal "echo \"hi, $\\\"user-login-name\\\"\""
(concat "hi, " user-login-name)))
+(ert-deftest esh-var-test/quoted-interp-list-var ()
+ "Interpolate list variable inside double-quotes"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo \"$eshell-test-value\""
+ "(1 2 3)")))
+
+(ert-deftest esh-var-test/quoted-interp-list-var-concat ()
+ "Interpolate and concat list variable inside double-quotes"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo \"a$'eshell-test-value'z\""
+ "a(1 2 3)z")))
+
(ert-deftest esh-var-test/quoted-interp-var-indices ()
"Interpolate string variable with indices inside double-quotes"
(let ((eshell-test-value '("zero" "one" "two" "three" "four")))
@@ -291,6 +338,18 @@ inside double-quotes"
(eshell-command-result-equal "echo \"$#eshell-test-value[foo]\""
"3")))
+(ert-deftest esh-var-test/quoted-interp-var-splice ()
+ "Splice-interpolate list variable inside double-quotes"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo a \"$@eshell-test-value\" z"
+ '("a" "1 2 3" "z"))))
+
+(ert-deftest esh-var-test/quoted-interp-var-splice-concat ()
+ "Splice-interpolate and concat list variable inside double-quotes"
+ (let ((eshell-test-value '(1 2 3)))
+ (eshell-command-result-equal "echo \"a$@'eshell-test-value'z\""
+ "a1 2 3z")))
+
(ert-deftest esh-var-test/quoted-interp-lisp ()
"Interpolate Lisp form evaluation inside double-quotes"
(eshell-command-result-equal "echo \"hi $(concat \\\"the\\\" \\\"re\\\")\""
@@ -325,6 +384,21 @@ inside double-quotes"
"foo\nbar baz"))
+;; Interpolating commands
+
+(ert-deftest esh-var-test/command-interp ()
+ "Interpolate a variable as a command name"
+ (let ((eshell-test-value "printnl"))
+ (eshell-command-result-equal "$eshell-test-value hello there"
+ "hello\nthere\n")))
+
+(ert-deftest esh-var-test/command-interp-splice ()
+ "Interpolate a splice variable as a command name with arguments"
+ (let ((eshell-test-value '("printnl" "hello" "there")))
+ (eshell-command-result-equal "$@eshell-test-value"
+ "hello\nthere\n")))
+
+
;; Interpolated variable conversion
(ert-deftest esh-var-test/interp-convert-var-number ()
diff --git a/test/lisp/eshell/eshell-tests-helpers.el b/test/lisp/eshell/eshell-tests-helpers.el
index 1d9674070c0..a9338050311 100644
--- a/test/lisp/eshell/eshell-tests-helpers.el
+++ b/test/lisp/eshell/eshell-tests-helpers.el
@@ -33,9 +33,9 @@
(defvar eshell-history-file-name nil)
(defvar eshell-last-dir-ring-file-name nil)
-(defvar eshell-test--max-subprocess-time 5
- "The maximum amount of time to wait for a subprocess to finish, in seconds.
-See `eshell-wait-for-subprocess'.")
+(defvar eshell-test--max-wait-time 5
+ "The maximum amount of time to wait for a condition to resolve, in seconds.
+See `eshell-wait-for'.")
(defun eshell-tests-remote-accessible-p ()
"Return if a test involving remote files can proceed.
@@ -73,19 +73,28 @@ BUFNAME will be set to the name of the temporary buffer."
(let ((,bufname (buffer-name)))
,@body)))
+(defun eshell-wait-for (predicate &optional message)
+ "Wait until PREDICATE returns non-nil.
+If this takes longer than `eshell-test--max-wait-time', raise an
+error. MESSAGE is an optional message to use if this times out."
+ (let ((start (current-time))
+ (message (or message "timed out waiting for condition")))
+ (while (not (funcall predicate))
+ (when (> (float-time (time-since start))
+ eshell-test--max-wait-time)
+ (error message))
+ (sit-for 0.1))))
+
(defun eshell-wait-for-subprocess (&optional all)
"Wait until there is no interactive subprocess running in Eshell.
If ALL is non-nil, wait until there are no Eshell subprocesses at
all running.
-If this takes longer than `eshell-test--max-subprocess-time',
+If this takes longer than `eshell-test--max-wait-time',
raise an error."
- (let ((start (current-time)))
- (while (if all eshell-process-list (eshell-interactive-process-p))
- (when (> (float-time (time-since start))
- eshell-test--max-subprocess-time)
- (error "timed out waiting for subprocess(es)"))
- (sit-for 0.1))))
+ (eshell-wait-for
+ (lambda ()
+ (not (if all eshell-process-list (eshell-interactive-process-p))))))
(defun eshell-insert-command (command &optional func)
"Insert a COMMAND at the end of the buffer.
diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el
index c67ac67fd36..dd8be8e65f0 100644
--- a/test/lisp/eshell/eshell-tests.el
+++ b/test/lisp/eshell/eshell-tests.el
@@ -128,16 +128,17 @@
(delete-region (point) (point-max))))))
(ert-deftest eshell-test/queue-input ()
- "Test queuing command input"
+ "Test queuing command input.
+This should let the current command finish, then automatically
+insert the queued one at the next prompt, and finally run it."
(with-temp-eshell
- (eshell-insert-command "sleep 2")
- (eshell-insert-command "echo alpha" 'eshell-queue-input)
- (let ((count 10))
- (while (and eshell-current-command
- (> count 0))
- (sit-for 1)
- (setq count (1- count))))
- (should (eshell-match-output "alpha\n"))))
+ (eshell-insert-command "sleep 1; echo slept")
+ (eshell-insert-command "echo alpha" #'eshell-queue-input)
+ (let ((start (marker-position (eshell-beginning-of-output))))
+ (eshell-wait-for (lambda () (not eshell-current-command)))
+ (should (string-match "^slept\n.*echo alpha\nalpha\n$"
+ (buffer-substring-no-properties
+ start (eshell-end-of-output)))))))
(ert-deftest eshell-test/flush-output ()
"Test flushing of previous output"
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el
index 8d63bb3de9b..50b0e948e49 100644
--- a/test/lisp/net/tramp-tests.el
+++ b/test/lisp/net/tramp-tests.el
@@ -2857,6 +2857,7 @@ This checks also `file-name-as-directory', `file-name-directory',
This tests also `file-directory-p' and `file-accessible-directory-p'."
(skip-unless (tramp--test-enabled))
+ ;; Since Emacs 29.1, `make-directory' has defined return values.
(dolist (quoted (if (tramp--test-expensive-test-p) '(nil t) '(nil)))
(let* ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (expand-file-name "foo/bar" tmp-name1))
@@ -2865,7 +2866,9 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(unwind-protect
(progn
(with-file-modes unusual-file-mode-1
- (make-directory tmp-name1))
+ (if (tramp--test-emacs29-p)
+ (should-not (make-directory tmp-name1))
+ (make-directory tmp-name1)))
(should-error
(make-directory tmp-name1)
:type 'file-already-exists)
@@ -2878,15 +2881,19 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
(make-directory tmp-name2)
:type 'file-error)
(with-file-modes unusual-file-mode-2
- (make-directory tmp-name2 'parents))
+ (if (tramp--test-emacs29-p)
+ (should-not (make-directory tmp-name2 'parents))
+ (make-directory tmp-name2 'parents)))
(should (file-directory-p tmp-name2))
(should (file-accessible-directory-p tmp-name2))
(when (tramp--test-supports-set-file-modes-p)
(should (equal (format "%#o" unusual-file-mode-2)
(format "%#o" (file-modes tmp-name2)))))
;; If PARENTS is non-nil, `make-directory' shall not
- ;; signal an error when DIR exists already.
- (make-directory tmp-name2 'parents))
+ ;; signal an error when DIR exists already. It returns t.
+ (if (tramp--test-emacs29-p)
+ (should (make-directory tmp-name2 'parents))
+ (make-directory tmp-name2 'parents)))
;; Cleanup.
(ignore-errors (delete-directory tmp-name1 'recursive))))))
diff --git a/test/lisp/proced-tests.el b/test/lisp/proced-tests.el
new file mode 100644
index 00000000000..3c1f5493e74
--- /dev/null
+++ b/test/lisp/proced-tests.el
@@ -0,0 +1,105 @@
+;;; proced-tests.el --- Test suite for proced.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2022 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+(require 'proced)
+(require 'thingatpt)
+
+(cl-defmacro proced--within-buffer (format filter &body body)
+ "Execute BODY within a proced buffer using format FORMAT and filter FILTER."
+ `(let ((proced-format ,format)
+ (proced-filter ,filter)
+ (proced-auto-update-flag nil)
+ (inhibit-message t))
+ (proced)
+ (unwind-protect
+ (with-current-buffer "*Proced*"
+ ,@body)
+ (kill-buffer "*Proced*"))))
+
+(defun proced--assert-emacs-pid-in-buffer ()
+ "Fail unless the process ID of the current Emacs process exists in buffer."
+ (should (string-match-p
+ (number-to-string (emacs-pid))
+ (buffer-substring-no-properties (point-min) (point-max)))))
+
+(defun proced--move-to-column (attribute)
+ "Move to the column under ATTRIBUTE in the current proced buffer."
+ (move-to-column (string-match attribute proced-header-line)))
+
+(ert-deftest proced-format-test ()
+ (dolist (format '(short medium long verbose))
+ (proced--within-buffer
+ format
+ 'user
+ (proced--assert-emacs-pid-in-buffer))))
+
+(ert-deftest proced-update-test ()
+ (proced--within-buffer
+ 'short
+ 'user
+ (proced-update)
+ (proced--assert-emacs-pid-in-buffer)))
+
+(ert-deftest proced-revert-test ()
+ (proced--within-buffer
+ 'short
+ 'user
+ (proced-revert)
+ (proced--assert-emacs-pid-in-buffer)))
+
+(ert-deftest proced-color-test ()
+ (let ((proced-enable-color-flag t))
+ (proced--within-buffer
+ 'short
+ 'user
+ (proced--assert-emacs-pid-in-buffer))))
+
+(ert-deftest proced-refine-test ()
+ ;;(skip-unless (memq system-type '(gnu/linux gnu/kfreebsd darwin)))
+ (proced--within-buffer
+ 'medium
+ 'user
+ ;; When refining on PID for process A, a process is kept if and only
+ ;; if its PID are the same as process A, which more or less guarentees
+ ;; the refinement will remove some processes.
+ (proced--move-to-column "PID")
+ (let ((pid (word-at-point)))
+ (proced-refine)
+ (while (not (eobp))
+ (proced--move-to-column "PID")
+ (should (string= pid (word-at-point)))
+ (forward-line)))))
+
+(ert-deftest proced-refine-with-update-test ()
+ (proced--within-buffer
+ 'medium
+ 'user
+ (proced--move-to-column "PID")
+ (let ((pid (word-at-point)))
+ (proced-refine)
+ (proced-update t)
+ (while (not (eobp))
+ (proced--move-to-column "PID")
+ (should (string= pid (word-at-point)))
+ (forward-line)))))
+
+(provide 'proced-tests)
+;;; proced-tests.el ends here
diff --git a/test/lisp/url/url-future-tests.el b/test/lisp/url/url-future-tests.el
index 5083fc5abae..ec1796f7670 100644
--- a/test/lisp/url/url-future-tests.el
+++ b/test/lisp/url/url-future-tests.el
@@ -52,7 +52,7 @@
(should (equal (url-future-cancel tocancel) tocancel))
(should-error (url-future-call tocancel))
(should (null url-future-tests--saver))
- (should (url-future-cancelled-p tocancel))))
+ (should (url-future-canceled-p tocancel))))
(provide 'url-future-tests)
diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el
index d72748cd0c9..3a53e025036 100644
--- a/test/lisp/whitespace-tests.el
+++ b/test/lisp/whitespace-tests.el
@@ -57,6 +57,24 @@ buffer's content."
(whitespace-cleanup)
(buffer-string)))
+(ert-deftest whitespace-tests--global ()
+ (let ((backup global-whitespace-mode)
+ (noninteractive nil)
+ (whitespace-enable-predicate (lambda () t)))
+ (unwind-protect
+ (progn
+ (global-whitespace-mode 1)
+ (ert-with-test-buffer-selected ()
+ (normal-mode)
+ (should whitespace-mode)
+ (global-whitespace-mode -1)
+ (should (null whitespace-mode))
+ (whitespace-mode 1)
+ (should whitespace-mode)
+ (global-whitespace-mode 1)
+ (should whitespace-mode)))
+ (global-whitespace-mode (if backup 1 -1)))))
+
(ert-deftest whitespace-cleanup-eob ()
(let ((whitespace-style '(empty)))
(should (equal (whitespace-tests--cleanup-string "a\n")
diff --git a/test/manual/noverlay/itree-tests.c b/test/manual/noverlay/itree-tests.c
index 278e65f9bf7..8cab7bf84d4 100644
--- a/test/manual/noverlay/itree-tests.c
+++ b/test/manual/noverlay/itree-tests.c
@@ -26,7 +26,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "emacs-compat.h"
#define EMACS_LISP_H /* lisp.h inclusion guard */
-#define ITREE_DEBUG 1
#define ITREE_TESTING
#include "itree.c"
@@ -53,7 +52,7 @@ test_insert1_setup (void)
enum { N = 6 };
const int values[N] = {50, 30, 20, 10, 15, 5};
struct itree_node *nodes[N] = {&N_50, &N_30, &N_20, &N_10, &N_15, &N_05};
- interval_tree_init (&tree);
+ itree_init (&tree);
for (int i = 0; i < N; ++i)
{
nodes[i]->begin = nodes[i]->end = values[i];
@@ -67,7 +66,7 @@ START_TEST (test_insert_1)
* [50]
*/
- interval_tree_insert (&tree, &N_50);
+ itree_insert_node (&tree, &N_50);
ck_assert (! N_50.red);
ck_assert_ptr_eq (&N_50, tree.root);
}
@@ -81,8 +80,8 @@ START_TEST (test_insert_2)
* (30)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_30);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_30);
ck_assert (! N_50.red);
ck_assert (N_30.red);
ck_assert_ptr_eq (&N_50, tree.root);
@@ -102,9 +101,9 @@ START_TEST (test_insert_3)
* (20) (50)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_30);
- interval_tree_insert (&tree, &N_20);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_30);
+ itree_insert_node (&tree, &N_20);
ck_assert (N_50.red);
ck_assert (! N_30.red);
ck_assert (N_20.red);
@@ -128,10 +127,10 @@ START_TEST (test_insert_4)
* (10)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_30);
- interval_tree_insert (&tree, &N_20);
- interval_tree_insert (&tree, &N_10);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_30);
+ itree_insert_node (&tree, &N_20);
+ itree_insert_node (&tree, &N_10);
ck_assert (! N_50.red);
ck_assert (! N_30.red);
ck_assert (! N_20.red);
@@ -159,11 +158,11 @@ START_TEST (test_insert_5)
* (10) (20)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_30);
- interval_tree_insert (&tree, &N_20);
- interval_tree_insert (&tree, &N_10);
- interval_tree_insert (&tree, &N_15);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_30);
+ itree_insert_node (&tree, &N_20);
+ itree_insert_node (&tree, &N_10);
+ itree_insert_node (&tree, &N_15);
ck_assert (! N_50.red);
ck_assert (! N_30.red);
ck_assert (N_20.red);
@@ -197,12 +196,12 @@ START_TEST (test_insert_6)
* (5)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_30);
- interval_tree_insert (&tree, &N_20);
- interval_tree_insert (&tree, &N_10);
- interval_tree_insert (&tree, &N_15);
- interval_tree_insert (&tree, &N_05);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_30);
+ itree_insert_node (&tree, &N_20);
+ itree_insert_node (&tree, &N_10);
+ itree_insert_node (&tree, &N_15);
+ itree_insert_node (&tree, &N_05);
ck_assert (! N_50.red);
ck_assert (! N_30.red);
ck_assert (! N_20.red);
@@ -238,7 +237,7 @@ test_insert2_setup (void)
enum { N = 6 };
const int values[] = {50, 70, 80, 90, 85, 95};
struct itree_node *nodes[N] = {&N_50, &N_70, &N_80, &N_90, &N_85, &N_95};
- interval_tree_init (&tree);
+ itree_init (&tree);
for (int i = 0; i < N; ++i)
{
nodes[i]->begin = nodes[i]->end = values[i];
@@ -252,7 +251,7 @@ START_TEST (test_insert_7)
* [50]
*/
- interval_tree_insert (&tree, &N_50);
+ itree_insert_node (&tree, &N_50);
ck_assert (! N_50.red);
ck_assert_ptr_eq (&N_50, tree.root);
}
@@ -266,8 +265,8 @@ START_TEST (test_insert_8)
* (70)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_70);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_70);
ck_assert (! N_50.red);
ck_assert (N_70.red);
ck_assert_ptr_eq (&N_50, tree.root);
@@ -287,9 +286,9 @@ START_TEST (test_insert_9)
* (50) (80)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_70);
- interval_tree_insert (&tree, &N_80);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_70);
+ itree_insert_node (&tree, &N_80);
ck_assert (N_50.red);
ck_assert (! N_70.red);
ck_assert (N_80.red);
@@ -313,10 +312,10 @@ START_TEST (test_insert_10)
* (90)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_70);
- interval_tree_insert (&tree, &N_80);
- interval_tree_insert (&tree, &N_90);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_70);
+ itree_insert_node (&tree, &N_80);
+ itree_insert_node (&tree, &N_90);
ck_assert (! N_50.red);
ck_assert (! N_70.red);
ck_assert (! N_80.red);
@@ -344,11 +343,11 @@ START_TEST (test_insert_11)
* (80) (90)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_70);
- interval_tree_insert (&tree, &N_80);
- interval_tree_insert (&tree, &N_90);
- interval_tree_insert (&tree, &N_85);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_70);
+ itree_insert_node (&tree, &N_80);
+ itree_insert_node (&tree, &N_90);
+ itree_insert_node (&tree, &N_85);
ck_assert (! N_50.red);
ck_assert (! N_70.red);
ck_assert (N_80.red);
@@ -383,12 +382,12 @@ START_TEST (test_insert_12)
* (95)
*/
- interval_tree_insert (&tree, &N_50);
- interval_tree_insert (&tree, &N_70);
- interval_tree_insert (&tree, &N_80);
- interval_tree_insert (&tree, &N_90);
- interval_tree_insert (&tree, &N_85);
- interval_tree_insert (&tree, &N_95);
+ itree_insert_node (&tree, &N_50);
+ itree_insert_node (&tree, &N_70);
+ itree_insert_node (&tree, &N_80);
+ itree_insert_node (&tree, &N_90);
+ itree_insert_node (&tree, &N_85);
+ itree_insert_node (&tree, &N_95);
ck_assert (! N_50.red);
ck_assert (! N_70.red);
ck_assert (! N_80.red);
@@ -419,7 +418,7 @@ START_TEST (test_insert_13)
enum { N = 4 };
const int values[N] = {10, 20, 30, 40};
struct itree_node *nodes[N] = {&N_10, &N_20, &N_30, &N_40};
- interval_tree_init (&tree);
+ itree_init (&tree);
for (int i = 0; i < N; ++i)
itree_insert (&tree, nodes[i], values[i], values[i]);
@@ -437,13 +436,13 @@ END_TEST
START_TEST (test_insert_14)
{
enum { N = 3 };
- struct itree_node nodes[N];
- interval_tree_init (&tree);
+ struct itree_node nodes[N] = {0};
+ itree_init (&tree);
for (int i = 0; i < N; ++i)
itree_insert (&tree, &nodes[i], 10, 10);
for (int i = 0; i < N; ++i)
- ck_assert (interval_tree_contains (&tree, &nodes[i]));
+ ck_assert (itree_contains (&tree, &nodes[i]));
}
END_TEST
@@ -458,7 +457,7 @@ END_TEST
static void
test_remove1_setup (void)
{
- interval_tree_init (&tree);
+ itree_init (&tree);
tree.root = &B;
A.parent = &B; B.parent = NULL; C.parent = &D; D.parent = &B; E.parent = &D;
A.left = A.right = C.left = C.right = E.left = E.right = NULL;
@@ -480,7 +479,7 @@ START_TEST (test_remove_1)
{
B.red = A.red = C.red = E.red = false;
D.red = true;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -502,7 +501,7 @@ END_TEST
START_TEST (test_remove_2)
{
B.red = D.red = A.red = C.red = E.red = false;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -523,7 +522,7 @@ START_TEST (test_remove_3)
{
D.red = A.red = E.red = false;
B.red = C.red = true;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -546,7 +545,7 @@ START_TEST (test_remove_4)
{
B.red = C.red = E.red = true;
A.red = D.red = false;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -569,7 +568,7 @@ END_TEST
static void
test_remove2_setup (void)
{
- interval_tree_init (&tree);
+ itree_init (&tree);
tree.root = &B;
A.parent = &B; B.parent = NULL; C.parent = &D; D.parent = &B; E.parent = &D;
A.right = A.left = C.right = C.left = E.right = E.left = NULL;
@@ -589,7 +588,7 @@ START_TEST (test_remove_5)
{
B.red = A.red = C.red = E.red = false;
D.red = true;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -611,7 +610,7 @@ END_TEST
START_TEST (test_remove_6)
{
B.red = D.red = A.red = C.red = E.red = false;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -632,7 +631,7 @@ START_TEST (test_remove_7)
{
D.red = A.red = E.red = false;
B.red = C.red = true;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -655,7 +654,7 @@ START_TEST (test_remove_8)
{
B.red = C.red = E.red = true;
A.red = D.red = false;
- interval_tree_remove_fix (&tree, &A, &B);
+ itree_remove_fix (&tree, &A, &B);
ck_assert (! A.red);
ck_assert (! B.red);
@@ -676,7 +675,7 @@ START_TEST (test_remove_9)
enum { N = 4 };
const int values[N] = {10, 20, 30, 40};
struct itree_node *nodes[N] = {&N_10, &N_20, &N_30, &N_40};
- interval_tree_init (&tree);
+ itree_init (&tree);
for (int i = 0; i < N; ++i)
itree_insert (&tree, nodes[i], values[i], values[i]);
@@ -722,8 +721,8 @@ START_TEST (test_remove_10)
srand (42);
shuffle (index, N);
- interval_tree_init (&tree);
- struct itree_node nodes[N];
+ itree_init (&tree);
+ struct itree_node nodes[N] = {0};
for (int i = 0; i < N; ++i)
{
ptrdiff_t pos = (i + 1) * 10;
@@ -733,10 +732,10 @@ START_TEST (test_remove_10)
shuffle (index, N);
for (int i = 0; i < N; ++i)
{
- ck_assert (interval_tree_contains (&tree, &nodes[index[i]]));
+ ck_assert (itree_contains (&tree, &nodes[index[i]]));
itree_remove (&tree, &nodes[index[i]]);
}
- ck_assert_ptr_null (tree.root);
+ ck_assert (itree_empty_p (&tree));
ck_assert_int_eq (tree.size, 0);
}
END_TEST
@@ -748,12 +747,12 @@ END_TEST
START_TEST (test_generator_1)
{
- struct itree_node node, *n;
- struct itree_iterator *g;
- interval_tree_init (&tree);
+ struct itree_node node = {0}, *n;
+ struct itree_iterator it, *g;
+ itree_init (&tree);
itree_insert (&tree, &node, 10, 20);
- g = itree_iterator_start (&tree, 0, 30, ITREE_ASCENDING, NULL, 0);
+ g = itree_iterator_start (&it, &tree, 0, 30, ITREE_ASCENDING);
n = itree_iterator_next (g);
ck_assert_ptr_eq (n, &node);
ck_assert_int_eq (n->begin, 10);
@@ -761,13 +760,11 @@ START_TEST (test_generator_1)
ck_assert_ptr_null (itree_iterator_next (g));
ck_assert_ptr_null (itree_iterator_next (g));
ck_assert_ptr_null (itree_iterator_next (g));
- itree_iterator_finish (g);
- g = itree_iterator_start (&tree, 30, 50, ITREE_ASCENDING, NULL, 0);
+ g = itree_iterator_start (&it, &tree, 30, 50, ITREE_ASCENDING);
ck_assert_ptr_null (itree_iterator_next (g));
ck_assert_ptr_null (itree_iterator_next (g));
ck_assert_ptr_null (itree_iterator_next (g));
- itree_iterator_finish (g);
}
END_TEST
@@ -777,8 +774,8 @@ test_check_generator (struct itree_tree *tree,
int n, ...)
{
va_list ap;
- struct itree_iterator *g =
- itree_iterator_start (tree, begin, end, ITREE_ASCENDING, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, tree, begin, end, ITREE_ASCENDING);
va_start (ap, n);
for (int i = 0; i < n; ++i)
@@ -790,13 +787,12 @@ test_check_generator (struct itree_tree *tree,
va_end (ap);
ck_assert_ptr_null (itree_iterator_next (g));
ck_assert_ptr_null (itree_iterator_next (g));
- itree_iterator_finish (g);
}
START_TEST (test_generator_2)
{
- interval_tree_init (&tree);
- struct itree_node nodes[3];
+ itree_init (&tree);
+ struct itree_node nodes[3] = {0};
for (int i = 0; i < 3; ++i)
itree_insert (&tree, &nodes[i], 10 * (i + 1), 10 * (i + 2));
@@ -830,7 +826,7 @@ test_create_tree (struct itree_node *nodes, int n, bool doshuffle)
shuffle (index, n);
}
- interval_tree_init (&tree);
+ itree_init (&tree);
for (int i = 0; i < n; ++i)
{
struct itree_node *node = &nodes[index[i]];
@@ -862,8 +858,8 @@ START_TEST (test_generator_5)
{.begin = 30, .end = 50},
{.begin = 40, .end = 60}};
test_create_tree (nodes, N, false);
- struct itree_iterator *g =
- itree_iterator_start (&tree, 0, 100, ITREE_PRE_ORDER, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, &tree, 0, 100, ITREE_PRE_ORDER);
for (int i = 0; i < N; ++i)
{
struct itree_node *n = itree_iterator_next (g);
@@ -876,7 +872,6 @@ START_TEST (test_generator_5)
case 3: ck_assert_int_eq (40, n->begin); break;
}
}
- itree_iterator_finish (g);
}
END_TEST
@@ -888,8 +883,8 @@ START_TEST (test_generator_6)
{.begin = 30, .end = 50},
{.begin = 40, .end = 60}};
test_create_tree (nodes, N, true);
- struct itree_iterator *g =
- itree_iterator_start (&tree, 0, 100, ITREE_ASCENDING, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, &tree, 0, 100, ITREE_ASCENDING);
for (int i = 0; i < N; ++i)
{
struct itree_node *n = itree_iterator_next (g);
@@ -902,7 +897,6 @@ START_TEST (test_generator_6)
case 3: ck_assert_int_eq (40, n->begin); break;
}
}
- itree_iterator_finish (g);
}
END_TEST
@@ -914,8 +908,8 @@ START_TEST (test_generator_7)
{.begin = 30, .end = 50},
{.begin = 40, .end = 60}};
test_create_tree (nodes, N, true);
- struct itree_iterator *g =
- itree_iterator_start (&tree, 0, 100, ITREE_DESCENDING, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, &tree, 0, 100, ITREE_DESCENDING);
for (int i = 0; i < N; ++i)
{
struct itree_node *n = itree_iterator_next (g);
@@ -928,7 +922,6 @@ START_TEST (test_generator_7)
case 3: ck_assert_int_eq (10, n->begin); break;
}
}
- itree_iterator_finish (g);
}
END_TEST
@@ -938,14 +931,13 @@ START_TEST (test_generator_8)
struct itree_node nodes[N] = {{.begin = 20, .end = 30},
{.begin = 40, .end = 50}};
test_create_tree (nodes, N, false);
- struct itree_iterator *g =
- itree_iterator_start (&tree, 1, 60, ITREE_DESCENDING, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, &tree, 1, 60, ITREE_DESCENDING);
struct itree_node *n = itree_iterator_next (g);
ck_assert_int_eq (n->begin, 40);
itree_iterator_narrow (g, 50, 60);
n = itree_iterator_next (g);
ck_assert_ptr_null (n);
- itree_iterator_finish (g);
}
END_TEST
@@ -955,14 +947,13 @@ START_TEST (test_generator_9)
struct itree_node nodes[N] = {{.begin = 25, .end = 25},
{.begin = 20, .end = 30}};
test_create_tree (nodes, N, false);
- struct itree_iterator *g =
- itree_iterator_start (&tree, 1, 30, ITREE_DESCENDING, NULL, 0);
+ struct itree_iterator it, *g =
+ itree_iterator_start (&it, &tree, 1, 30, ITREE_DESCENDING);
struct itree_node *n = itree_iterator_next (g);
ck_assert_int_eq (n->begin, 25);
itree_iterator_narrow (g, 25, 30);
n = itree_iterator_next (g);
ck_assert_int_eq (n->begin, 20);
- itree_iterator_finish (g);
}
END_TEST
@@ -981,7 +972,7 @@ static void
test_setup_gap_node (ptrdiff_t begin, ptrdiff_t end,
bool front_advance, bool rear_advance)
{
- interval_tree_init (&gap_tree);
+ itree_init (&gap_tree);
gap_node.front_advance = front_advance;
gap_node.rear_advance = rear_advance;
itree_insert (&gap_tree, &gap_node, begin, end);
@@ -1281,9 +1272,8 @@ main (void)
Suite *s = basic_suite ();
SRunner *sr = srunner_create (s);
- init_itree ();
srunner_run_all (sr, CK_ENV);
- int nfailed = srunner_ntests_failed (sr);
+ int failed = srunner_ntests_failed (sr);
srunner_free (sr);
- return (nfailed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+ return failed ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index 7d3d9eb72b8..f0b9dc0fb92 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -830,7 +830,7 @@ Return nil if that can't be determined."
(when (eq process-tests--EMFILE-message :unknown)
(setq process-tests--EMFILE-message
(with-temp-buffer
- (when (eql (ignore-error 'file-error
+ (when (eql (ignore-error file-error
(call-process "errno" nil t nil "EMFILE"))
0)
(goto-char (point-min))
diff --git a/test/src/regex-emacs-tests.el b/test/src/regex-emacs-tests.el
index b323f592dca..977b2f63715 100644
--- a/test/src/regex-emacs-tests.el
+++ b/test/src/regex-emacs-tests.el
@@ -273,7 +273,7 @@ on success"
string
(condition-case nil
(if (string-match pattern string) nil 'search-failed)
- ('invalid-regexp 'compilation-failed))
+ (invalid-regexp 'compilation-failed))
bounds-ref substring-ref)))
@@ -518,7 +518,7 @@ known/benign differences in behavior.")
what-failed
(condition-case nil
(if (string-match pattern string) nil 'search-failed)
- ('invalid-regexp 'compilation-failed))
+ (invalid-regexp 'compilation-failed))
matches-observed
(cl-loop for x from 0 to 20