diff options
111 files changed, 5753 insertions, 4406 deletions
diff --git a/.gitignore b/.gitignore index eb76ff330b8..833e88a3aa7 100644 --- a/.gitignore +++ b/.gitignore @@ -18,14 +18,15 @@ # along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. -# Currently we assume only Git 1.7.1 (April 2010) or later, so this -# file does not rely on "**" in patterns. The "**" feature was added -# in Git 1.8.2 (March 2013). - - -# Personal customization. -.dir-locals-2.el -.no-advice-on-failure +# Ignore all dot-files except for those under version control. +.* +!.clang-format +!.clangd +!.dir-locals.el +!.gitattributes +!.gitignore +!.gitlab-ci.yml +!.mailmap # Built by 'autogen.sh'. /aclocal.m4 @@ -119,8 +120,8 @@ cross/ndk-build/ndk-build.mk cross/ndk-build/*.o # Lisp-level sources built by 'make'. -*cus-load.el -*loaddefs.el +lisp/**/*cus-load.el +lisp/**/*loaddefs.el lisp/cedet/semantic/bovine/c-by.el lisp/cedet/semantic/bovine/make-by.el lisp/cedet/semantic/bovine/scm-by.el @@ -319,7 +320,6 @@ gnustmp* *.orig *.swp *~ -.#* \#*\# ChangeLog [0-9]*.patch @@ -368,17 +368,8 @@ lib-src/seccomp-filter-exec.pfc # Ignore directory made by admin/make-manuals. /manual/ -# Ignore Finder files on MacOS. -.DS_Store - -# Ignore a directory used by dap-mode. -.vscode /test/gmp.h -# GDB history -.gdb_history -_gdb_history - # Files ignored in exec/. exec/aclocal.m4 exec/config.guess @@ -2,7 +2,7 @@ Copyright (C) 2001-2024 Free Software Foundation, Inc. See the end of the file for license conditions. -This directory tree holds version 30.0.60 of GNU Emacs, the extensible, +This directory tree holds version 31.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/coccinelle/process.cocci b/admin/coccinelle/process.cocci deleted file mode 100644 index bf295ab7b6f..00000000000 --- a/admin/coccinelle/process.cocci +++ /dev/null @@ -1,110 +0,0 @@ -// Change direct access to Lisp_Object fields of struct Lisp_Process to PVAR. -@@ -struct Lisp_Process *P; -Lisp_Object O; -@@ -( -- P->tty_name -+ PVAR (P, tty_name) -| -- P->name -+ PVAR (P, name) -| -- P->command -+ PVAR (P, command) -| -- P->filter -+ PVAR (P, filter) -| -- P->sentinel -+ PVAR (P, sentinel) -| -- P->log -+ PVAR (P, log) -| -- P->buffer -+ PVAR (P, buffer) -| -- P->childp -+ PVAR (P, childp) -| -- P->plist -+ PVAR (P, plist) -| -- P->type -+ PVAR (P, type) -| -- P->mark -+ PVAR (P, mark) -| -- P->status -+ PVAR (P, status) -| -- P->decode_coding_system -+ PVAR (P, decode_coding_system) -| -- P->decoding_buf -+ PVAR (P, decoding_buf) -| -- P->encode_coding_system -+ PVAR (P, encode_coding_system) -| -- P->encoding_buf -+ PVAR (P, encoding_buf) -| -- P->write_queue -+ PVAR (P, write_queue) - -| - -- XPROCESS (O)->tty_name -+ PVAR (XPROCESS (O), tty_name) -| -- XPROCESS (O)->name -+ PVAR (XPROCESS (O), name) -| -- XPROCESS (O)->command -+ PVAR (XPROCESS (O), command) -| -- XPROCESS (O)->filter -+ PVAR (XPROCESS (O), filter) -| -- XPROCESS (O)->sentinel -+ PVAR (XPROCESS (O), sentinel) -| -- XPROCESS (O)->log -+ PVAR (XPROCESS (O), log) -| -- XPROCESS (O)->buffer -+ PVAR (XPROCESS (O), buffer) -| -- XPROCESS (O)->childp -+ PVAR (XPROCESS (O), childp) -| -- XPROCESS (O)->plist -+ PVAR (XPROCESS (O), plist) -| -- XPROCESS (O)->type -+ PVAR (XPROCESS (O), type) -| -- XPROCESS (O)->mark -+ PVAR (XPROCESS (O), mark) -| -- XPROCESS (O)->status -+ PVAR (XPROCESS (O), status) -| -- XPROCESS (O)->decode_coding_system -+ PVAR (XPROCESS (O), decode_coding_system) -| -- XPROCESS (O)->decoding_buf -+ PVAR (XPROCESS (O), decoding_buf) -| -- XPROCESS (O)->encode_coding_system -+ PVAR (XPROCESS (O), encode_coding_system) -| -- XPROCESS (O)->encoding_buf -+ PVAR (XPROCESS (O), encoding_buf) -| -- XPROCESS (O)->write_queue -+ PVAR (XPROCESS (O), write_queue) -) diff --git a/build-aux/gitlog-to-changelog b/build-aux/gitlog-to-changelog index 16a9405a7cb..49e7ef95cef 100755 --- a/build-aux/gitlog-to-changelog +++ b/build-aux/gitlog-to-changelog @@ -495,7 +495,7 @@ sub git_dir_option($) # Complain about any unused entry in the --amend=F specified file. my $fail = 0; - foreach my $sha (keys %$amend_code) + foreach my $sha (sort keys %$amend_code) { warn "$ME:$amend_file: unused entry: $sha\n"; $fail = 1; diff --git a/build-aux/install-sh b/build-aux/install-sh index 7c56c9c0151..b1d7a6f67f6 100755 --- a/build-aux/install-sh +++ b/build-aux/install-sh @@ -1,7 +1,7 @@ #!/bin/sh # install - install a program, script, or datafile -scriptversion=2023-11-23.18; # UTC +scriptversion=2024-06-19.01; # UTC # This originates from X11R5 (mit/util/scripts/install.sh), which was # later released in X11R6 (xc/config/util/install.sh) with the @@ -170,7 +170,7 @@ while test $# -ne 0; do -T) is_target_a_directory=never;; - --version) echo "$0 $scriptversion"; exit $?;; + --version) echo "$0 (GNU Automake) $scriptversion"; exit $?;; --) shift break;; @@ -345,7 +345,7 @@ do ' 0 # Because "mkdir -p" follows existing symlinks and we likely work - # directly in world-writeable /tmp, make sure that the '$tmpdir' + # directly in world-writable /tmp, make sure that the '$tmpdir' # directory is successfully created first before we actually test # 'mkdir -p'. if (umask $mkdir_umask && @@ -353,7 +353,7 @@ do exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1 then if test -z "$dir_arg" || { - # Check for POSIX incompatibilities with -m. + # Check for POSIX incompatibility with -m. # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or # other-writable bit of parent directory when it shouldn't. # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. diff --git a/build-aux/ndk-build-helper-1.mk b/build-aux/ndk-build-helper-1.mk index 985f7cddfaf..4420eb433f4 100644 --- a/build-aux/ndk-build-helper-1.mk +++ b/build-aux/ndk-build-helper-1.mk @@ -35,7 +35,7 @@ NDK_CXX_FLAG_$(LOCAL_MODULE) := $(info Building $(build_kind)) $(info $(LOCAL_MODULE)) -$(info $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI)))) +$(info $(addprefix $(LOCAL_PATH:%/=%)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI)))) ifeq ($(filter-out lib%,$(LOCAL_MODULE)),) NDK_SO_NAMES = $(LOCAL_MODULE)_emacs.so @@ -106,7 +106,7 @@ endif $(info $(foreach dir,$(NDK_INCLUDES),-I$(dir))) $(info $(LOCAL_EXPORT_CFLAGS)) -$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname))) +$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR:%/=%)/,$(NDK_A_NAMES))) -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname))) $(info $(NDK_SO_NAMES)) $(info $(NDK_CXX_FLAG_$(LOCAL_MODULE))) $(info End) diff --git a/build-aux/ndk-build-helper-2.mk b/build-aux/ndk-build-helper-2.mk index 697740b3d45..b8d22f5952d 100644 --- a/build-aux/ndk-build-helper-2.mk +++ b/build-aux/ndk-build-helper-2.mk @@ -29,7 +29,7 @@ NDK_CXX_FLAG_$(LOCAL_MODULE) := $(info Building $(build_kind)) $(info $(LOCAL_MODULE)) -$(info $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI)))) +$(info $(addprefix $(LOCAL_PATH:%/=%)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI)))) ifeq ($(filter-out lib%,$(LOCAL_MODULE)),) NDK_A_NAMES = $(LOCAL_MODULE).a @@ -99,7 +99,7 @@ endif $(info $(foreach dir,$(NDK_INCLUDES),-I$(dir))) $(info $(LOCAL_EXPORT_CFLAGS)) -$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) $(and $(NDK_SO_NAMES), -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname)))) +$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR:%/=%)/,$(NDK_A_NAMES))) $(and $(NDK_SO_NAMES), -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname)))) $(info $(NDK_A_NAMES) $(NDK_SO_NAMES)) $(info $(NDK_CXX_FLAG_$(LOCAL_MODULE))) $(info End) diff --git a/build-aux/ndk-build-helper.mk b/build-aux/ndk-build-helper.mk index 521e1b24ce3..b4746dd623f 100644 --- a/build-aux/ndk-build-helper.mk +++ b/build-aux/ndk-build-helper.mk @@ -42,7 +42,7 @@ EMACS_SRCDIR := $(absname $(EMACS_SRCDIR)) # my-dir is a function that returns the Android module directory. If # no Android.mk has been loaded, use ANDROID_MODULE_DIRECTORY. -my-dir = $(or $(and $(local-makefile),$(dir $(local-makefile))),$(ANDROID_MODULE_DIRECTORY)) +my-dir = $(patsubst %/,%,$(or $(and $(local-makefile),$(dir $(local-makefile))),$(ANDROID_MODULE_DIRECTORY))) # Return all Android.mk files under the first arg. all-makefiles-under = $(wildcard $(1)/*/Android.mk) diff --git a/build-aux/ndk-module-extract.awk b/build-aux/ndk-module-extract.awk index 6ff30973d67..b57bf74001d 100644 --- a/build-aux/ndk-module-extract.awk +++ b/build-aux/ndk-module-extract.awk @@ -55,14 +55,14 @@ /^End$/ { if (name == MODULE && (kind == "shared" || kind == "static")) { - printf "module_name=%s\n", name - printf "module_kind=%s\n", kind - printf "module_src=\"%s\"\n", src - printf "module_includes=\"%s\"\n", includes - printf "module_cflags=\"%s\"\n", cflags - printf "module_ldflags=\"%s\"\n", ldflags - printf "module_target=\"%s\"\n", target - printf "module_cxx_deps=\"%s\"\n", cxx_deps + printf "module_name=%s;", name + printf "module_kind=%s;", kind + printf "module_src=\"%s\";", src + printf "module_includes=\"%s\";", includes + printf "module_cflags=\"%s\";", cflags + printf "module_ldflags=\"%s\";", ldflags + printf "module_target=\"%s\";", target + printf "module_cxx_deps=\"%s\";", cxx_deps } src = "" @@ -83,6 +83,6 @@ imports = "" # Strip off leading whitespace. gsub (/^[ \t]+/, "", makefile_imports) - printf "module_imports=\"%s\"\n", makefile_imports + printf "module_imports=\"%s\";", makefile_imports makefile_imports = "" } diff --git a/configure.ac b/configure.ac index 3ee332521f6..909f5786c9a 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], [30.0.60], [bug-gnu-emacs@gnu.org], [], +AC_INIT([GNU Emacs], [31.0.50], [bug-gnu-emacs@gnu.org], [], [https://www.gnu.org/software/emacs/]) if test "$XCONFIGURE" = "android"; then @@ -197,11 +197,17 @@ AS_IF([test "$XCONFIGURE" = "android"],[ AC_MSG_NOTICE([configuring in `exec']) + # Derive a name for a cache file for this configure script from the + # current, if specified. + exec_cache_file= + AS_CASE([$cache_file], [/dev/null | ""], [], + [[[\\/]* | ?:[\\/]*]], [exec_cache_file="--cache-file=$cache_file.2"], + [*], [exec_cache_file="--cache-file=../$cache_file.2"]) OLDCWD=`pwd` cd exec $CONFIG_SHELL $emacs_srcdir/exec/configure \ --host=$host "CC=$CC" "LD=$CC" "AS=$CC" \ - "AR=$AR" "CFLAGS=$CFLAGS" + "AR=$AR" "CFLAGS=$CFLAGS" $exec_cache_file emacs_val=$? cd $OLDCWD @@ -1263,6 +1269,11 @@ packages targeting Android 2.2.])]) emacs_val="--enable-check-lisp-object-type=$enable_check_lisp_object_type" passthrough="$passthrough $emacs_val" + # And derive a name for the recursive configure invocation's cache + # file if one should be specified for this. + AS_IF([test -n "$cache_file" && test "$cache_file" != "/dev/null"], + [passthrough="$passthrough --cache-file=$cache_file.1"]) + AS_IF([test "x$with_mailutils" = "xyes"], [emacs_use_mailutils=yes]) AC_SUBST([emacs_use_mailutils]) @@ -1600,6 +1611,30 @@ AC_DEFUN([gl_TYPE_OFF64_T], [HAVE_OFF64_T=1 AC_SUBST([HAVE_OFF64_T])]) +# `strnlen' cannot accept nlen greater than the size of the object S +# on Android 2.2 and earlier. +m4_define([ORIGINAL_AC_FUNC_STRNLEN], m4_defn([AC_FUNC_STRNLEN])) +AC_DEFUN([AC_FUNC_STRNLEN], [ +AC_REQUIRE([AC_USE_SYSTEM_EXTENSIONS])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([for strnlen capable of accepting large limits], + [emacs_cv_func_strnlen_working], + [AC_RUN_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT], [[ + volatile size_t (*strnlen_pointer) (const char *s, size_t) = &strnlen; + if ((*strnlen_pointer) ("", -1) != 0) + return 1; + return 0; +]])],[emacs_cv_func_strnlen_working=yes], + [emacs_cv_func_strnlen_working=no], + [# Guess no on Android 21 and earlier, yes elsewhere. + AS_IF([test -n "$ANDROID_SDK" && test "$ANDROID_SDK" -lt 22], + [emacs_cv_func_strnlen_working=no], + [emacs_cv_func_strnlen_working='guessing yes'])])]) +AS_IF([test "$emacs_cv_func_strnlen_working" != "no"], + [ORIGINAL_AC_FUNC_STRNLEN], + [ac_cv_func_strnlen_working=no + AC_LIBOBJ([strnlen])])]) + # Initialize gnulib right after choosing the compiler. dnl Amongst other things, this sets AR and ARFLAGS. gl_EARLY @@ -5059,12 +5094,14 @@ 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]) +AC_SUBST_FILE([module_env_snippet_31]) 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" +module_env_snippet_31="$srcdir/src/module-env-31.h" emacs_major_version=`AS_ECHO([$PACKAGE_VERSION]) | sed 's/[[.]].*//'` AC_SUBST([emacs_major_version]) @@ -5925,7 +5962,7 @@ LIBS="$LIB_PTHREAD $LIB_MATH $LIBS" AC_CHECK_FUNCS([accept4 fchdir gethostname \ getrusage get_current_dir_name \ lrand48 random rint tcdrain trunc \ -select getpagesize setlocale newlocale \ +select getpagesize newlocale \ getrlimit setrlimit shutdown \ pthread_sigmask strsignal setitimer \ sendto recvfrom getsockname getifaddrs freeifaddrs \ diff --git a/cross/ndk-build/Makefile.in b/cross/ndk-build/Makefile.in index 0970a765b45..b5eac9bd089 100644 --- a/cross/ndk-build/Makefile.in +++ b/cross/ndk-build/Makefile.in @@ -79,7 +79,7 @@ local-makefile = $$(NDK_LAST_MAKEFILE) # my-dir is a function that returns the Android module directory. If # no Android.mk has been loaded, use the directory of the Makefile # being included. -my-dir = $$(or $$(and $$(local-makefile),$$(dir $$(local-makefile))),$(dir $(1))) +my-dir = $$(patsubst %/,%,$$(or $$(and $$(local-makefile),$$(dir $$(local-makefile))),$(dir $(1)))) # Return all Android.mk files under the first arg. all-makefiles-under = $$(wildcard $$(1)/*/Android.mk) diff --git a/cross/ndk-build/ndk-resolve.mk b/cross/ndk-build/ndk-resolve.mk index 896c29f7f90..289e3a8a003 100644 --- a/cross/ndk-build/ndk-resolve.mk +++ b/cross/ndk-build/ndk-resolve.mk @@ -50,7 +50,6 @@ ifeq ($$(filter $(1)$(and $(3),whole),$$(NDK_RESOLVED_CFLAGS_$(LOCAL_MODULE))),) # Always mark this module's cflags as having been resolved, even if # this is a whole library. NDK_RESOLVED_CFLAGS_$(LOCAL_MODULE) += $(1) - NDK_CFLAGS_$(LOCAL_MODULE) += $(NDK_LOCAL_EXPORT_CFLAGS_$(1)) NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix -I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1))) endif diff --git a/doc/lispref/commands.texi b/doc/lispref/commands.texi index a9da6c75367..6ddb70a3b9f 100644 --- a/doc/lispref/commands.texi +++ b/doc/lispref/commands.texi @@ -2128,7 +2128,7 @@ motion and mouse motion. However, some commands bound to @code{down-mouse-1}--@code{mouse-drag-region}, for example--either conflict with defined touch screen gestures (such as ``long-press to -drag''), or with user expectations for touch input, and shouldn't +drag''), or with user expectations for touch input, and should not subject the touch sequence to simple translation. If a command whose name contains the property (@pxref{Symbol Properties}) @code{ignored-mouse-command} is encountered or there is no command @@ -2146,13 +2146,20 @@ compromise for packages which assume @code{mouse-drag-region} has already set point to the location of any mouse click and selected the window where it took place. -To prevent unwanted @code{mouse-1} events arriving after a mouse menu -is dismissed (@pxref{Mouse Menus}), Emacs also avoids simple +To prevent unwanted @code{mouse-1} events from arriving after a mouse +menu is dismissed (@pxref{Mouse Menus}), Emacs also disables simple translation if @code{down-mouse-1} is bound to a keymap, making it a prefix key. In lieu of simple translation, it translates the closing -@code{touchscreen-end} to a @code{down-mouse-1} event with the -starting position of the touch sequence, consequently displaying -the mouse menu. +@code{touchscreen-end} to a @code{down-mouse-1} event with the starting +position of the touch sequence, consequently displaying the mouse menu. + +@vindex @code{touch-screen-simple-mouse-conversion} +Simple conversion will be enabled without regard to the existence of +command or menu bindings if the variable +@code{touch-screen-simple-mouse-conversion} is bound or set to a +non-@code{nil} value, as, for example, it may be by a caller of +@code{read-key} expecting to receive @code{mouse-movement} and +@code{drag-mouse-1} events. @cindex @code{mouse-1-menu-command}, a symbol property Since certain commands are also bound to @code{down-mouse-1} for the diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 55885b7438d..6e4b727a2bd 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5214,8 +5214,10 @@ specifications. This convenience function can be used to get a specific display property, no matter whether the @code{display} property is a vector, a list or a simple property. This is like @code{get-text-property} -(@pxref{Examining Properties}), but works on the @code{display} -property only. +(@pxref{Examining Properties}), but works on the @code{display} property +only. For properties with a single value (e.g.@: @code{height}, this +returns the value itself; for properties with a list of values (e.g.@: +@code{slice}), this returns the list of values. @var{position} is the position in the buffer or string to examine, and @var{prop} is the @code{display} property to return. The optional diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index f56888aac3f..73bc2442678 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -2932,9 +2932,8 @@ For instance, to write all these things to @file{~/.emacs.d/aux/}: @lisp -(when (>= emacs-major-version 28) - (setq lock-file-name-transforms - '(("\\`/.*/\\([^/]+\\)\\'" "~/.emacs.d/aux/\\1" t)))) +(setq lock-file-name-transforms + '(("\\`/.*/\\([^/]+\\)\\'" "~/.emacs.d/aux/\\1" t))) (setq auto-save-file-name-transforms '(("\\`/.*/\\([^/]+\\)\\'" "~/.emacs.d/aux/\\1" t))) (setq backup-directory-alist diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index 858e1ba34dc..75138a9963f 100644 --- a/doc/misc/erc.texi +++ b/doc/misc/erc.texi @@ -2,7 +2,7 @@ @c %**start of header @setfilename ../../info/erc.info @settitle ERC Manual -@set ERCVER 5.6.0.30.1 +@set ERCVER 5.6.1 @set ERCDIST as distributed with Emacs @value{EMACSVER} @include docstyle.texi @syncodeindex fn cp diff --git a/doc/misc/eww.texi b/doc/misc/eww.texi index eec6b3c3299..e0c6b7d610b 100644 --- a/doc/misc/eww.texi +++ b/doc/misc/eww.texi @@ -373,6 +373,15 @@ customizing @code{shr-blocked-images}. @code{shr-inhibit-images}. If this variable is @code{nil}, display the ``ALT'' text of images instead. +@vindex shr-sliced-image-height + To make scrolling up/down past images more intuititve, EWW splits +large images into several rows. This way, you can scroll individually +past each slice, instead of jumping past the entire image. EWW slices +images that take up more than @code{shr-sliced-image-height} of the +height of the window they are displayed in. For example, a value of 0.7 +means that images are allowed to take up 70% of the height of the window +before being sliced. + @vindex shr-color-visible-distance-min @vindex shr-color-visible-luminance-min @cindex Contrast @@ -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 30. +This file is about changes in Emacs version 31. See file HISTORY for a list of GNU Emacs versions and release dates. -See files NEWS.29, NEWS.28, ..., NEWS.18, and NEWS.1-17 for changes +See files NEWS.30, NEWS.29, ..., 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,3102 +22,71 @@ 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 30.1 - ---- -** Native compilation is now enabled by default. -'configure' will enable the Emacs Lisp native compiler, so long as -libgccjit is present and functional on the system. To disable native -compilation, configure Emacs with the option: - - ./configure --with-native-compilation=no - -+++ -** Emacs has been ported to the Android operating system. -This requires Emacs to be compiled on another computer. The Android -NDK, SDK, and a suitable Java compiler must also be installed. - -See the file "java/INSTALL" for more details. - ---- -** Native JSON support is now always available; libjansson is no longer used. -No external library is required. The '--with-json' configure option has -been removed. 'json-available-p' now always returns non-nil and is only -kept for compatibility. - ---- -** Emacs now defaults to the ossaudio library for sound on NetBSD and OpenBSD. -Previously, configure used ALSA libraries if installed on the system -when configured '--with-sound=yes' (which is the default), with fallback -to libossaudio. The libossaudio library included with the base system -is now used even if ALSA is found to avoid relying on external packages -and to resolve potential incompatibilities between GNU/Linux and *BSD -versions of ALSA. Use '--with-sound=alsa' to build with ALSA on these -operating systems instead. +* Installation Changes in Emacs 31.1 -* Startup Changes in Emacs 30.1 - ---- -** On GNU/Linux, Emacs is now the default application for 'org-protocol'. -Org mode provides a way to quickly capture bookmarks, notes, and links -using 'emacsclient': - - emacsclient "org-protocol://store-link?url=URL&title=TITLE" - -Previously, users had to manually configure their GNU/Linux desktop -environment to open 'org-protocol' links in Emacs. These links should -now open in Emacs automatically, as the "emacsclient.desktop" file now -arranges for Emacs to be the default application for the 'org-protocol' -URI scheme. See the Org mode manual, Info node "(org) Protocols" for -more details. - -+++ -** New variable lets Lisp code read emacsclient arguments. -When '--eval' is passed to emacsclient and Emacs is evaluating each -argument, the new variable 'server-eval-args-left' is set to those -arguments not yet evaluated. It can be used by Lisp code to 'pop' -arguments and process them by the function called in the '--eval' -expression, which is useful when those arguments contain arbitrary -characters that otherwise might require elaborate and error-prone -escaping (to protect them from the shell). +* Startup Changes in Emacs 31.1 -* Incompatible Changes in Emacs 30.1 - ---- -** Tree-Sitter modes are now declared as submodes of the non-TS modes. -In order to help the use of those Tree-Sitter modes, they are now -declared to have the corresponding non-Tree-Sitter mode as an -additional parent. -This way, things like ".dir-locals.el" settings, and YASnippet -collections of snippets automatically apply to the new Tree-Sitter modes. - -Note that those modes still do not inherit from the non-TS mode, so -configuration settings installed via mode hooks are not affected. - ---- -** Mouse wheel events should now always be 'wheel-up/down/left/right'. -At those places where the old 'mouse-4/5/6/7' events could still occur -(i.e., X11 input in the absence of XInput2, and 'xterm-mouse-mode'), -we remap them to the corresponding 'wheel-up/down/left/right' event, -according to the new user option 'mouse-wheel-buttons'. -The old variables 'mouse-wheel-up-event', 'mouse-wheel-down-event', -'mouse-wheel-left-event', and 'mouse-wheel-right-event' are thereby -obsolete. - -+++ -** 'completion-auto-help' now affects 'icomplete-in-buffer'. -Previously, 'completion-auto-help' mostly affected only minibuffer -completion. Now, if 'completion-auto-help' has the value 'lazy', then -Icomplete's in-buffer display of possible completions will only appear -after the 'completion-at-point' command has been invoked twice, and if -'completion-auto-help' is nil, then Icomplete's in-buffer display is -completely suppressed. Thus, if you use 'icomplete-in-buffer', ensure -'completion-auto-help' is not customized to 'lazy' or nil. - -+++ -** The "*Completions*" buffer now always accompanies 'icomplete-in-buffer'. -Previously, it was not consistent whether the "*Completions*" buffer would -appear when using 'icomplete-in-buffer'. Now the "*Completions*" buffer -and Icomplete's in-buffer display of possible completions always -appear together. If you would prefer to see only Icomplete's -in-buffer display, and not the "*Completions*" buffer, you can add this -to your init file: - - (advice-add 'completion-at-point :after #'minibuffer-hide-completions) - ---- -** The default process filter was rewritten in native code. -The round-trip through the Lisp function -'internal-default-process-filter' is skipped when the process filter is -the default one. It is reimplemented in native code, reducing GC churn. -To undo this change, set 'fast-read-process-output' to nil. - -+++ -** The Network Security Manager now warns about 3DES by default. -This cypher is no longer recommended owing to a major vulnerability -disclosed in 2016, and its small 112 bit key size. Emacs now warns -about its use also when 'network-security-level' is set to 'medium' -(the default). See 'network-security-protocol-checks'. - ---- -** The Network Security Manager now warns about <2048 bits in DH key exchange. -Emacs used to warn for Diffie-Hellman key exchanges with prime numbers -smaller than 1024 bits. Since more servers now support it, this -number has been bumped to 2048 bits. - -+++ -** URL now never sends user email addresses in HTTP requests. -Emacs never sent email addresses by default, but it used to be -possible to customize 'url-privacy-level' so that the users email -address was sent along in HTTP requests. This feature has now been -removed, as it was considered more dangerous than useful. RFC 9110 -(§ 10.1.2) also recommends against it. The user option -'url-personal-mail-address' is now also obsolete. - -To send an email address in the header of individual HTTP requests, -see the variable 'url-request-extra-headers'. +* Changes in Emacs 31.1 -* Changes in Emacs 30.1 - ---- -** Emacs now supports Unicode Standard version 15.1. - -+++ -** Emacs now comes with Org v9.7. -See the file "etc/ORG-NEWS" for user-visible changes in Org. - -+++ -** Improved support for touchscreen devices. -On systems that understand them (at present X, Android, PGTK, and -MS-Windows), many touch screen gestures are now implemented and -translated into mouse or gesture events, and support for tapping tool -bar buttons and opening menus has been added. Countless packages, such -as Dired and Custom, have been adjusted to better understand touch -screen input. - -+++ -** Support for styled underline face attributes. -These are implemented as new values of the 'style' attribute in a face -underline specification, 'double-line', 'dots', and 'dashes', and are -available on GUI systems. If your terminal's termcap or terminfo -database entry defines the 'Su' or 'Smulx' capability, Emacs will also -emit the prescribed escape sequence to render faces with such styles on -TTY frames. - ---- -** Support for underline colors on TTY frames. -Colors specified in the underline face will now also be displayed on TTY -frames on terminals that support the 'Su' or 'Smulx' capabilities. - -+++ -** Modeline elements can now be right-aligned. -Anything following the symbol 'mode-line-format-right-align' in -'mode-line-format' will be right-aligned. Exactly where it is -right-aligned to is controlled by the new user option -'mode-line-right-align-edge'. - ---- -** 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. - ---- -** 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-p' returns nil or 'icon' for it. This can happen, for -example, as part of preview for iconified frames. - -+++ -** Most file notification backends detect unmounting of a watched filesystem. -The only exception is w32notify. - -+++ -** The ':map' property of images is now recomputed when image is transformed. -Images with clickable maps now work as expected after you run commands -such as 'image-increase-size', 'image-decrease-size', 'image-rotate', -'image-flip-horizontally', and 'image-flip-vertically'. -Set the new user option 'image-recompute-map-p' to nil to prevent Emacs -from recomputing image maps. - -** Minibuffer and Completions - -+++ -*** New commands 'previous-line-completion' and 'next-line-completion'. -Bound to '<up>' and '<down>' arrow keys, respectively, they navigate -the "*Completions*" buffer vertically by lines, wrapping at the -top/bottom when 'completion-auto-wrap' is non-nil. - -+++ -*** New user option 'minibuffer-visible-completions'. -When customized to non-nil, you can use arrow keys in the minibuffer -to navigate the completions displayed in the "*Completions*" window. -Typing 'RET' selects the highlighted candidate. 'C-g' hides the -completions window. When the completions window is not visible, -then all these keys have their usual meaning in the minibuffer. -This option is supported for in-buffer completion as well. - ---- -*** Selected completion candidates are deselected on typing. -When you type at the minibuffer prompt, the current completion -candidate will be un-highlighted, and point in the "*Completions*" window -will be moved off that candidate. 'minibuffer-choose-completion' -('M-RET') will still choose a previously-selected completion -candidate, but the new command 'minibuffer-choose-completion-or-exit' -(bound to 'RET' by 'minibuffer-visible-completions') will exit with -the minibuffer contents instead. This deselection behavior can be -controlled with the new user option 'completion-auto-deselect', which -is t by default. - -+++ -*** New value 'historical' for user option 'completions-sort'. -When 'completions-sort' is set to 'historical', completion candidates -will be first sorted alphabetically, and then re-sorted by their order -in the minibuffer history, with more recent candidates appearing first. - -+++ -*** 'completion-category-overrides' supports more metadata. -The new supported completion properties are 'cycle-sort-function', -'display-sort-function', 'annotation-function', 'affixation-function', -and 'group-function'. You can now customize them for any category in -'completion-category-overrides' that will override the properties -defined in completion metadata. - -+++ -*** 'completion-extra-properties' supports more metadata. -The new supported completion properties are 'category', -'group-function', 'display-sort-function', and 'cycle-sort-function'. - -** Windows - -+++ -*** New command 'toggle-window-dedicated'. -This makes it easy to interactively mark a specific window as -dedicated, so it won't be reused by 'display-buffer'. This can be -useful for complicated window setups. It is bound to 'C-x w d' -globally. - -+++ -*** "d" in the mode line now indicates that the window is dedicated. -Windows have always been able to be dedicated to a specific buffer; -see 'window-dedicated-p'. Now the mode line indicates the dedicated -status of a window, with "d" appearing in the mode line if a window is -dedicated and "D" if the window is strongly dedicated. This indicator -appears before the buffer name, and after the buffer modification and -remote buffer indicators (usually "---" together). - -+++ -*** New action alist entry 'some-window' for 'display-buffer'. -It specifies which window 'display-buffer-use-some-window' should prefer. -For example, when 'display-buffer-base-action' is customized to -'(nil . ((some-window . mru)))', then a buffer will be displayed -in the same most recently used window from consecutive calls of -'display-buffer' (in a configuration with more than two windows). - -+++ -*** New action alist entry 'category' for 'display-buffer'. -If the caller of 'display-buffer' passes '(category . symbol)' -in its 'action' argument, you can match the displayed buffer -by adding '(category . symbol)' to the condition part of -'display-buffer-alist' entries. - -+++ -*** New action alist entry 'post-command-select-window' for 'display-buffer'. -It specifies whether the window of the displayed buffer should be -selected or deselected at the end of executing the current command. - -+++ -*** New variable 'window-restore-killed-buffer-windows'. -It specifies how 'set-window-configuration' and 'window-state-put' -should proceed with windows whose buffer was killed after the -corresponding configuration or state was recorded. - ---- -*** New variable 'window-point-context-set-function'. -It can be used to set a context for window point in all windows by -'window-point-context-set' before calling 'current-window-configuration' -and 'window-state-get'. Then later another new variable -'window-point-context-use-function' can be used by -'window-point-context-use' after 'set-window-configuration' and -'window-state-put' to restore positions of window points -according to the context stored in a window parameter. - -+++ -*** New functions 'set-window-cursor-type' and 'window-cursor-type'. -'set-window-cursor-type' sets a per-window cursor type, and -'window-cursor-type' queries this setting for a given window. Windows -are always created with a 'window-cursor-type' of t, which means to -consult the variable 'cursor-type' as before. - ---- -*** The user option 'display-comint-buffer-action' is now obsolete. -You can use a '(category . comint)' condition in 'display-buffer-alist' -to match buffers displayed by comint-related commands. Another -user option 'display-tex-shell-buffer-action' is obsolete too -for which you can use '(category . tex-shell)'. - -** Tool bars - -+++ -*** Tool bars can now be placed on the bottom on more systems. -The 'tool-bar-position' frame parameter can be set to 'bottom' on all -window systems other than macOS and GNUstep (Nextstep). - -+++ -*** New global minor mode 'modifier-bar-mode'. -When this minor mode is enabled, the tool bar displays buttons -representing modifier keys. Clicking on these buttons applies the -corresponding modifiers to the next input event. - -+++ -*** New user option 'tool-bar-always-show-default'. -When non-nil, the tool bar at the top of a frame does not show buffer -local customization of the tool bar. The default value is nil. - -** Tab Bars and Tab Lines - ---- -*** New user option 'tab-bar-select-restore-context'. -It uses 'window-point-context-set' to save contexts where -window points were located before switching away from the tab, -and 'window-point-context-use' to restore positions of window -points after switching back to that tab. - ---- -*** New user option 'tab-bar-select-restore-windows'. -It defines what to do with windows whose buffer was killed since the tab -was last selected. By default it displays a placeholder buffer -with the name " *Old buffer <name>*" that provides information about -the name of the killed buffer that was displayed in that window. - ---- -*** New user option 'tab-bar-tab-name-format-functions'. -It can be used to add, remove and reorder functions that change the -appearance of every tab on the tab bar. - ---- -*** New user option 'tab-line-tabs-buffer-group-function'. -It provides two choices to group tab buffers by major mode and by -project name. - ---- -*** New hook 'tab-bar-tab-post-select-functions'. - ---- -*** New keymap 'tab-bar-mode-map'. -By default it contains a keybinding 'C-TAB' to switch tabs, but only -when 'C-TAB' is not bound globally. You can unbind it if it conflicts -with 'C-TAB' in other modes. - ---- -*** New keymap 'tab-line-mode-map'. -By default it contains keybindings for switching tabs: 'C-x <left>', -'C-x <right>', 'C-x C-<left>', 'C-x C-<right>'. You can unbind them if -you want to use these keys for the commands 'previous-buffer' and -'next-buffer'. - ---- -*** Default list of tabs is changed to support a fixed order. -This means that 'tab-line-tabs-fixed-window-buffers', the new default -tabs function, is like the previous 'tab-line-tabs-window-buffers' where -both of them show only buffers that were previously displayed in the -window. But the difference is that the new function always keeps the -original order of buffers on the tab line, even after switching between -these buffers. You can drag the tabs and release at a new position -to manually reorder the buffers on the tab line. - ---- -*** Buffers on group tabs are now sorted alphabetically. -This will keep the fixed order of tabs, even after switching between -them. - -** Help - -+++ -*** New command 'help-find-source'. -Switch to a buffer visiting the source of what is being described in -"*Help*". It is bound to 'C-h 4 s' globally. - ---- -*** New user option 'describe-bindings-outline-rules'. -This user option controls outline visibility in the output buffer of -'describe-bindings' when 'describe-bindings-outline' is non-nil. - ---- -*** 'describe-function' shows the function inferred type when available. -For native compiled Lisp functions, 'describe-function' prints (after -the signature) the automatically inferred function type as well. - ---- -*** 'describe-function' now shows the type of the function object. -The text used to say things like "car is a built-in function" whereas it -now says "car is a primitive-function" where "primitive-function" is the -the name of the symbol returned by 'cl-type-of'. You can click on those -words to get information about that type. - ---- -*** 'C-h m' ('describe-mode') uses outlining by default. -Set 'describe-mode-outline' to nil to get back the old behavior. - ---- -*** 'C-h k' ('describe-key') shows Unicode name. -For keybindings which produce single characters via translation or input -methods, 'C-h k' now shows the Unicode name of the produced character in -addition to the character itself, e.g. - -'C-h k C-x 8 E' => - - € 'EURO SIGN' (translated from C-x 8 E) - ---- -*** 'C-h b' ('describe-bindings') shows Unicode names. -For keybindings which produce single characters via translation (such as -those using the 'C-x 8' or 'A-' prefix, or 'dead-acute', 'dead-grave', -etc), the Unicode names will now be shown in addition to the character -itself, i.e. - - A-! ¡ INVERTED EXCLAMATION MARK - A-$ ¤ CURRENCY SIGN - -and so on. - -+++ -*** Multi-character key echo now ends with a suggestion to use Help. -Customize 'echo-keystrokes-help' to nil to prevent that. - -** Customize - -+++ -*** New command 'customize-dirlocals'. -This command pops up a buffer to edit the settings in ".dir-locals.el". - ---- -*** New command 'customize-toggle-option'. -This command can toggle boolean options for the duration of a session. - -+++ -*** New prefix argument for modifying directory-local variables. -The commands 'add-dir-local-variable', 'delete-dir-local-variable' and -'copy-file-locals-to-dir-locals' now take an optional prefix argument, -to enter the file name where you want to modify directory-local -variables. - -+++ -*** New user option 'safe-local-variable-directories'. -This user option names directories in which Emacs will treat all -directory-local variables as safe. - -+++ -** CL Print - -+++ -*** There is a new chapter in the CL manual documenting cl-print.el. -See the Info node "(cl) Printing". - -+++ -*** You can expand the "..." truncation everywhere. -The code that allowed "..." to be expanded in the "*Backtrace*" buffer -should now work anywhere the data is generated by 'cl-print'. - -+++ -*** The 'backtrace-ellipsis' button is replaced by 'cl-print-ellipsis'. - -+++ -*** hash-tables' contents can be expanded via the ellipsis. - -+++ -*** Modes can control the expansion via 'cl-print-expand-ellipsis-function'. - -+++ -*** New setting 'raw' for 'cl-print-compiled'. -This setting causes byte-compiled functions to be printed in full by -'prin1'. A button on this output can be activated to disassemble the -function. - -** Miscellaneous - -+++ -*** New command 'kill-matching-buffers-no-ask'. -This works like 'kill-matching-buffers', but without asking for -confirmation. - -+++ -*** 'recover-file' can show diffs between auto save file and current file. -When answering the prompt with "diff" or "=", it now shows the diffs -between the auto save file and the current file. - -+++ -*** 'read-passwd' can toggle the visibility of passwords. -Use 'TAB' in the minibuffer to show or hide the password. -Alternatively, click the new show-password icon on the mode-line with -'mouse-1' to toggle the visibility of the password. - -*** 'advice-remove' is now an interactive command. -When called interactively, 'advice-remove' now prompts for an advised -function to the advice to remove. - ---- -*** New user option 'uniquify-dirname-transform'. -This can be used to customize how buffer names are uniquified, by -making arbitrary transforms on the buffer's directory name (whose -components are used to uniquify buffer names when they clash). You -can use this to distinguish between buffers visiting files with the -same base name that belong to different projects by using the provided -transform function 'project-uniquify-dirname-transform'. - -+++ -*** New user option 'remote-file-name-inhibit-delete-by-moving-to-trash'. -When non-nil, this option suppresses moving remote files to the local -trash when deleting. Default is nil. - ---- -*** New user option 'remote-file-name-inhibit-auto-save'. -If this user option is non-nil, 'auto-save-mode' will not auto-save -remote buffers. The default is nil. - -+++ -*** New user option 'remote-file-name-access-timeout'. -If a positive number, this option limits the call of 'access-file' -for remote files to that number of seconds. Default is nil. - -+++ -*** New user option 'yes-or-no-prompt'. -This allows the user to customize the prompt that is appended by -'yes-or-no-p' when asking questions. The default value is -"(yes or no) ". - ---- -*** New user option 'menu-bar-close-window'. -When non-nil, selecting "Close" from the "File" menu or clicking -"Close" in the tool bar will result in the current window being -deleted, if possible. The default is nil, and these gestures kill the -buffer shown in the current window, but don't delete the window. - ---- -*** New face 'display-time-date-and-time'. -This is used for displaying the time and date components of -'display-time-mode'. - ---- -*** New face 'appt-notification' for 'appt-display-mode-line'. -It can be used to customize the look of the appointment notification -displayed on the mode line when 'appt-display-mode-line' is non-nil. - ---- -*** New icon images for general use. -Several symbolic icons have been added to "etc/images/symbols", -including plus, minus, check-mark, star, etc. - ---- -*** Emacs now recognizes shebang lines that pass '-S'/'--split-string' to 'env'. -When visiting a script that invokes 'env -S INTERPRETER ARGS...' in -its shebang line, Emacs will now skip over 'env -S' and deduce the -major mode based on the interpreter after 'env -S'. - -*** 'insert-directory-program' is now a user option. -On *BSD and macOS systems, this user option now defaults to the "gls" -executable, if it exists. This should remove the need to change its -value when installing GNU coreutils using something like ports or -Homebrew. - -+++ -*** 'write-region-inhibit-fsync' now defaults to t in interactive mode. -This is the default in batch mode since Emacs 24. - ---- -*** The default value of 'read-process-output-max' was increased to 65536. - -+++ -*** 'url-gateway-broken-resolution' is now obsolete. -This option was intended for use on SunOS 4.x and Ultrix systems, -neither of which have been supported by Emacs since version 23.1. -The user option 'url-gateway-nslookup-program' and the command -'url-gateway-nslookup-host' are consequently also obsolete. +* Editing Changes in Emacs 31.1 -* Editing Changes in Emacs 30.1 - -+++ -** New minor mode 'visual-wrap-prefix-mode'. -When enabled, continuation lines displayed for a wrapped long line -will receive a 'wrap-prefix' automatically computed from the line's -surrounding context, such that continuation lines are indented on -display as if they were filled with 'M-q' or similar. Unlike 'M-q', -the indentation only happens on display, and doesn't change the buffer -text in any way. The global minor mode -'global-visual-wrap-prefix-mode' enables this minor mode in all -buffers. - -(This minor mode is the 'adaptive-wrap' ELPA package renamed and -lightly edited for inclusion in Emacs.) - -+++ -** New global minor mode 'kill-ring-deindent-mode'. -When enabled, text being saved to the kill ring will be de-indented by -the column number at its start. For example, saving the entire -function call within an indented block: - -foo () -{ - long_function_with_several_arguments (argument_1_compute (), - argument_2_compute (), - argument_3_compute ()); -} - -will save this to the kill ring: - -long_function_with_several_arguments (argument_1_compute (), - argument_2_compute (), - argument_3_compute ()) - -This omits the two columns of extra indentation that would otherwise be -copied from the second and third lines and saved to the kill ring. - ---- -** New command 'replace-regexp-as-diff'. -It reads a regexp to search for and a string to replace with, then -displays a buffer with replacements as diffs. After reviewing the -changes in the output buffer you can apply the replacements as -a patch to the current file buffer. There are also new commands -'multi-file-replace-regexp-as-diff' that shows as diffs replacements -in a list of specified files, and 'dired-do-replace-regexp-as-diff' -that shows as diffs replacements in the marked files in Dired. - -+++ -** New mode of prompting for register names and showing preview. -The new user option 'register-use-preview' can be customized to the -value t or insist to request a different user interface of prompting for -register names and previewing the registers: Emacs will require -confirmation for overwriting the value of a register, and will show -the preview of registers without delay. You can also customize this -new option to disable the preview completely. - -The default value of 'register-use-preview' preserves the behavior of -Emacs 29 and before. See the Info node "(emacs) Registers" for more -details about the new UI and its variants. - -+++ -** New advanced macro counter commands. -New commands have been added to implement advanced macro counter -functions. - -The commands 'C-x C-k C-r l' and 'C-x C-k C-r s' load and save the -macro counter from and to a number register, respectively. - -The commands 'C-x C-k C-r a =', 'C-x C-k C-r a <', and 'C-x C-k C-r a >' -compare the macro counter with the contents of a number register and -increment the counter by an optional prefix if the comparison succeeds. - -The commands 'C-x C-k C-q =', 'C-x C-k C-q <', and 'C-x C-k C-q >' -compare the macro counter with an optional prefix and terminate the -macro if the comparison succeeds. - -+++ -** New mode 'kmacro-menu-mode' and new command 'list-keyboard-macros'. -The new command 'list-keyboard-macros' is the keyboard-macro version -of commands like 'list-buffers' and 'list-processes', creating a listing -of the currently existing keyboards macros using the new mode -'kmacro-menu-mode'. It allows rearranging the macros in the ring, -duplicating them, deleting them, and editing their counters, formats, -and keys. - ---- -** On X, Emacs now supports input methods which perform "string conversion". -This means an input method can now ask Emacs to delete text -surrounding point and replace it with something else, as well as query -Emacs for surrounding text. If your input method allows you to "undo" -mistaken compositions, this will now work as well. - ---- -** New user option 'duplicate-region-final-position'. -It controls the placement of point and the region after duplicating a -region with 'duplicate-dwim'. - -+++ -** New user option 'mouse-prefer-closest-glyph'. -When enabled, clicking or dragging with the mouse will put the point -or start the drag in front of the buffer position corresponding to the -glyph with the closest X coordinate to the click or start of the drag. -In other words, if the mouse pointer is in the right half of a glyph, -point will be put after the buffer position corresponding to that glyph, -whereas if the mouse pointer is in the left half of a glyph, point -will be put in front the buffer position corresponding to that glyph. -By default this is disabled. - ---- -** New pre-defined values for 'electric-quote-chars'. -The available customization options for 'electric-quote-chars' have been -updated with common pairs of quotation characters, including "‘", "’", -"“", "”", "«", "»", "‹", "›", "‚", "„", "「", "」", "『", and "』". -The default is unchanged. - -+++ -** 'M-TAB' now invokes 'completion-at-point' in Text mode. -By default, Text mode no longer binds 'M-TAB' to 'ispell-complete-word'. -Instead, this mode arranges for 'completion-at-point', globally bound to -'M-TAB', to perform word completion as well. You can have Text mode -binding 'M-TAB' to 'ispell-complete-word' as it did in previous Emacs -versions, or disable Ispell word completion in Text mode altogether, by -customizing the new user option 'text-mode-ispell-word-completion'. - -** Internationalization - ---- -*** Mode-line mnemonics for some coding-systems have changed. -The mode-line mnemonic for 'utf-7' is now the lowercase 'u', to be -consistent with the other encodings of this family. - -The mode-line mnemonic for 'koi8-u' is now 'У', U+0423 CYRILLIC -CAPITAL LETTER U, to distinguish between this encoding and the -UTF-8/UTF-16 family. - -If your terminal cannot display 'У', or if you want to get the old -behavior back for any other reason, you can do that using the -'coding-system-put' function. For example, the following restores the -previous behavior of showing 'U' in the mode line for 'koi8-u': - - (coding-system-put 'koi8-u :mnemonic ?U) - ---- -*** 'vietnamese-tcvn' is now a coding system alias for 'vietnamese-vscii'. -VSCII-1 and TCVN-5712 are different names for the same character -encoding. Therefore, the duplicate coding system definition has been -dropped in favor of an alias. - -The mode-line mnemonic for 'vietnamese-vscii' and its aliases is the -lowercase letter "v". - ---- -*** Users in CJK locales can control width of some non-CJK characters. -Some characters are considered by Unicode as "ambiguous" with respect -to their display width: either "full-width" (i.e., taking 2 columns on -display) or "narrow" (taking 1 column). The actual width depends on -the fonts used for these characters by Emacs or (for text-mode frames) -by the terminal emulator. Traditionally, font sets in CJK locales -were set up so as to display these characters as full-width, and thus -Emacs modified the char-width table in those locales to follow suit. -Lately, the tendency is to display these characters as narrow. The -new user option 'cjk-ambiguous-chars-are-wide' allows users to control -whether Emacs considers these characters as full-width (the default) -or narrow (if the variable is customized to the nil value). - -This setting affects the results of 'string-width' and similar -functions in CJK locales. - ---- -*** New input methods for the Urdu, Pashto, and Sindhi languages. -These languages are spoken in Pakistan and Afghanistan. - ---- -*** New input method "english-colemak". -This input method supports the Colemak keyboard layout. - ---- -*** Additional 'C-x 8' key translations for "æ" and "Æ". -These characters can now be input with 'C-x 8 a e' and 'C-x 8 A E', -respectively, in addition to the existing translations 'C-x 8 / e' and -'C-x 8 / E'. - ---- -*** New 'C-x 8' key translations for "low" quotes "„", and "‚". -These can now be entered with 'C-x , "' and 'C-x , ''. - ---- -*** New German language 'C-x 8' key translations for quotation marks. -The characters "„", "“", and "”" can now be entered with 'C-x 8 v', -'C-x 8 b' and 'C-x 8 n'. The single versions "‚", "‘", and "’" can now -be entered with 'C-x 8 V', 'C-x 8 B' and 'C-x 8 N'. These characters -are used for the official German quoting style. Using them requires -activating German language support via 'iso-transl-set-language'. - ---- -*** "latin-prefix" and "latin-postfix" quotation marks additions. -These input methods can now produce single, double and "low" left and -right quotation marks: - - "‘", "’", "“", "”", "„", and "‚" +* Changes in Specialized Modes and Packages in Emacs 31.1 -by using "[", "]", and "," for "left", "right", and "low" respectively -to modify "'" and """. +** Whitespace --- -*** "latin-prefix" and "latin-postfix" guillemets support. -These input methods can now produce single guillemets "‹" and "›". For -"latin-prefix" use "~~<" and "~~>", for "latin-postfix" use "<~" and -">~". Double guillemets ("«" and "»") were already supported. - ---- -*** New French language 'C-x 8' key translations for "‹" and "›". -These characters can now be entered using 'C-x 8 ~ <' and 'C-x 8 ~ >', -respectively, after activating French language support via -'iso-transl-set-language'. Double guillemets were already supported via -'C-x 8 <' and 'C-x 8 >' - ---- -*** Additional 'C-x 8' key translation for Euro "€" currency symbol. -This can now be entered using 'C-x 8 E' in addition to the existing -'C-x 8 * E' translation. - - -* Changes in Specialized Modes and Packages in Emacs 30.1 - -** Outline mode - -+++ -*** New commands to show/hide outlines by regexp. -'C-c / h' ('outline-hide-by-heading-regexp') asks for a regexp and then -hides the body lines of all outlines whose heading lines match the -regexp. 'C-c / s' ('outline-show-by-heading-regexp') does the inverse: -it shows the bodies of outlines that matched a regexp. - -+++ -*** 'outline-minor-mode' is supported in tree-sitter major modes. -It can be used in all tree-sitter major modes that set either the -variable 'treesit-simple-imenu-settings' or 'treesit-outline-predicate'. - -** Info - ---- -*** New user option 'Info-url-alist'. -This user option associates manual names with URLs. It affects the -'Info-goto-node-web' command. By default, associations for all -Emacs-included manuals are set. Further associations can be added for -arbitrary Info manuals. - ---- -*** Emacs can now display Info manuals compressed with 'lzip'. -This requires the 'lzip' program to be installed on your system. - -** GUD (Grand Unified Debugger) - -+++ -*** New user option 'gud-highlight-current-line'. -When enabled, GUD will visually emphasize the line being executed upon -pauses in the debuggee's execution, such as those occasioned by -breakpoints being hit. - -+++ -*** New command 'lldb'. -Run the LLDB debugger, analogous to the 'gud-gdb' command. - ---- -*** Variable order and truncation can now be configured in 'gdb-many-windows'. -The new user option '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'. - -By default, this user option 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'. - -If you want to get back the old behavior, set the user option to the value - - (setopt gdb-locals-table-row-config - `((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) - -+++ -*** New user option 'gdb-display-io-buffer'. -If this is nil, command 'gdb' will neither create nor display a separate -buffer for the I/O of the program being debugged, but will instead -redirect the program's interaction to the GDB execution buffer. The -default is t, to preserve previous behavior. - -** Grep - -+++ -*** New user option 'grep-use-headings'. -When non-nil, the output of Grep is split into sections, one for each -file, instead of having file names prefixed to each line. It is -equivalent to the '--heading' option of some tools such as 'git grep' -and 'rg'. The headings are displayed using the new 'grep-heading' face. -The default is nil. - -** Compilation mode - ---- -*** The 'omake' matching rule is now disabled by default. -This is because it partly acts by modifying other rules which may -occasionally be surprising. It can be re-enabled by adding 'omake' to -'compilation-error-regexp-alist'. - ---- -*** Lua errors and stack traces are now recognized. -Compilation mode now recognizes Lua language errors and stack traces. -Every Lua error is recognized as a compilation error, and every Lua -stack frame is recognized as a compilation info. - -** Project - -+++ -*** New user option 'project-mode-line'. -When non-nil, display the name of the current project on the mode -line. Clicking 'mouse-1' on the project name pops up the project -menu. The default value is nil. - ---- -*** New user option 'project-file-history-behavior'. -Customizing it to 'relativize' makes commands like 'project-find-file' -and 'project-find-dir' display previous history entries relative to -the current project. - --- -*** New user option 'project-key-prompt-style'. -The look of the key prompt in the project switcher has been changed -slightly. To get the previous one, set this option to 'brackets'. - ---- -*** Function 'project-try-vc' tries harder to find the responsible VCS. -When 'project-vc-extra-root-markers' is non-nil, and causes a -subdirectory project to be detected which is not a VCS root, Project now -additionally traverses the parent directories until a VCS root is found -(if any), so that the ignore rules for that repository are used, and -the file listing's performance is still optimized. - -+++ -*** New commands 'project-any-command' and 'project-prefix-or-any-command'. -The former is now bound to 'C-x p o' by default. -The latter is designed primarily for use as a value of -'project-switch-commands'. If instead of a short menu you prefer to -have access to all keys defined inside 'project-prefix-map', as well -as global bindings (to run other commands inside the project root), -you can add this to your init script: - - (setopt project-switch-commands #'project-prefix-or-any-command) - ---- -*** New variable 'project-files-relative-names'. -If it is non-nil, 'project-files' can return file names relative to the -project root. Project backends can use this to improve the performance -of their 'project-files' implementation. - -** VC - ---- -*** Log-Edit buffers now display a tool bar. -This tool bar contains items for committing log entries and editing or -generating log entries, among other editing operations. - ---- -*** 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. - ---- -*** New value 'no-backend' for user option 'vc-display-status'. -With this value only the revision number is displayed on the mode-line. - ---- -*** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'. -The command was previously obsoleted and unbound in Emacs 28. - ---- -*** Support for viewing VC change history across renames. -When a fileset's VC change history ends at a rename, 'C-x v l' now -prints the old name(s) and shows a button which jumps to the history of -the files under the old names. This feature is supported for Git and -Hg. Naturally, 'vc-git-print-log-follow' should be nil for this to work -(or '--follow' should not be in 'vc-hg-log-switches', in Hg's case). -Unlike when the '--follow' switch is used, commands to see the diff of -the old revision ('d'), to check out an old file version ('f') or to -annotate it ('a'), also work on revisions which precede renames. - ---- -*** 'vc-annotate' now abbreviates the Git revision in the buffer name. -When using the Git backend, 'vc-annotate' will use an abbreviated -revision identifier in its buffer name. To restore the previous -behavior, set user option 'vc-annotate-use-short-revision' to nil. - ---- -*** New user option 'vc-git-file-name-changes-switches'. -It allows tweaking the thresholds for rename and copy detection. - -** Diff mode - ---- -*** New user option 'diff-refine-nonmodified'. -When this is non-nil, 'diff-refine-hunk' will highlight lines that were -added or removed in their entirety (as opposed to modified lines, where -some parts of the line were modified), using the same faces as for -highlighting the words added and removed within modified lines. The -default value is nil. - -+++ -*** 'diff-ignore-whitespace-hunk' can now be applied to all hunks. -When called with a non-nil prefix argument, -'diff-ignore-whitespace-hunk' now iterates over all the hunks in the -current diff, regenerating them without whitespace changes. - -+++ -*** New user option 'diff-ignore-whitespace-switches'. -This allows changing which type of whitespace changes are ignored when -regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to -the previously hard-coded "-b". - -+++ -*** New command 'diff-apply-buffer' bound to 'C-c RET a'. -It applies the diff in the entire diff buffer and -saves all modified file buffers. - -** Dired - ---- -*** New user option 'dired-movement-style'. -When non-nil, make 'dired-next-line', 'dired-previous-line', -'dired-next-dirline', 'dired-prev-dirline' skip empty lines. -It also controls how to move point when encountering a boundary -(e.g., if every line is visible, invoking 'dired-next-line' at -the last line will move to the first line). The default is nil. - ---- -*** New user option 'dired-filename-display-length'. -It is an integer representing the maximum display length of file names. -The middle part of a file name whose length exceeds the restriction is -hidden and an ellipsis is displayed instead. A value of 'window' -means using the right edge of window as the display restriction. The -default is nil. - ---- -*** New user option 'shell-command-guess-functions'. -It defines how to populate a list of commands available -for 'M-!', 'M-&', '!', '&' and the context menu "Open With" -based on marked files in Dired. Possible backends are -'dired-guess-default', MIME types, XDG configuration -and a universal command such as "open" or "start" -that delegates to the OS. - -+++ -*** New command 'dired-do-open'. -This command is bound to 'E' (mnemonics "External"). Also it can be -used by clicking "Open" in the context menu; it "opens" the marked or -clicked on files according to the OS conventions. For example, on -systems supporting XDG, this runs 'xdg-open' on the files. - -+++ -*** New variable 'dired-guess-shell-alist-optional'. -It contains commands for external viewers and players for various media -formats, moved to this list from 'dired-guess-shell-alist-default'. - ---- -*** The default value of 'dired-omit-size-limit' was increased. -After performance improvements to omitting in large directories, the new -default value is 300k, up from 100k. This means 'dired-omit-mode' will -omit files in directories whose directory listing is up to 300 kilobytes -in size. - -+++ -*** 'dired-listing-switches' handles connection-local values if exist. -This allows to customize different switches for different remote machines. - -** Ediff - ---- -*** New user option 'ediff-floating-control-frame'. -If non-nil, try making the control frame be floating rather than tiled. - -Many X tiling window managers make the Ediff control frame a tiled -window equal in size to the main Emacs frame, which works poorly. -This option is useful to set if you use such a window manager. - -** Buffer Selection - ---- -*** 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.) +*** 'whitespace-cleanup' now adds missing newline at end of file. +If 'whitespace-style' includes 'missing-newline-at-eof (which is the +default), the 'whitespace-cleanup' function will now add the newline. ** Eshell -+++ -*** You can now run Eshell scripts in batch mode. -By adding the following interpreter directive to an Eshell script, you -can make it executable like other shell scripts: - - #!/usr/bin/env -S emacs --batch -f eshell-batch-file - -+++ -*** New builtin Eshell command 'compile'. -This command runs another command, sending its output to a compilation -buffer when the command would output interactively. This can be useful -when defining aliases so that they produce a compilation buffer when -appropriate, but still allow piping the output elsewhere if desired. -For more information, see the "(eshell) Built-ins" node in the Eshell -manual. - -+++ -*** Eshell's 'env' command now supports running commands. -Like in many other shells, Eshell's 'env' command now lets you run a -command passed as arguments to 'env'. If you pass any initial -arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to -'VALUE' before running the command. - ---- -*** Eshell's 'umask' command now supports setting the mask symbolically. -Now, you can pass an argument like "u+w,o-r" to Eshell's 'umask' -command, which will give write permission for owners of newly-created -files and deny read permission for users who are not members of the -file's group. See the Info node "(coreutils) File permissions" for -more information on this notation. - ---- -*** Performance improvements for interactive output in Eshell. -Interactive output in Eshell should now be significantly faster, -especially for commands that can print large amounts of output -(e.g. "cat"). For external commands, Eshell saves time by only looking -for password prompts in the last 256 characters of each block of output. -To restore the previous behavior when checking for password prompts, set -'eshell-password-prompt-max-length' to 'most-positive-fixnum'. - ---- -*** Eshell built-in commands can now display progress. -Eshell built-in commands like "cat" and "ls" now update the display -periodically while running to show their progress. - -+++ -*** New special reference type '#<marker POSITION BUFFER>'. -This special reference type returns a marker at 'POSITION' in -'BUFFER'. You can insert it by typing or using the new interactive -command 'eshell-insert-marker'. You can also insert special -references of any type using the new interactive command -'eshell-insert-special-reference'. See the "(eshell) Arguments" node -in the Eshell manual for more details. - -+++ -*** 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. - -+++ -*** You can now splice Eshell globs in-place into argument lists. -By setting 'eshell-glob-splice-results' to a non-nil value, Eshell -will expand glob results in-place as if you had typed each matching -file name individually. For more information, see the "(eshell) -Globbing" node in the Eshell manual. - -+++ -*** Eshell now supports negative numbers and ranges for indices. -Now, you can retrieve the last element of a list with '$my-list[-1]' -or get a sublist of elements 2 through 4 with '$my-list[2..5]'. For -more information, see the "(eshell) Dollars Expansion" node in the -Eshell manual. - -+++ -*** Eshell commands can now be explicitly-remote (or local). -By prefixing a command name in Eshell with a remote identifier, like -"/ssh:user@remote:whoami", you can now run commands on a particular -host no matter your current directory. Likewise, you can run a -command on your local system no matter your current directory via -"/local:whoami". For more information, see the "(eshell) Remote Access" -node in the Eshell manual. - -+++ -*** Eshell's '$UID' and '$GID' variables are now connection-aware. -Now, when expanding '$UID' or '$GID' in a remote directory, the value -is the user or group ID associated with the remote connection. - ---- -*** Eshell now uses 'field' properties in its output. -In particular, this means that pressing the '<home>' key moves the -point to the beginning of your input, not the beginning of the whole -line. If you want to go back to the old behavior, add something like -this to your configuration: - - (keymap-set eshell-mode-map "<home>" #'eshell-bol-ignoring-prompt) - -This also means you no longer need to adjust 'eshell-prompt-regexp' -when customizing your Eshell prompt. - ---- -*** You can now properly unload Eshell. -Calling '(unload-feature 'eshell)' no longer signals an error, and now -correctly unloads Eshell and all of its modules. - -+++ -*** 'eshell-read-aliases-list' is now an interactive command. -After manually editing 'eshell-aliases-file', you can use this command -to load the edited aliases. - -+++ -*** 'rgrep' is now a builtin Eshell command. -Running 'rgrep' in Eshell now uses the Emacs grep facility instead of -calling external rgrep. - -+++ -*** If a command exits abnormally, the Eshell prompt now shows its exit code. - -+++ -*** New user option 'eshell-history-append'. -If non-nil, each Eshell session will save history by appending new -entries of that session to the history file rather than overwriting -the file with the whole history of the session. The default is nil. - -** Pcomplete - ---- -*** New user option 'pcomplete-remote-file-ignore'. -When this option is non-nil, remote file names are not completed by -Pcomplete. Packages, like 'shell-mode', could set this in order to -suppress remote file name completion at all. - ---- -*** Completion for the 'doas' command has been added. -Command completion for 'doas' in Eshell and Shell mode will now work. - -** Shell mode - -+++ -*** New user option 'shell-get-old-input-include-continuation-lines'. -When this user option is non-nil, 'shell-get-old-input' ('C-RET') -includes multiple shell "\" continuation lines from command output. -Default is nil. - -+++ -*** New user option 'shell-history-file-name'. -When this user option is set to t, 'shell-mode' does not read the shell -history file. Setting this user option to a string specifies the name -of the shell history file to be read. A nil value triggers reading the -environment variable 'HISTFILE'. - -In a 'shell' buffer, this user option is connection-local. - ---- -*** Performance improvements for interactive output. -Interactive output in Shell mode now scans more selectively for password -prompts by only examining the last 256 characters of each block of -output, reducing the time spent when printing large amounts of output. -To restore the old behavior, set 'comint-password-prompt-max-length' to -'most-positive-fixnum'. - -** Prog mode - -+++ -*** New command 'prog-fill-reindent-defun'. -This command either fills a single paragraph in a defun, such as a -docstring, or a comment, or (re)indents the surrounding defun if point -is not in a comment or a string. By default, it is bound to 'M-q' in -'prog-mode' and all its descendants. - -** Imenu - -+++ -*** New user option 'imenu-flatten'. -It controls whether to flatten the list of sections in an imenu, and -how to display the sections in the flattened list. - -+++ -*** The sort order of Imenu completions can now be customized. -You can customize the user option 'completion-category-overrides' -and set 'display-sort-function' for the category 'imenu'. - -** Which Function mode - -+++ -*** Which Function mode can now display function names on the header line. -The new user option 'which-func-display' allows choosing where the -function name is displayed. The default is 'mode' to display in the -mode line. 'header' will display in the header line; -'mode-and-header' displays in both the header line and mode line. - -+++ -*** New user option 'which-func-update-delay'. -This replaces the user option 'idle-update-delay', which was previously -used to control the delay before 'which-function-mode' updated its -display. The user option 'idle-update-delay', which was only used by -Which Function mode, is now obsolete. - -** Tramp - -+++ -*** Tramp methods can be optional. -An optional connection method is not enabled by default. The user must -enable it explicitly by the 'tramp-enable-method' command. The existing -methods "fcp", "krlogin", " ksu" and "nc" are optional now. - -+++ -*** New optional connection method "androidsu". -This provides access to system files with elevated privileges granted by -the idiosyncratic 'su' implementations and system utilities customary on -Android. - -+++ -*** New optional connection method "run0". -This connection method is similar to "sudo", but it uses the -'systemd-run' program internally. - -+++ -*** New connection methods "dockercp" and "podmancp". -These are the external methods counterparts of "docker" and "podman". - -+++ -*** New optional connection methods for containers. -There are new optional connection methods "toolbox", "distrobox", -"flatpak", "apptainer" and "nspawn". They allow accessing system -containers provided by Toolbox or Distrobox, sandboxes provided by -Flatpak, instances managed by Apptainer, or accessing systemd-based -light-weight containers.. - -+++ -*** Connection method "kubernetes" supports now optional container name. -The host name for Kubernetes connections can be of kind [CONTAINER.]POD, -in order to specify a dedicated container. If there is just the pod -name, the first container in the pod is taken. The new user options -'tramp-kubernetes-context' and 'tramp-kubernetes-namespace' allow -accessing pods with different context or namespace but the default one. - -+++ -*** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share'. -The old name still exists as obsolete variable alias. This user -option controls now connection sharing for both ssh-based and -plink-based methods. It allows the values t, nil, and 'suppress'. -The latter suppresses also "ControlMaster" settings in the user's -"~/.ssh/config" file, or connection share configuration in PuTTY -sessions, respectively. - -+++ -*** New command 'tramp-cleanup-some-buffers'. -It kills only a subset of opened remote buffers, subject to the user -option 'tramp-cleanup-some-buffers-hook'. - -+++ -*** New command 'inhibit-remote-files'. -This command disables the handling of file names with the special -remote file name syntax. It should be applied only when remote files -won't be used in this Emacs instance. It provides a slightly improved -performance of file name handling in Emacs. - -+++ -*** New macro 'without-remote-files'. -This macro could wrap code which handles local files only. Due to the -temporary deactivation of remote files, it results in a slightly -improved performance of file name handling in Emacs. - -+++ -*** New user option 'tramp-completion-multi-hop-methods'. -It contains a list of connection methods for which completion should -be attempted at the end of a multi-hop chain. This allows completion -candidates to include a list of, for example, containers running on a -remote docker host. - -+++ -*** New command 'tramp-revert-buffer-with-sudo'. -It reverts the current buffer to visit with "sudo" permissions. The -buffer must either visit a file, or it must run 'dired-mode'. Another -method but "sudo" can be configured with user option -'tramp-file-name-with-method'. - -+++ -*** Direct asynchronous processes are indicated by a connection-local variable. -If direct asynchronous processes shall be used, set the connection-local -variable 'tramp-direct-async-process' to a non-nil value. This has been -changed, in previous Emacs versions this was indicated by the now -deprecated connection property "direct-async-process". See the Tramp -manual "(tramp) Improving performance of asynchronous remote processes". - ---- -*** Direct asynchronous processes use 'tramp-remote-path'. -When a direct asynchronous process is invoked, it uses 'tramp-remote-path' -for setting the remote 'PATH' environment variable. - -** EWW - ---- -*** New mouse bindings in EWW buffers. -Certain form elements that were displayed as buttons, yet could only be -activated by keyboard input, are now operable using 'mouse-2'. With -"Submit" buttons, this triggers submission of the form, while clicks on -other classes of buttons either toggle their values or prompt for user -input, as the case may be. - ---- -*** EWW text input fields and areas are now fields. -In consequence, movement commands and OS input method features now -recognize and confine their activities to the text input field around -point. See also the Info node "(elisp) Fields". - -+++ -*** 'eww-open-file' can now display the file in a new buffer. -By default, the command reuses the "*eww*" buffer, but if called with -the new argument NEW-BUFFER non-nil, it will use a new buffer instead. -Interactively, invoke 'eww-open-file' with a prefix argument to -activate this behavior. - ---- -*** 'eww' URL or keyword prompt now has tab completion. -The interactive minibuffer prompt when invoking 'eww' now has support -for tab completion. - -+++ -*** 'eww' URL and keyword prompt now completes suggested URIs and bookmarks. -The interactive minibuffer prompt when invoking 'eww' now provides -completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes -bookmark URIs. - -+++ -*** New command 'eww-copy-alternate-url'. -It copies an alternate link on the page currently visited in EWW into -the kill ring. Alternate links are optional metadata that HTML pages -use for linking to their alternative representations, such as -translated versions or associated RSS feeds. - -+++ -*** 'eww-open-in-new-buffer' supports the prefix argument. -When invoked with the prefix argument ('C-u'), -'eww-open-in-new-buffer' will not make the new buffer the current one. -This is useful for continuing reading the URL in the current buffer -when the new URL is fetched. - ---- -*** History navigation in EWW now behaves as in other browsers. -Previously, when navigating back and forward through page history, EWW -would add a duplicate entry to the end of the history list each time. -This made it impossible to navigate to the "end" of the history list. -Now, navigating through history in EWW simply changes your position in -the history list, allowing you to reach the end as expected. In -addition, when browsing to a new page from a "historical" one (i.e., a -page loaded by navigating back through history), EWW deletes the history -entries newer than the current page. To change the behavior when -browsing from "historical" pages, you can customize -'eww-before-browse-history-function'. - -+++ -*** 'eww-readable' now toggles display of the readable parts of a web page. -When called interactively, 'eww-readable' toggles whether to display -only the readable parts of a page or the full page. With a positive -prefix argument, it always displays the readable parts, and with a zero -or negative prefix, it always displays the full page. - -+++ -*** New user option 'eww-readable-urls'. -This is a list of regular expressions matching the URLs where EWW should -display only the readable parts by default. For more details, see -"(eww) Basics" in the EWW manual. - ---- -*** New user option 'eww-readable-adds-to-history'. -When non-nil (the default), calling 'eww-readable' adds a new entry to -the EWW page history. - -** Go-ts mode - -+++ -*** New command 'go-ts-mode-docstring'. -This command adds a docstring comment to the current defun. If a -comment already exists, point is only moved to the comment. It is -bound to 'C-c C-d' in 'go-ts-mode'. - -** Man mode - -+++ -*** New user option 'Man-prefer-synchronous-call'. -When this is non-nil, run the 'man' command synchronously rather than -asynchronously (which is the default behavior). - -+++ -*** New user option 'Man-support-remote-systems'. -This option controls whether the man page is formatted on the remote -system when the current buffer's default-directory is remote. You can -invoke the 'man' command with a prefix argument to countermand the -value of this option for the current invocation of 'man'. - -** DocView - ---- -*** New face 'doc-view-svg-face'. -This replaces 'doc-view-svg-foreground' and 'doc-view-svg-background'. -If you don't like the colors produced by the default definition of -this new face when DocView displays documents, customize this face to -restore the colors you were used to, or to get colors more to your -liking. - ---- -*** DocView buffers now display a new tool bar. -This tool bar contains options for searching and navigating within the -document, replacing the incompatible items for incremental search and -editing within the default tool bar displayed in the past. - -** Shortdoc - -+++ -*** New function 'shortdoc-function-examples'. -This function returns examples of use of a given Emacs Lisp function -from the available shortdoc information. - -+++ -*** New function 'shortdoc-help-fns-examples-function'. -This function inserts into the current buffer examples of use of a -given Emacs Lisp function, which it gleans from the shortdoc -information. If you want 'describe-function' ('C-h f') to insert -examples of using the function into regular "*Help*" buffers, add the -following to your init file: - - (add-hook 'help-fns-describe-function-functions - #'shortdoc-help-fns-examples-function) - -** Package - ---- -*** New user option 'package-vc-register-as-project'. -When non-nil, it will automatically register every package as a -project, that you can quickly select using 'project-switch-project' -('C-x p p'). - ---- -*** New user option 'package-vc-allow-build-commands'. -Controls for which packages Emacs runs extra build commands when -installing directly from the package VCS repository. - ---- -*** New command 'package-vc-log-incoming'. -This commands displays incoming changes for a VC package without -modifying the current checkout. - ---- -*** New command to start an inferior Emacs loading only specific packages. -The new command 'package-isolate' will start a new Emacs process, as -a sub-process of Emacs where you invoke the command, in a way that -causes the new process to load only some of the installed packages. -The command prompts for the packages to activate in this -sub-process, and is intended for testing Emacs and/or the packages -in a clean environment. - -** Flymake - -+++ -*** New user option 'flymake-indicator-type'. -This user option controls which error indicator type Flymake should use -in current buffer. Depending on your preference, this can either use -fringes or margins for indicating errors. - -+++ -*** New user option 'flymake-margin-indicators-string'. -It controls, for each error type, the string and its face to display as -the margin indicator. - -+++ -*** New user option 'flymake-autoresize-margins'. -If non-nil, Flymake will resize the margins when 'flymake-mode' is -turned on or off. -Only relevant if 'flymake-indicator-type' is set to 'margins'. - -+++ -*** New user option 'flymake-margin-indicator-position'. -It controls which margin (left or right) is used for margin -indicators. - -+++ -*** New user option 'flymake-show-diagnostics-at-end-of-line'. -When non-nil, Flymake shows summarized descriptions of diagnostics at -the end of the line. Depending on your preference, this can either be -distracting and easily confused with actual code, or a significant -early aid that relieves you from moving the buffer or reaching for the -mouse to consult an error message. - -** Flyspell - -+++ -*** New user option 'flyspell-check-changes'. -When non-nil, Flyspell mode spell-checks only words that you edited; it -does not check unedited words just because you move point across them. - ---- -** JS mode. -The binding 'M-.' has been removed from the major mode keymaps in -'js-mode' and 'js-ts-mode', having it default to the global binding -which calls 'xref-find-definitions'. If the previous one worked -better for you, use 'define-key' in your init script to bind -'js-find-symbol' to that combination again. - ---- -** Json mode. -'js-json-mode' does not derive from 'js-mode' any more so as not -to confuse tools like Eglot or YASnippet into thinking that those -buffers contain Javascript code. - -** Python mode - ---- -*** New user option 'python-indent-block-paren-deeper'. -If non-nil, increase the indentation of the lines inside parens in a -header of a block when they are indented to the same level as the body -of the block: - - if (some_expression - and another_expression): - do_something() - -instead of: - - if (some_expression - and another_expression): - do_something() - ---- -*** New user option 'python-interpreter-args'. -This allows the user to specify command line arguments to the non -interactive Python interpreter specified by 'python-interpreter'. - ---- -*** New function 'python-shell-send-block'. -It sends the python block delimited by 'python-nav-beginning-of-block' -and 'python-nav-end-of-block' to the inferior Python process. - -** Inferior Python mode - ---- -*** Default value of 'python-shell-compilation-regexp-alist' is changed. -Support for Python's ExceptionGroup has been added, so in the Python -shell, the line indicating the source of an error in the error messages -from ExceptionGroup will be recognized as well. - -** Eldoc - ---- -*** 'eldoc' no longer truncates to a single line by default. -Previously, the entire docstring was not available to eldoc, which made -'eldoc-echo-area-use-multiline-p' ineffective. The old behavior may be -kept by customizing 'eldoc-echo-area-use-multiline-p'. - ---- -** Scheme mode. -Scheme mode now handles the regular expression literal '#/regexp/' that -is available in some Scheme implementations. -Also, it should now handle nested sexp-comments. - -** Use package - -+++ -*** New ':vc' keyword. -This keyword enables the user to install packages using package-vc.el. - -+++ -*** New user option 'use-package-vc-prefer-newest'. -This allows the user to always install the newest commit of a package -when using the ':vc' keyword. - -** Gnus - -+++ -*** New backend 'nnfeed'. -This allows backend developers to easily create new backends for web -feeds, as inheriting backends of 'nnfeed'. - -+++ -*** New backend 'nnatom'. -This allow users to add Atom Syndication Format feeds to Gnus as -servers. - -*** The 'nnweb-type' option 'gmane' has been removed. -The gmane.org website is, sadly, down since a number of years with no -prospect of it coming back. Therefore, it is no longer valid to set -the server variable 'nnweb-type' to 'gmane'. - ---- -*** New user option 'gnus-mode-line-logo'. -This allows the user to either disable the display of any logo or -specify which logo will be displayed as part of the -buffer-identification in the mode-line of Gnus buffers. - -** Rmail - ---- -*** New commands for reading mailing lists. -The new Rmail commands 'rmail-mailing-list-post', -'rmail-mailing-list-unsubscribe', 'rmail-mailing-list-help', and -'rmail-mailing-list-archive' allow, respectively, posting to, -unsubscribing from, requesting help about, and browsing the archives -of, the mailing list from which the current email message was -delivered. - -** Dictionary - ---- -*** New user option 'dictionary-search-interface'. -Controls how the 'dictionary-search' command prompts for and displays -dictionary definitions. Customize this user option to 'help' to have -'dictionary-search' display definitions in a "*Help*" buffer and -provide dictionary-based minibuffer completion for word selection. - ---- -*** New user option 'dictionary-read-word-prompt'. -This allows the user to customize the prompt that is used by -'dictionary-search' when asking for a word to search in the -dictionaries. - ---- -*** New user option 'dictionary-display-definition-function'. -This allows the user to customize the way in which 'dictionary-search' -displays word definitions. If non-nil, this user option should be set -to a function that displays a word definition obtained from a -dictionary server. The new function -'dictionary-display-definition-in-help-buffer' can be used to display -the definition in a "*Help*" buffer, instead of the default -"*Dictionary*" buffer. - ---- -*** New user option 'dictionary-read-word-function'. -This allows the user to customize the way in which 'dictionary-search' -prompts for a word to search in the dictionary. This user option -should be set to a function that lets the user select a word and -returns it as a string. The new function -'dictionary-completing-read-word' can be used to prompt with -completion based on dictionary matches. - ---- -*** New user option 'dictionary-read-dictionary-function'. -This allows the user to customize the way in which 'dictionary-search' -prompts for a dictionary to search in. This user option should be set -to a function that lets the user select a dictionary and returns its -name as a string. The new function -'dictionary-completing-read-dictionary' can be used to prompt with -completion based on dictionaries that the server supports. - ---- -*** The default value of 'dictionary-tooltip-dictionary' has changed. -The new default value is t, which means use the same dictionary as the -value of 'dictionary-default-dictionary'. The previous default value -was nil, which effectively disabled 'dictionary-tooltip-mode', even if -the mode was turned on. - -** Pp - -+++ -*** New 'pp-default-function' user option replaces 'pp-use-max-width'. -Its default value is 'pp-fill', a new default pretty-printing function, -which tries to obey 'fill-column'. - ---- -*** 'pp-to-string' takes an additional PP-FUNCTION argument. -This argument specifies the prettifying algorithm to use. - ---- -*** 'pp' and 'pp-to-string' now always include a terminating newline. -In the past they included a terminating newline in most cases but not all. - -** Emacs Lisp mode - ---- -*** ',@' now has 'prefix' syntax. -Previously, the '@' character, which normally has 'symbol' syntax, -would combine with a following Lisp symbol and interfere with symbol -searching. - -+++ -*** 'emacs-lisp-docstring-fill-column' now defaults to 72. -It was previously 65. The new default formats documentation strings to -fit on fewer lines without negatively impacting readability. - -** CPerl mode - ---- -*** Subroutine signatures are now supported. -CPerl mode fontifies subroutine signatures like variable declarations -which makes them visually distinct from subroutine prototypes. - ---- -*** Syntax of Perl up to version 5.40 is supported. -CPerl mode supports the new keywords for exception handling and the -object oriented syntax which were added in Perl 5.36, 5.38 and 5.40. - ---- -*** New user option 'cperl-fontify-trailer'. -This user option takes the values 'perl-code' or 'comment' and treats -text after an "__END__" or "__DATA__" token accordingly. The default -value of 'perl-code' is useful for trailing POD and for AutoSplit -modules, the value 'comment' makes CPerl mode treat trailers as -comment, like Perl mode does. - ---- -*** New command 'cperl-file-style'. -This command sets the indentation style for the current buffer. To -change the default style, either use the user option with the same name -or use the command 'cperl-set-style'. - ---- -*** New minor mode 'cperl-extra-paired-delimiters-mode'. -Perl 5.36 and newer allows using more than 200 non-ASCII paired -delimiters for quote-like constructs, e.g. "q«text»". Use this minor -mode in buffers where this feature is activated. - ---- -*** Commands using the Perl Info manual are obsolete. -The Perl documentation in Info format is no longer distributed with -Perl or on CPAN since more than 10 years. Perl documentation can be -read with 'cperl-perldoc' instead. - ---- -*** Highlighting trailing whitespace has been removed. -The user option 'cperl-invalid-face' is now obsolete, and does -nothing. See the user option 'show-trailing-whitespace' instead. - -** Emacs Sessions (Desktop) - -+++ -*** Restoring buffers visiting remote files can now time out. -When a buffer is restored which visits a remote file, the restoration -of the session could hang if the remote host is off-line or slow to -respond. Setting the user option 'remote-file-name-access-timeout' to -a positive number will abandon the attempt to restore such buffers -after a timeout of that many seconds, thus allowing the rest of -desktop restoration to continue. - -** Recentf - -+++ -*** Checking recent remote files can now time out. -Similarly to buffer restoration by Desktop, 'recentf-mode' checking -of the accessibility of remote files can now time out if -'remote-file-name-access-timeout' is set to a positive number. - -** Image Dired - -+++ -*** New user option 'image-dired-thumb-naming'. -You can now configure how thumbnails are named using this option. - -** ERT - -+++ -*** New macro 'skip-when' to skip 'ert-deftest' tests. -This can help to avoid some awkward skip conditions. For example -'(skip-unless (not noninteractive))' can be changed to the easier -to read '(skip-when noninteractive)'. - -+++ -*** Syntax highlighting unit testing support. -An ERT extension ('ert-font-lock') now provides support for face -assignment unit testing. For more information, see the "(ert) Syntax -Highlighting Tests" node in the ERT manual. - -** Socks - -+++ -*** Socks supports version 4a. -The 'socks-server' user option accepts '4a' as a value for its version -field. - -** Edmacro - -+++ -*** New command 'edmacro-set-macro-to-region-lines'. -Bound to 'C-c C-r', this command replaces the macro text with the -lines of the region. If needed, the region is extended to include -whole lines. If the region ends at the beginning of a line, that last -line is excluded. - -+++ -*** New user option 'edmacro-reverse-macro-lines'. -When this is non-nil, the lines of key sequences are displayed with -the most recent line first. This is can be useful when working with -macros with many lines, such as from 'kmacro-edit-lossage'. - -** Calc - -+++ -*** Calc parses fractions written using U+2044 FRACTION SLASH. -Fractions of the form "123⁄456" are handled as if written "123:456". -Note in particular the difference in behavior from U+2215 DIVISION SLASH -and U+002F SOLIDUS, which result in division rather than a rational -fraction. In addition, precomposed fraction characters, such as ½ -(U+00BD VULGAR FRACTION ONE HALF), are also recognized as rational -fractions. (They have been recognized since 2004, but it looks like it -was never mentioned in the NEWS, or even the Calc manual.) - -** IELM - ---- -*** IELM now remembers input history between sessions. -The new user option 'ielm-history-file-name' is the name of the file -where IELM input history will be saved. Customize it to nil to revert -to the old behavior of not remembering input history between sessions. - -** EasyPG - -+++ -*** New user option 'epa-keys-select-method'. -This allows the user to customize the key selection method, which can be -either by using a pop-up buffer or from the minibuffer. The pop-up -buffer method is the default, which preserves previous behavior. - -** Widget - -+++ -*** New face 'widget-unselected'. -Customize this face to a non-default value to visually distinguish the -labels of unselected active radio-button or checkbox widgets from the -labels of unselected inactive widgets (the default value inherits from -the 'widget-inactive' face). - -+++ -*** New user option 'widget-skip-inactive'. -If non-nil, moving point forward or backward between widgets by typing -'TAB' or 'S-TAB' skips over inactive widgets. The default value is nil. - -** Ruby mode - ---- -*** New user option 'ruby-rubocop-use-bundler'. -By default it retains the previous behavior: read the contents of -Gemfile and act accordingly. But you can also set it to t or nil to -skip the check. - -** Thingatpt - ---- -*** New variables for providing custom thingatpt implementations. -The new variables 'bounds-of-thing-at-point-provider-alist' and -'forward-thing-provider-alist' now allow defining custom implementations -of 'bounds-of-thing-at-point' and 'forward-thing', respectively. - ---- -*** New helper functions for text property-based thingatpt providers. -The new helper functions 'thing-at-point-for-char-property', -'bounds-of-thing-at-point-for-char-property', and -'forward-thing-for-char-property' can help to implement custom thingatpt -providers for "things" that are defined by text properties. - --- -*** 'bug-reference-mode' now supports 'thing-at-point'. -Now, calling '(thing-at-point 'url)' when point is on a bug reference -will return the URL for that bug. - -** Miscellaneous - -+++ -*** New user option 'rcirc-log-time-format'. -This allows for rcirc logs to use a custom timestamp format, which the -chat buffers use by default. +*** New option 'eshell-command-async-buffer'. +This option lets you tell 'eshell-command' how to respond if its output +buffer is already in use by another invocation of 'eshell-command', much +like 'async-shell-command-buffer' does for 'shell-command'. By default, +this will prompt for confirmation before creating a new buffer when +necessary. To restore the previous behavior, set this option to +'confirm-kill-process'. ---- -*** New user option 'Buffer-menu-group-by'. -It controls how buffers are divided into groups that are displayed with -headings using Outline minor mode. Using commands that mark buffers -on the outline heading line will mark all buffers in the outline. +** SHR +++ -*** New command 'Buffer-menu-toggle-internal'. -This command toggles the display of internal buffers in Buffer Menu mode; -that is, buffers not visiting a file and whose names start with a space. -Previously, such buffers were never shown. This command is bound to 'I' -in Buffer Menu mode. - ---- -*** 'ffap-lax-url' now defaults to nil. -Previously, it was set to t, but this broke remote file name detection. - ---- -*** More control on automatic update of Proced buffers. -The user option 'proced-auto-update-flag' can now be set to two -additional values, which control automatic updates of Proced buffers -that are not displayed in some window. - ---- -*** nXML Mode now comes with schemas for Mono/.NET development. -The following new XML schemas are now supported: -- MSBuild project files -- Dotnet package properties files -- Dotnet resource extension files -- Dotnet Application config files -- Nuget config file -- Nuget package specification file -- Nuget packages config file +*** SHR now slices large images into rows. +Sliced images allow for more intuitive scrolling up/down by letting you +scroll past each slice, instead of jumping past the entire image. +Previously, SHR sliced images when zoomed to their original size, no +matter how large or small that was). Now, SHR slices any images taller +than 'shr-sliced-image-height'. For more information, see the "(eww) +Advanced" node in the EWW manual. --- -*** color.el now supports the Oklab color representation. - -+++ -*** New user option 'xwidget-webkit-disable-javascript'. -This allows disabling JavaScript in xwidget Webkit sessions. - ---- -*** 'ls-lisp--insert-directory' supports more long options of 'ls'. -'ls-lisp--insert-directory', the ls-lisp implementation of -'insert-directory', now supports the '--time=TIME' and '--sort=time' -options of GNU 'ls'. - ---- -*** 'M-x ping' can now give additional flags to the 'ping' program. -Typing 'C-u M-x ping' prompts first for the host, and then for the flags -to give to the 'ping' command. - ---- -*** Webjump now assumes URIs are HTTPS instead of HTTP. -For links in 'webjump-sites' without an explicit URI scheme, it was -previously assumed that they should be prefixed with "http://". Such -URIs are now prefixed with "https://" instead. - ---- -*** Added prefixes in titdic-cnv library. -Most of the variables and functions in the file have been renamed to -make sure they all use a 'tit-' namespace prefix. - ---- -*** 'xref-revert-buffer' is now an alias of 'revert-buffer'. -The Xref buffer now sets up 'revert-buffer-function' such that -'revert-buffer' behaves like 'xref-revert-buffer' did in previous Emacs -versions, and the latter is now an alias of the former. - ---- -*** The Makefile browser is now obsolete. -The command 'makefile-switch-to-browser' command is now obsolete, -together with related commands used in the "*Macros and Targets*" -buffer. We recommend using an alternative like 'imenu' instead. +*** You can now customize the image zoom levels to cycle through. +By customizing 'shr-image-zoom-levels', you can change the list of zoom +levels that SHR cycles through when calling 'shr-zoom-image'. -* New Modes and Packages in Emacs 30.1 - -** New major modes based on the tree-sitter library - -+++ -*** New major mode 'elixir-ts-mode'. -A major mode based on the tree-sitter library for editing Elixir files. - -+++ -*** New major mode 'heex-ts-mode'. -A major mode based on the tree-sitter library for editing HEEx files. - -+++ -*** New major mode 'html-ts-mode'. -An optional major mode based on the tree-sitter library for editing -HTML files. - -+++ -*** New major mode 'lua-ts-mode'. -A major mode based on the tree-sitter library for editing Lua files. - -+++ -*** New major mode 'php-ts-mode'. -A major mode based on the tree-sitter library for editing PHP files. - -+++ -** New package EditorConfig. -This package provides support for the EditorConfig standard, -an editor-neutral way to provide directory local (project-wide) settings. -It is enabled via a new global minor mode 'editorconfig-mode' -which makes Emacs obey the '.editorconfig' files. -There is also a new major mode 'editorconfig-conf-mode' -to edit those configuration files. - -+++ -** New global minor mode 'etags-regen-mode'. -This minor mode generates the tags table automatically based on the -current project configuration, and later updates it as you edit the -files and save the changes. - -+++ -** New package 'which-key'. -The 'which-key' package from GNU ELPA is now included in Emacs. It -implements the global minor mode 'which-key-mode' that displays a table -of key bindings upon entering a partial key chord and waiting for a -moment. For example, after enabling the minor mode, if you enter 'C-x' -and wait for one second, the minibuffer will expand with all available -key bindings that follow 'C-x' (or as many as space allows). - -+++ -** New minor mode 'completion-preview-mode'. -This minor mode shows you symbol completion suggestions as you type, -using an inline preview. New user options in the 'completion-preview' -customization group control exactly when Emacs displays this preview. -'completion-preview-mode' is buffer-local, to enable it globally use -'global-completion-preview-mode'. - -+++ -** New package Window-Tool-Bar. -This provides a new minor mode, 'window-tool-bar-mode'. When this minor -mode is enabled, a tool bar is displayed at the top of a window. To -conserve space, no tool bar is shown if 'tool-bar-map' is nil. The -global minor mode 'global-window-tool-bar-mode' enables this minor mode -in all buffers. - -+++ -** New library Track-Changes. -This library is a layer of abstraction above 'before-change-functions' -and 'after-change-functions' which provides a superset of -the functionality of 'after-change-functions': -- It provides the actual previous text rather than only its length. -- It takes care of accumulating and bundling changes until a time when - its client finds it convenient to react to them. -- It detects most cases where some changes were not properly - reported (calls to 'before/after-change-functions' that are - incorrectly paired, missing, etc...) and reports them adequately. - -+++ -** New global minor mode 'minibuffer-regexp-mode'. -This is a minor mode for editing regular expressions in the minibuffer, -for example in 'query-replace-regexp'. It correctly highlights parens -via 'show-paren-mode' and 'blink-matching-paren' in a user-friendly way, -avoids reporting alleged paren mismatches and makes sexp navigation more -intuitive. - ---- -** The highly accessible Modus themes collection has eight items. -The 'modus-operandi' and 'modus-vivendi' are the main themes that have -been part of Emacs since version 28. The former is light, the latter -dark. In addition to these, we now have 'modus-operandi-tinted' and -'modus-vivendi-tinted' for easier legibility, as well as -'modus-operandi-deuteranopia', 'modus-vivendi-deuteranopia', -'modus-operandi-tritanopia', and 'modus-vivendi-tritanopia' to cover -the needs of users with red-green or blue-yellow color deficiency. -The Info manual "(modus-themes) Top" describes the details and -showcases all their user options. - -+++ -** New library PEG. -Emacs now includes a library for writing Parsing Expression -Grammars (PEG), an approach to text parsing that provides more structure -than regular expressions, but less complexity than context-free -grammars. The Info manual "(elisp) Parsing Expression Grammars" has -documentation and examples. - ---- -** New major mode 'shell-command-mode'. -This mode is used by default for the output of asynchronous 'shell-command'. -To revert to the previous behavior, set the (also new) variable -'async-shell-command-mode' to 'shell-mode'. Any hooks or mode-specific -variables used should be adapted appropriately. - -+++ -** New package Compat. -Emacs now comes with a stub implementation of the -forwards-compatibility Compat package from GNU ELPA. This allows -built-in packages to use the library more effectively, and helps -preventing the installation of Compat if unnecessary. +* New Modes and Packages in Emacs 31.1 -* Incompatible Lisp Changes in Emacs 30.1 - -+++ -** Evaluating a 'lambda' returns an object of type 'interpreted-function'. -Instead of representing interpreted functions as lists that start with -either 'lambda' or 'closure', Emacs now represents them as objects -of their own 'interpreted-function' type, which is very similar -to 'byte-code-function' objects (the argument list, docstring, and -interactive forms are placed in the same slots). -Lists that start with 'lambda' are now used only for non-evaluated -functions (in other words, for source code), but for backward compatibility -reasons, 'functionp' still recognizes them as functions and you can -still call them as before. -Thus code that attempts to "dig" into the internal structure of an -interpreted function's object with the likes of 'car' or 'cdr' will -no longer work and will need to use 'aref' instead to extract its -various subparts (when 'interactive-form', 'documentation', and -'help-function-arglist' aren't adequate). - ---- -** The escape sequence '\x' not followed by hex digits is now an error. -Previously, '\x' without at least one hex digit denoted character code -zero (NUL) but as this was neither intended nor documented or even -known by anyone, it is now treated as an error by the Lisp reader. - ---- -** 'subr-native-elisp-p' is renamed to 'native-comp-function-p'. -The previous name still exists but is marked as obsolete. - -+++ -** 'define-globalized-minor-mode' requires that modes use 'run-mode-hooks'. -Minor modes defined with 'define-globalized-minor-mode', such as -'global-font-lock-mode', will not be enabled any more in those buffers -whose major modes fail to use 'run-mode-hooks'. Major modes defined -with 'define-derived-mode' are not affected. 'run-mode-hooks' has been the -recommended way to run major mode hooks since Emacs 22. - -+++ -** 'buffer-match-p' and 'match-buffers' take '&rest ARGS'. -They used to take a single '&optional ARG' and were documented to use -an unreliable hack to try and support condition predicates that -don't accept this optional ARG. -The new semantics makes no such accommodation, but the code still -supports it (with a warning) for backward compatibility. - ---- -** 'post-gc-hook' runs after updating 'gcs-done' and 'gc-elapsed'. - ---- -** Connection-local variables are applied in buffers visiting remote files. -This overrides possible directory-local or file-local variables with -the same name. - -+++ -** 'copy-tree' now copies records when its optional 2nd argument is non-nil. - -+++ -** Regexp zero-width assertions followed by operators are better defined. -Previously, regexps such as "xy\\B*" would have ill-defined behavior. -Now any operator following a zero-width assertion applies to that -assertion only (which is useless). For historical compatibility, an -operator character following '^' or '\`' becomes literal, but we -advise against relying on this. - -+++ -** Infinities and NaNs no longer act as symbols on non-IEEE platforms. -On old platforms like the VAX that do not support IEEE floating-point, -tokens like '0.0e+NaN' and '1.0e+INF' are no longer read as symbols. -Instead, the Lisp reader approximates an infinity with the nearest -finite value, and a NaN with some other non-numeric object that -provokes an error if used numerically. - -+++ -** Conversion of strings to and from byte-arrays works with multibyte strings. -The functions 'dbus-string-to-byte-array' and -'dbus-byte-array-to-string' now accept and return multibyte Lisp -strings, encoding to UTF-8 and decoding from UTF-8 internally. This -means that the argument to 'dbus-byte-array-to-string' must be a valid -UTF-8 byte sequence, and the optional parameter MULTIBYTE of -'dbus-byte-array-to-string' is now obsolete and unused. The argument of -'dbus-string-to-byte-array' should be a regular Lisp string, not a -unibyte string. - -+++ -** 'minibuffer-allow-text-properties' now can be set buffer-local. -'read-from-minibuffer' and functions that use it can take the -buffer-local value from the minibuffer. - -+++ -** 'minibuffer-allow-text-properties' also affects completions. -When it has a non-nil value, then completion functions like -'completing-read' don't discard text properties from the returned -completion candidate. - -+++ -** X color support compatibility aliases are now obsolete. -The compatibility aliases 'x-defined-colors', 'x-color-defined-p', -'x-color-values', and 'x-display-color-p' are now obsolete. - -+++ -** 'easy-mmode-define-{minor,global}-mode' aliases are now obsolete. -Use 'define-minor-mode' and 'define-globalized-minor-mode' instead. - -+++ -** The 'millisec' argument of 'sleep-for' is now obsolete. -Use a float value for the first argument instead. - ---- -** User options 'eshell-NAME-unload-hook' are now obsolete. -These hooks were named incorrectly, and so they never actually ran -when unloading the corresponding feature. Instead, you should use -hooks named after the feature name, like 'esh-mode-unload-hook'. - -** User options 'eshell-process-wait-{seconds,milliseconds}' are now obsolete. -Instead, use 'eshell-process-wait-time', which supports floating-point -values. - ---- -** User option 'tramp-completion-reread-directory-timeout' has been removed. -This user option has been obsoleted in Emacs 27, use -'remote-file-name-inhibit-cache' instead. - -+++ -** The obsolete calling convention of 'sit-for' has been removed. -That convention was: '(sit-for SECONDS MILLISEC &optional NODISP)'. - ---- -** 'defadvice' is marked as obsolete. -See the "(elisp) Porting Old Advice" Info node for help converting -them to use 'advice-add' or 'define-advice' instead. - ---- -** 'cl-old-struct-compat-mode' is marked as obsolete. -You may need to recompile your code if it was compiled with Emacs < 24.3. - ---- -** Old derived.el functions removed. -The following functions have been deleted because they were only used -by code compiled with Emacs < 21: -'derived-mode-init-mode-variables', 'derived-mode-merge-abbrev-tables', -'derived-mode-merge-keymaps', 'derived-mode-merge-syntax-tables', -'derived-mode-run-hooks', 'derived-mode-set-abbrev-table', -'derived-mode-set-keymap', 'derived-mode-set-syntax-table', -'derived-mode-setup-function-name'. +* Incompatible Lisp Changes in Emacs 31.1 -* Lisp Changes in Emacs 30.1 - -+++ -** The 'wheel-up/down/left/right' events are now bound unconditionally. -The 'mouse-wheel-up/down/left/right-event' variables are thus used only -to specify the 'mouse-4/5/6/7' events that might still happen to be -generated by some old packages (or if 'mouse-wheel-buttons' has been set -to nil). - ---- -** Xterm Mouse mode now emits 'wheel-up/down/right/left' events. -This is instead of 'mouse-4/5/6/7' events for the mouse wheel. It uses -the new variable 'mouse-wheel-buttons' to decide which button maps to -which wheel event (if any). - ---- -** In batch mode, tracing now sends the trace to stdout. - -+++ -** New hook 'hack-dir-local-get-variables-functions'. -This can be used to provide support for other directory-local settings -beside ".dir-locals.el". - -+++ -** 'auto-coding-functions' can know the name of the file. -The functions on this hook can now find the name of the file to -which the text belongs by consulting the variable 'auto-coding-file-name'. - -+++ -** New user option 'compilation-safety' to control safety of native code. -It is now possible to control how safe is the code generated by native -compilation, by customizing this user option. It is also possible to -control this at function granularity by using the new 'safety' parameter -in the function's 'declare' form. - -+++ -** New types 'closure' and 'interpreted-function'. -'interpreted-function' is the new type used for interpreted functions, -and 'closure' is the common parent type of 'interpreted-function' -and 'byte-code-function'. - -Those new types come with the associated new predicates 'closurep' and -'interpreted-function-p' as well as a new constructor -'make-interpreted-closure'. - ---- -** New function 'help-fns-function-name'. -For named functions, it just returns the name and otherwise -it returns a short "unique" string that identifies the function. -In either case, the string is propertized so clicking on it gives -further details. - -+++ -** New function 'char-to-name'. -This is a convenience function to return the Unicode name of a char (if -it has one). - -+++ -** New function 'cl-type-of'. -This function is like 'type-of' except that it sometimes returns -a more precise type. For example, for nil and t it returns 'null' -and 'boolean' respectively, instead of just 'symbol'. - -+++ -** New functions 'primitive-function-p' and 'cl-functionp'. -'primitive-function-p' is like 'subr-primitive-p' except that it returns -t only if the argument is a function rather than a special-form, -and 'cl-functionp' is like 'functionp' except it returns nil -for lists and symbols. - ---- -** Built-in types now have corresponding classes. -At the Lisp level, this means that things like '(cl-find-class 'integer)' -will now return a class object, and at the UI level it means that -things like 'C-h o integer RET' will show some information about that type. - ---- -** New variable 'major-mode-remap-defaults' and function 'major-mode-remap'. -The first is like Emacs-29's 'major-mode-remap-alist' but to be set by -packages (instead of users). The second looks up those two variables. - -+++ -** Pcase's functions (in 'pred' and 'app') can specify the argument position. -For example, instead of '(pred (< 5))' you can write '(pred (> _ 5))'. - -+++ -** 'define-advice' now sets the new advice's 'name' property to NAME. -Named advices defined with 'define-advice' can now be removed with -'(advice-remove SYMBOL NAME)' in addition to '(advice-remove SYMBOL -SYMBOL@NAME)'. - -+++ -** New function 'require-with-check' to detect new versions shadowing. -This is like 'require', but it checks whether the argument 'feature' -is already loaded, in which case it either signals an error or -forcibly reloads the file that defines the feature. - -+++ -** New variable 'lisp-eval-depth-reserve'. -It puts a limit to the amount by which Emacs can temporarily increase -'max-lisp-eval-depth' when handling signals. - -+++ -** New special form 'handler-bind'. -It provides a functionality similar to 'condition-case' except it runs -the handler code without unwinding the stack, such that we can record -the backtrace and other dynamic state at the point of the error. See -the Info node "(elisp) Handling Errors". - -+++ -** New text properties add tooltips on fringes. -It is now possible to provide tooltips on fringes by adding special text -properties 'left-fringe-help' and 'right-fringe-help'. See the "(elisp) -Special Properties" Info node in the Emacs Lisp Reference Manual for -more details. - -+++ -** New 'display-buffer' action alist entry 'pop-up-frames'. -This has the same effect as the variable of the same name and takes -precedence over the variable when present. - ---- -** New function 'merge-ordered-lists'. -Mostly used internally to do a kind of topological sort of -inheritance hierarchies. - -+++ -** 'drop' is now an alias for the function 'nthcdr'. - -+++ -** New polymorphic comparison function 'value<'. -This function returns non-nil if the first argument is less than the -second. It works for any two values of the same type with reasonable -ordering for numbers, strings, symbols, bool-vectors, markers, buffers -and processes. Conses, lists, vectors and records are ordered -lexicographically. -It is intended as a convenient ordering predicate for sorting, and is -likely to be faster than hand-written Lisp functions. - -+++ -** New 'sort' arguments and features. -The 'sort' function can now be called using the signature - - (sort SEQ &rest KEYWORD-ARGUMENTS) - -where arguments after the first are keyword/value pairs, all optional: -':key' specifies a function that produces the sorting key from an element, -':lessp' specifies the ordering predicate, defaulting to 'value<', -':reverse' is used to reverse the sorting order, -':in-place is used for in-place sorting, as the default is now to -sort a copy of the input. - -The new signature is less error-prone and reduces the need to write -ordering predicates by hand. We recommend that you use the ':key' -argument instead of ':lessp' unless a suitable ordering predicate is -already available. This can also be used for multi-key sorting: - - (sort seq :key (lambda (x) (list (age x) (size x) (cost x)))) - -sorts by the return value of 'age', then by 'size', then by 'cost'. - -The old signature, '(sort SEQ PREDICATE)', can still be used and sorts -its input in-place as before. - -** New API for 'derived-mode-p' and control of the graph of major modes. - -+++ -*** 'derived-mode-p' now takes the list of modes as a single argument. -The same holds for 'provided-mode-derived-p'. -The old calling convention where multiple modes are passed as -separate arguments is deprecated. - -+++ -*** New functions to access the graph of major modes. -While 'define-derived-mode' still only supports single inheritance, -modes can declare additional parents (for tests like 'derived-mode-p') -with 'derived-mode-add-parents'. -Accessing the 'derived-mode-parent' property directly is now -deprecated in favor of the new functions 'derived-mode-set-parent' -and 'derived-mode-all-parents'. - -+++ -** Drag-and-drop functions can now be called once for compound drops. -It is now possible for drag-and-drop handler functions to respond to -drops incorporating more than one URL. Functions capable of this must -set their 'dnd-multiple-handler' symbol properties to a non-nil value. -See the Info node "(elisp) Drag and Drop". - -The function 'dnd-handle-one-url' has been made obsolete, since it -cannot take these new handlers into account. - -+++ -** 'notifications-notify' can use Icon Naming Specification for ':app-icon'. -You can use a symbol as the value for ':app-icon' to provide icon name -without specifying a file, like this: - - (notifications-notify - :title "I am playing music" :app-icon 'multimedia-player) - ---- -** New function 're-disassemble' to see the innards of a regexp. -If you built Emacs with '--enable-checking', you can use this to help -debug either your regexp performance problems or the regexp engine. - -+++ -** XLFDs are no longer restricted to 255 characters. -'font-xlfd-name' now returns an XLFD even if it is greater than 255 -characters in length, provided that the LONG_XLFDs argument is true. -Other features in Emacs which employ XLFDs have been modified to -produce and understand XLFDs larger than 255 characters. - -+++ -** New macro 'static-if' for conditional evaluation of code. -This macro hides a form from the evaluator or byte-compiler based on a -compile-time condition. This is handy for avoiding byte-compilation -warnings about code that will never actually run under some conditions. - -+++ -** Desktop notifications are now supported on the Haiku operating system. -The new function 'haiku-notifications-notify' provides a subset of the -capabilities of the 'notifications-notify' function in a manner -analogous to 'w32-notification-notify'. - -** New Haiku specific variable 'haiku-pass-control-tab-to-system'. -This sets whether Emacs should pass 'C-TAB' on to the system instead of -handling it, fixing a problem where window switching would not activate -if an Emacs frame had focus on the Haiku operating system. - -+++ -** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. -It results in 'insert-file-contents' erasing the buffer instead of -preserving markers if the file being inserted is not a regular file, -rather than signaling an error. - -+++ -** New variable 'current-key-remap-sequence'. -It is bound to the key sequence that caused a call to a function bound -within 'function-key-map' or 'input-decode-map' around those calls. - -+++ -** The function 'key-translate' can now remove translations. -If the second argument TO is nil, the existing key translation is -removed. - -+++ -** New variables describing the names of built in programs. -The new variables 'ctags-program-name', 'ebrowse-program-name', -'etags-program-name', 'hexl-program-name', 'emacsclient-program-name' -'movemail-program-name', and 'rcs2log-program-name' should be used -instead of "ctags", "ebrowse", "etags", "hexl", "emacsclient", and -"rcs2log", when starting one of these built in programs in a subprocess. - -+++ -** New variable 'case-symbols-as-words' affects case operations for symbols. -If non-nil, then case operations such as 'upcase-initials' or -'replace-match' (with nil FIXEDCASE) will treat the entire symbol name -as a single word. This is useful for programming languages and styles -where only the first letter of a symbol's name is ever capitalized. -The default value of this variable is nil. - ---- -** Bytecode is now always loaded eagerly. -Bytecode compiled with older Emacs versions for lazy loading using -'byte-compile-dynamic' is now loaded all at once. -As a consequence, 'fetch-bytecode' has no use, does nothing, and is -now obsolete. The variable 'byte-compile-dynamic' has no effect any -more; compilation will always yield bytecode for eager loading. - -+++ -** Returned strings from functions and macros are never docstrings. -Functions and macros whose bodies consist of a single string literal now -only return that string, and will not use it as a docstring. Example: - - (defun sing-a-song () - "Sing a song.") - -The above function returns the string "Sing a song." and has no -docstring. Previously, that string was used as both the docstring and -return value, which was never what the programmer wanted. If you want -the string to be a docstring, add an explicit return value. - -This change applies to 'defun', 'defsubst', 'defmacro' and 'lambda' -forms; other defining forms such as 'cl-defun' already worked this way. - -** New or changed byte-compilation warnings - ---- -*** Warn about missing 'lexical-binding' directive. -The compiler now warns if an Elisp file lacks the standard -'-*- lexical-binding: ... -*-' cookie on the first line. -This line typically looks something like - - ;;; My little pony mode -*- lexical-binding: t -*- - -It is needed to inform the compiler about which dialect of ELisp -your code is using: the modern dialect with lexical binding or -the old dialect with only dynamic binding. - -Lexical binding avoids some name conflicts and allows the compiler to -detect more mistakes and generate more efficient code, so it is -recommended. For how to adapt your code to lexical binding, see the -manual section "(elisp) Converting to Lexical Binding". - -If your code cannot be converted to lexical binding, you can insert -the line - - ;;; -*- lexical-binding: nil -*- - -first in the file to declare that it uses the old dialect. - ---- -*** 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: - - (when (> x 2)) - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'empty-body'. - ---- -*** 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: - - (condition-case nil - (/ x y) - ('arith-error "division by zero")) - -Quoting them adds the error name 'quote' to those handled or ignored -respectively, which was probably not intended. - ---- -*** 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: - - (eq x "hello") - -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'. - -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. - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'suspicious'. - ---- -*** Warn about 'condition-case' without handlers. -The compiler now warns when the 'condition-case' form is used without -any actual handlers, as in - - (condition-case nil (read buffer)) - -because it has no effect other than the execution of the body form. -In particular, no errors are caught or suppressed. If the intention -was to catch all errors, add an explicit handler for 'error', or use -'ignore-error' or 'ignore-errors'. - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'suspicious'. - ---- -*** Warn about 'unwind-protect' without unwind forms. -The compiler now warns when the 'unwind-protect' form is used without -any unwind forms, as in - - (unwind-protect (read buffer)) - -because the behavior is identical to that of the argument; there is -no protection of any kind. Perhaps the intended unwind forms have -been misplaced or forgotten, or the use of 'unwind-protect' could be -simplified away. - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'suspicious'. - ---- -*** Warn about useless trailing 'cond' clauses. -The compiler now warns when a 'cond' form contains clauses following a -default (unconditional) clause. Example: - - (cond ((= x 0) (say "none")) - (t (say "some")) - (say "goodbye")) - -Such a clause will never be executed, and is likely to be a mistake, -perhaps due to misplaced parens. - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'suspicious'. - ---- -*** Warn about mutation of constant values. -The compiler now warns about code that modifies program constants in -some obvious cases. Examples: - - (setcar '(1 2) 7) - (aset [3 4] 0 8) - (aset "abc" 1 ?d) - -Such code may have unpredictable behavior because the constants are part -of the program and are not data structures generated afresh during -execution; the compiler does not expect them to change. - -To avoid the warning, operate on an object created by the program -(maybe a copy of the constant), or use a non-destructive operation -instead. - -This warning can be suppressed using 'with-suppressed-warnings' with -the warning name 'mutate-constant'. - ---- -*** Warn about more ignored function return values. -The compiler now warns when the return value from certain functions is -implicitly ignored. Example: - - (progn (nreverse my-list) my-list) - -will elicit a warning because it is usually pointless to call -'nreverse' on a list without using the returned value. - -To silence the warning, make use of the value in some way, such as -assigning it to a variable. You can also wrap the function call in -'(ignore ...)', or use 'with-suppressed-warnings' with the warning -name 'ignored-return-value'. - -The warning will only be issued for calls to functions declared -'important-return-value' or 'side-effect-free' (but not 'error-free'). - ---- -*** Warn about docstrings that contain control characters. -The compiler now warns about docstrings with control characters other -than newline and tab. This is often a result of improper escaping. -Example: - - (defun my-fun () - "Uses c:\remote\dir\files and the key \C-x." - ...) - -where the docstring contains the four control characters 'CR', 'DEL', -'FF' and 'C-x'. - -The warning name is 'docstrings-control-chars'. - ---- -*** The warning about wide docstrings can now be disabled separately. -Its warning name is 'docstrings-wide'. - -+++ -** 'fset', 'defalias' and 'defvaralias' now signal an error for cyclic aliases. -Previously, 'fset', 'defalias' and 'defvaralias' could be made to -build circular function and variable indirection chains as in - - (defalias 'able 'baker) - (defalias 'baker 'able) - -but trying to use them would sometimes make Emacs hang. Now, an attempt -to create such a loop results in an error. - -Since circular alias chains now cannot occur, 'function-alias-p', -'indirect-function' and 'indirect-variable' will never signal an error. -Their 'noerror' arguments have no effect and are therefore obsolete. - -** Touch Screen support - -+++ -*** 'x-popup-menu' now understands touch screen events. -When a 'touchscreen-begin' or 'touchscreen-end' event is passed as the -POSITION argument, it will behave as if that event was a mouse event. - -+++ -*** New functions for handling touch screen events. -The new functions 'touch-screen-track-tap' and 'touch-screen-track-drag' -handle tracking common touch screen gestures from within a command. - -+++ -*** New parameter to 'touchscreen-end' events. -CANCEL non-nil establishes that the touch sequence has been intercepted -by programs such as window managers and should be ignored with Emacs. - ---- -** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill. - -+++ -** New variable 'secondary-tool-bar-map'. -If non-nil, this variable contains a keymap of menu items that are -displayed along tool bar items defined by 'tool-bar-map'. These items -are displayed below the tool bar if the value of 'tool-bar-position' is -'top', and above it if the value is 'bottom'. This is used by -'modifier-bar-mode'. - ---- -** New variable 'completion-lazy-hilit'. -Lisp programs that present completion candidates may bind this -variable non-nil around calls to functions such as -'completion-all-completions'. This tells the underlying completion -styles to skip eager fontification of completion candidates, which -improves performance. Such a Lisp program can then use the -'completion-lazy-hilit' function to fontify candidates just in time. - -+++ -** New primitive 'buffer-last-name'. -It returns the name of a buffer before the last time it was renamed or -killed. - -+++ -** New primitive 'marker-last-position'. -It returns the last position of a marker in its buffer even if that -buffer has been killed. ('marker-position' would return nil in that -case.) - -** Functions and variables to transpose sexps - ---- -*** New helper variable 'transpose-sexps-function'. -Lisp programs can now set this variable to customize the behavior of the -'transpose-sexps' command. - ---- -*** New function 'transpose-sexps-default-function'. -The previous implementation of 'transpose-sexps' was moved into its own -function, to be used in 'transpose-sexps-function'. - ---- -*** New function 'treesit-transpose-sexps'. -Tree-sitter now unconditionally sets 'transpose-sexps-function' for all -tree-sitter enabled modes to this function. - -** Functions and variables to move by program statements - -+++ -*** New variable 'forward-sentence-function'. -Major modes can now set this variable to customize the behavior of the -'forward-sentence' command. - ---- -*** New function 'forward-sentence-default-function'. -The previous implementation of 'forward-sentence' is moved into its -own function, to be bound by 'forward-sentence-function'. - -+++ -*** New function 'treesit-forward-sentence'. -All tree-sitter enabled modes that define 'sentence' in -'treesit-thing-settings' now set 'forward-sentence-function' to call -'treesit-forward-sentence'. - -** Functions and variables to move by program sexps - -+++ -*** New function 'treesit-forward-sexp'. -Tree-sitter conditionally sets 'forward-sexp-function' for major modes -that have defined 'sexp' in 'treesit-thing-settings' to enable -sexp-related motion commands. - ---- -** New user option 'native-comp-async-warnings-errors-kind'. -It allows control of what kinds of warnings and errors from asynchronous -native compilation are reported to the parent Emacs process. The -default is to report all errors and only important warnings. If you -were used to customizing 'native-comp-async-report-warnings-errors' to -nil or 'silent', we suggest that you now leave it at its default value, -and see if you get only warnings that matter. - -** Function 'declare' forms - -+++ -*** New 'ftype' function declaration. -The declaration '(ftype TYPE)' specifies the type of a function. -Example: - - (defun hello (x y) - (declare (ftype (function (integer boolean) string))) - ...) - -specifies that the function takes two arguments, an integer and a -boolean, and returns a string. If the compilation happens with -'compilation-safety' set to zero, this information can be used by the -native compiler to produce better code, but specifying an incorrect type -may lead to Emacs crashing. See the Info node "(elisp) Declare Form" -for further information. - -+++ -*** New 'important-return-value' function declaration and property. -The declaration '(important-return-value t)' sets the -'important-return-value' property which indicates that the function -return value should probably not be thrown away implicitly. - -+++ -** New functions 'file-user-uid' and 'file-group-gid'. -These functions are like 'user-uid' and 'group-gid', respectively, but -are aware of file name handlers, so they will return the remote UID or -GID for remote files (or -1 if the connection has no associated user). - -+++ -** 'treesit-font-lock-rules' now accepts additional global keywords. -When supplied with ':default-language LANGUAGE', rules after it will -default to use 'LANGUAGE'. - ---- -** New optional argument to 'modify-dir-local-variable'. -A 5th argument, optional, has been added to -'modify-dir-local-variable'. It can be used to specify which -dir-locals file to modify. - -** Connection local variables - -+++ -*** New macros 'connection-local-p' and 'connection-local-value'. -The former macro returns non-nil if a variable has a connection-local -binding. The latter macro returns the connection-local value of a -variable if any, or its current value. - -** Hash tables - -+++ -*** ':rehash-size' and ':rehash-threshold' args no longer have any effect. -These keyword arguments are now ignored by 'make-hash-table'. Emacs -manages the memory for all hash table objects in the same way. -The functions 'hash-table-rehash-size' and 'hash-table-rehash-threshold' -remain for compatibility but now always return the old default values. - -+++ -*** The printed representation has been shrunk and simplified. -The 'test' parameter is omitted if it is 'eql' (the default), as is -'data' if empty. 'rehash-size', 'rehash-threshold' and 'size' are -always omitted, and ignored if present when the object is read back in. - -** Obarrays - -+++ -*** New obarray type. -Obarrays are now represented by an opaque type instead of using vectors. -They are created by 'obarray-make' and manage their internal storage -automatically, which means that the size parameter to 'obarray-make' can -safely be omitted. That is, they do not become slower as they fill up. - -The old vector representation is still accepted by functions operating -on obarrays, but 'obarrayp' only returns t for obarray objects. -'type-of' now returns 'obarray' for obarray objects. - -Old code which (incorrectly) created "obarrays" as Lisp vectors filled -with something other than 0, as in '(make-vector N nil)', will no longer -work, and should be rewritten to use 'obarray-make'. Alternatively, you -can fill the vector with 0. - -+++ -*** New function 'obarray-clear' removes all symbols from an obarray. - ---- -*** 'obarray-size' and 'obarray-default-size' are now obsolete. -They pertained to the internal storage size which is now irrelevant. - -+++ -** 'treesit-install-language-grammar' can handle local directory instead of URL. -It is now possible to pass a directory of a local repository as URL -inside 'treesit-language-source-alist', so that calling -'treesit-install-language-grammar' would avoid cloning the repository. -It may be useful, for example, for the purposes of bisecting a -treesitter grammar. - -+++ -** New buffer-local variable 'tabulated-list-groups'. -It controls display and separate sorting of groups of entries. - -+++ -** New variable 'revert-buffer-restore-functions'. -It helps to preserve various states after reverting the buffer. - ---- -** New text property 'context-menu-functions'. -Like the variable with the same name, it adds menus from the list that -is the value of the property to context menus shown when clicking on the -text which as this property. - ---- -** Detecting the end of an iteration of a keyboard macro. -'read-event', 'read-char', and 'read-char-exclusive' no longer return -1 -when called at the end of an iteration of the execution of a keyboard -macro. Instead, they will transparently continue reading available input -(e.g., from the keyboard). If you need to detect the end of a macro -iteration, check the following condition before calling one of the -aforementioned functions: - - (and (arrayp executing-kbd-macro) - (>= executing-kbd-macro-index (length executing-kbd-macro))) - -+++ -** 'vtable-update-object' updates an existing object with just two arguments. -It is now possible to update the representation of an object in a vtable -by calling 'vtable-update-object' with just the vtable and the object as -arguments. (Previously, the OLD-OBJECT argument was required which, in -this case, would mean repeating the object in the argument list.) When -replacing an object with a different one, passing both the new and old -objects is still necessary. - -** 'vtable-insert-object' can insert "before" or at an index. -The signature of 'vtable-insert-object' has changed and is now: - - (vtable-insert-object TABLE OBJECT &optional LOCATION BEFORE) - -LOCATION corresponds to the old AFTER-OBJECT argument; if BEFORE is -non-nil, the new object is inserted before the LOCATION object, making -it possible to insert a new object at the top of the table. (Before, -this was not possible.) In addition, LOCATION can be an integer, a -(zero-based) index into the table at which the new object is inserted -(BEFORE is ignored in this case). - -+++ -** New function 'sqlite-execute-batch'. -This function lets the user execute multiple SQL statements in one go. -It is useful, for example, when a Lisp program needs to evaluate an -entire SQL file. - -** JSON - ---- -*** The parser keeps duplicated object keys in alist and plist output. -A JSON object such as '{"a":1,"a":2}' will now be translated into the -Lisp values '((a . 1) (a . 2))' or '(:a 1 :a 2)' if alist or plist -object types are requested. - ---- -*** The parser sometimes signals different types of errors. -It will now signal 'json-utf8-decode-error' for inputs that are not -correctly UTF-8 encoded. - ---- -*** The parser and encoder now accept arbitrarily large integers. -Previously, they were limited to the range of signed 64-bit integers. - -** New tree-sitter functions and variables for defining and using "things" - -+++ -*** New variable 'treesit-thing-settings'. -It allows modes to define "things" like 'defun', 'text', 'sexp', and -'sentence' for navigation commands and tree-traversal functions. - -+++ -*** New functions for navigating "things". -There are new navigation functions 'treesit-thing-prev', -'treesit-thing-next', 'treesit-navigate-thing', -'treesit-beginning-of-thing', and 'treesit-end-of-thing'. - -+++ -*** New functions 'treesit-thing-at', 'treesit-thing-at-point'. - -+++ -*** Tree-traversing functions. -The functions 'treesit-search-subtree', 'treesit-search-forward', -'treesit-search-forward-goto', and 'treesit-induce-sparse-tree' now -accept more kinds of predicates. Lisp programs can now use thing -symbols (defined in 'treesit-thing-settings') and any thing definitions -for the predicate argument. - -** Other tree-sitter function and variable changes - -+++ -*** 'treesit-parser-list' now takes additional optional arguments. -The additional arguments are LANGUAGE and TAG. If LANGUAGE is given, -only return parsers for that language. If TAG is given, only return -parsers with that tag. Note that passing nil as tag doesn't mean return -all parsers, but rather "all parsers with no tags". - -+++ -*** New variable 'treesit-primary-parser'. -This variable should be set by multi-langauge major modes before calling -'treesit-major-mode-setup', in order for tree-sitter integration -functionalities to operate correctly. +* Lisp Changes in Emacs 31.1 -* Changes in Emacs 30.1 on Non-Free Operating Systems - -** MS-Windows - -+++ -*** You can now opt out of following MS-Windows' Dark mode. -By default, Emacs on MS-Windows follows the system's Dark mode for its -title bars' and scroll bars' appearance. If the new user option -'w32-follow-system-dark-mode' is customized to the nil value, Emacs -will disregard the system's Dark mode and will always use the default -Light mode. - ---- -*** You can now use Image-Dired even if the 'convert' program is not installed. -If you don't have GraphicsMagick or ImageMagick installed, and thus the -'gm convert'/'convert' program is not available, Emacs on MS-Windows -will now use its own function 'w32image-create-thumbnail' to create -thumbnail images and show them in the thumbnail buffer. Unlike with -using 'convert', this fallback method is synchronous, so Emacs will wait -until all the thumbnails are created and displayed, before showing them. +* Changes in Emacs 31.1 on Non-Free Operating Systems --- -*** Emacs on MS-Windows now supports the ':stipple' face attribute. +** Process execution has been optimized on Android. +The run-time performance of subprocesses on recent Android releases +where a userspace executable loader is required has been optimized on +systems featuring Linux 3.5.0 and above. ---------------------------------------------------------------------- diff --git a/etc/NEWS.30 b/etc/NEWS.30 new file mode 100644 index 00000000000..31d69ddabab --- /dev/null +++ b/etc/NEWS.30 @@ -0,0 +1,3145 @@ +GNU Emacs NEWS -- history of user-visible changes. + +Copyright (C) 2022-2024 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 30. + +See file HISTORY for a list of GNU Emacs versions and release dates. +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' +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 30.1 + +--- +** Native compilation is now enabled by default. +'configure' will enable the Emacs Lisp native compiler, so long as +libgccjit is present and functional on the system. To disable native +compilation, configure Emacs with the option: + + ./configure --with-native-compilation=no + ++++ +** Emacs has been ported to the Android operating system. +This requires Emacs to be compiled on another computer. The Android +NDK, SDK, and a suitable Java compiler must also be installed. + +See the file "java/INSTALL" for more details. + +--- +** Native JSON support is now always available; libjansson is no longer used. +No external library is required. The '--with-json' configure option has +been removed. 'json-available-p' now always returns non-nil and is only +kept for compatibility. + +--- +** Emacs now defaults to the ossaudio library for sound on NetBSD and OpenBSD. +Previously, configure used ALSA libraries if installed on the system +when configured '--with-sound=yes' (which is the default), with fallback +to libossaudio. The libossaudio library included with the base system +is now used even if ALSA is found to avoid relying on external packages +and to resolve potential incompatibilities between GNU/Linux and *BSD +versions of ALSA. Use '--with-sound=alsa' to build with ALSA on these +operating systems instead. + + +* Startup Changes in Emacs 30.1 + +--- +** On GNU/Linux, Emacs is now the default application for 'org-protocol'. +Org mode provides a way to quickly capture bookmarks, notes, and links +using 'emacsclient': + + emacsclient "org-protocol://store-link?url=URL&title=TITLE" + +Previously, users had to manually configure their GNU/Linux desktop +environment to open 'org-protocol' links in Emacs. These links should +now open in Emacs automatically, as the "emacsclient.desktop" file now +arranges for Emacs to be the default application for the 'org-protocol' +URI scheme. See the Org mode manual, Info node "(org) Protocols" for +more details. + ++++ +** New variable lets Lisp code read emacsclient arguments. +When '--eval' is passed to emacsclient and Emacs is evaluating each +argument, the new variable 'server-eval-args-left' is set to those +arguments not yet evaluated. It can be used by Lisp code to 'pop' +arguments and process them by the function called in the '--eval' +expression, which is useful when those arguments contain arbitrary +characters that otherwise might require elaborate and error-prone +escaping (to protect them from the shell). + + +* Incompatible Changes in Emacs 30.1 + +--- +** Tree-Sitter modes are now declared as submodes of the non-TS modes. +In order to help the use of those Tree-Sitter modes, they are now +declared to have the corresponding non-Tree-Sitter mode as an +additional parent. +This way, things like ".dir-locals.el" settings, and YASnippet +collections of snippets automatically apply to the new Tree-Sitter modes. + +Note that those modes still do not inherit from the non-TS mode, so +configuration settings installed via mode hooks are not affected. + +--- +** Mouse wheel events should now always be 'wheel-up/down/left/right'. +At those places where the old 'mouse-4/5/6/7' events could still occur +(i.e., X11 input in the absence of XInput2, and 'xterm-mouse-mode'), +we remap them to the corresponding 'wheel-up/down/left/right' event, +according to the new user option 'mouse-wheel-buttons'. +The old variables 'mouse-wheel-up-event', 'mouse-wheel-down-event', +'mouse-wheel-left-event', and 'mouse-wheel-right-event' are thereby +obsolete. + ++++ +** 'completion-auto-help' now affects 'icomplete-in-buffer'. +Previously, 'completion-auto-help' mostly affected only minibuffer +completion. Now, if 'completion-auto-help' has the value 'lazy', then +Icomplete's in-buffer display of possible completions will only appear +after the 'completion-at-point' command has been invoked twice, and if +'completion-auto-help' is nil, then Icomplete's in-buffer display is +completely suppressed. Thus, if you use 'icomplete-in-buffer', ensure +'completion-auto-help' is not customized to 'lazy' or nil. + ++++ +** The "*Completions*" buffer now always accompanies 'icomplete-in-buffer'. +Previously, it was not consistent whether the "*Completions*" buffer would +appear when using 'icomplete-in-buffer'. Now the "*Completions*" buffer +and Icomplete's in-buffer display of possible completions always +appear together. If you would prefer to see only Icomplete's +in-buffer display, and not the "*Completions*" buffer, you can add this +to your init file: + + (advice-add 'completion-at-point :after #'minibuffer-hide-completions) + +--- +** The default process filter was rewritten in native code. +The round-trip through the Lisp function +'internal-default-process-filter' is skipped when the process filter is +the default one. It is reimplemented in native code, reducing GC churn. +To undo this change, set 'fast-read-process-output' to nil. + ++++ +** The Network Security Manager now warns about 3DES by default. +This cypher is no longer recommended owing to a major vulnerability +disclosed in 2016, and its small 112 bit key size. Emacs now warns +about its use also when 'network-security-level' is set to 'medium' +(the default). See 'network-security-protocol-checks'. + +--- +** The Network Security Manager now warns about <2048 bits in DH key exchange. +Emacs used to warn for Diffie-Hellman key exchanges with prime numbers +smaller than 1024 bits. Since more servers now support it, this +number has been bumped to 2048 bits. + ++++ +** URL now never sends user email addresses in HTTP requests. +Emacs never sent email addresses by default, but it used to be +possible to customize 'url-privacy-level' so that the users email +address was sent along in HTTP requests. This feature has now been +removed, as it was considered more dangerous than useful. RFC 9110 +(§ 10.1.2) also recommends against it. The user option +'url-personal-mail-address' is now also obsolete. + +To send an email address in the header of individual HTTP requests, +see the variable 'url-request-extra-headers'. + + +* Changes in Emacs 30.1 + +--- +** Emacs now supports Unicode Standard version 15.1. + ++++ +** Emacs now comes with Org v9.7. +See the file "etc/ORG-NEWS" for user-visible changes in Org. + ++++ +** Improved support for touchscreen devices. +On systems that understand them (at present X, Android, PGTK, and +MS-Windows), many touch screen gestures are now implemented and +translated into mouse or gesture events, and support for tapping tool +bar buttons and opening menus has been added. Countless packages, such +as Dired and Custom, have been adjusted to better understand touch +screen input. + ++++ +** Support for styled underline face attributes. +These are implemented as new values of the 'style' attribute in a face +underline specification, 'double-line', 'dots', and 'dashes', and are +available on GUI systems. If your terminal's termcap or terminfo +database entry defines the 'Su' or 'Smulx' capability, Emacs will also +emit the prescribed escape sequence to render faces with such styles on +TTY frames. + +--- +** Support for underline colors on TTY frames. +Colors specified in the underline face will now also be displayed on TTY +frames on terminals that support the 'Su' or 'Smulx' capabilities. + ++++ +** Modeline elements can now be right-aligned. +Anything following the symbol 'mode-line-format-right-align' in +'mode-line-format' will be right-aligned. Exactly where it is +right-aligned to is controlled by the new user option +'mode-line-right-align-edge'. + +--- +** 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. + +--- +** 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-p' returns nil or 'icon' for it. This can happen, for +example, as part of preview for iconified frames. + ++++ +** Most file notification backends detect unmounting of a watched filesystem. +The only exception is w32notify. + ++++ +** The ':map' property of images is now recomputed when image is transformed. +Images with clickable maps now work as expected after you run commands +such as 'image-increase-size', 'image-decrease-size', 'image-rotate', +'image-flip-horizontally', and 'image-flip-vertically'. +Set the new user option 'image-recompute-map-p' to nil to prevent Emacs +from recomputing image maps. + +** Minibuffer and Completions + ++++ +*** New commands 'previous-line-completion' and 'next-line-completion'. +Bound to '<up>' and '<down>' arrow keys, respectively, they navigate +the "*Completions*" buffer vertically by lines, wrapping at the +top/bottom when 'completion-auto-wrap' is non-nil. + ++++ +*** New user option 'minibuffer-visible-completions'. +When customized to non-nil, you can use arrow keys in the minibuffer +to navigate the completions displayed in the "*Completions*" window. +Typing 'RET' selects the highlighted candidate. 'C-g' hides the +completions window. When the completions window is not visible, +then all these keys have their usual meaning in the minibuffer. +This option is supported for in-buffer completion as well. + +--- +*** Selected completion candidates are deselected on typing. +When you type at the minibuffer prompt, the current completion +candidate will be un-highlighted, and point in the "*Completions*" window +will be moved off that candidate. 'minibuffer-choose-completion' +('M-RET') will still choose a previously-selected completion +candidate, but the new command 'minibuffer-choose-completion-or-exit' +(bound to 'RET' by 'minibuffer-visible-completions') will exit with +the minibuffer contents instead. This deselection behavior can be +controlled with the new user option 'completion-auto-deselect', which +is t by default. + ++++ +*** New value 'historical' for user option 'completions-sort'. +When 'completions-sort' is set to 'historical', completion candidates +will be first sorted alphabetically, and then re-sorted by their order +in the minibuffer history, with more recent candidates appearing first. + ++++ +*** 'completion-category-overrides' supports more metadata. +The new supported completion properties are 'cycle-sort-function', +'display-sort-function', 'annotation-function', 'affixation-function', +and 'group-function'. You can now customize them for any category in +'completion-category-overrides' that will override the properties +defined in completion metadata. + ++++ +*** 'completion-extra-properties' supports more metadata. +The new supported completion properties are 'category', +'group-function', 'display-sort-function', and 'cycle-sort-function'. + +** Windows + ++++ +*** New command 'toggle-window-dedicated'. +This makes it easy to interactively mark a specific window as +dedicated, so it won't be reused by 'display-buffer'. This can be +useful for complicated window setups. It is bound to 'C-x w d' +globally. + ++++ +*** "d" in the mode line now indicates that the window is dedicated. +Windows have always been able to be dedicated to a specific buffer; +see 'window-dedicated-p'. Now the mode line indicates the dedicated +status of a window, with "d" appearing in the mode line if a window is +dedicated and "D" if the window is strongly dedicated. This indicator +appears before the buffer name, and after the buffer modification and +remote buffer indicators (usually "---" together). + ++++ +*** New action alist entry 'some-window' for 'display-buffer'. +It specifies which window 'display-buffer-use-some-window' should prefer. +For example, when 'display-buffer-base-action' is customized to +'(nil . ((some-window . mru)))', then a buffer will be displayed +in the same most recently used window from consecutive calls of +'display-buffer' (in a configuration with more than two windows). + ++++ +*** New action alist entry 'category' for 'display-buffer'. +If the caller of 'display-buffer' passes '(category . symbol)' +in its 'action' argument, you can match the displayed buffer +by adding '(category . symbol)' to the condition part of +'display-buffer-alist' entries. + ++++ +*** New action alist entry 'post-command-select-window' for 'display-buffer'. +It specifies whether the window of the displayed buffer should be +selected or deselected at the end of executing the current command. + ++++ +*** New variable 'window-restore-killed-buffer-windows'. +It specifies how 'set-window-configuration' and 'window-state-put' +should proceed with windows whose buffer was killed after the +corresponding configuration or state was recorded. + +--- +*** New variable 'window-point-context-set-function'. +It can be used to set a context for window point in all windows by +'window-point-context-set' before calling 'current-window-configuration' +and 'window-state-get'. Then later another new variable +'window-point-context-use-function' can be used by +'window-point-context-use' after 'set-window-configuration' and +'window-state-put' to restore positions of window points +according to the context stored in a window parameter. + ++++ +*** New functions 'set-window-cursor-type' and 'window-cursor-type'. +'set-window-cursor-type' sets a per-window cursor type, and +'window-cursor-type' queries this setting for a given window. Windows +are always created with a 'window-cursor-type' of t, which means to +consult the variable 'cursor-type' as before. + +--- +*** The user option 'display-comint-buffer-action' is now obsolete. +You can use a '(category . comint)' condition in 'display-buffer-alist' +to match buffers displayed by comint-related commands. Another +user option 'display-tex-shell-buffer-action' is obsolete too +for which you can use '(category . tex-shell)'. + +** Tool bars + ++++ +*** Tool bars can now be placed on the bottom on more systems. +The 'tool-bar-position' frame parameter can be set to 'bottom' on all +window systems other than macOS and GNUstep (Nextstep). + ++++ +*** New global minor mode 'modifier-bar-mode'. +When this minor mode is enabled, the tool bar displays buttons +representing modifier keys. Clicking on these buttons applies the +corresponding modifiers to the next input event. + ++++ +*** New user option 'tool-bar-always-show-default'. +When non-nil, the tool bar at the top of a frame does not show buffer +local customization of the tool bar. The default value is nil. + +** Tab Bars and Tab Lines + +--- +*** New user option 'tab-bar-select-restore-context'. +It uses 'window-point-context-set' to save contexts where +window points were located before switching away from the tab, +and 'window-point-context-use' to restore positions of window +points after switching back to that tab. + +--- +*** New user option 'tab-bar-select-restore-windows'. +It defines what to do with windows whose buffer was killed since the tab +was last selected. By default it displays a placeholder buffer +with the name " *Old buffer <name>*" that provides information about +the name of the killed buffer that was displayed in that window. + +--- +*** New user option 'tab-bar-tab-name-format-functions'. +It can be used to add, remove and reorder functions that change the +appearance of every tab on the tab bar. + +--- +*** New user option 'tab-line-tabs-buffer-group-function'. +It provides two choices to group tab buffers by major mode and by +project name. + +--- +*** New hook 'tab-bar-tab-post-select-functions'. + +--- +*** New keymap 'tab-bar-mode-map'. +By default it contains a keybinding 'C-TAB' to switch tabs, but only +when 'C-TAB' is not bound globally. You can unbind it if it conflicts +with 'C-TAB' in other modes. + +--- +*** New keymap 'tab-line-mode-map'. +By default it contains keybindings for switching tabs: 'C-x <left>', +'C-x <right>', 'C-x C-<left>', 'C-x C-<right>'. You can unbind them if +you want to use these keys for the commands 'previous-buffer' and +'next-buffer'. + +--- +*** Default list of tabs is changed to support a fixed order. +This means that 'tab-line-tabs-fixed-window-buffers', the new default +tabs function, is like the previous 'tab-line-tabs-window-buffers' where +both of them show only buffers that were previously displayed in the +window. But the difference is that the new function always keeps the +original order of buffers on the tab line, even after switching between +these buffers. You can drag the tabs and release at a new position +to manually reorder the buffers on the tab line. + +--- +*** Buffers on group tabs are now sorted alphabetically. +This will keep the fixed order of tabs, even after switching between +them. + +** Help + ++++ +*** New command 'help-find-source'. +Switch to a buffer visiting the source of what is being described in +"*Help*". It is bound to 'C-h 4 s' globally. + +--- +*** New user option 'describe-bindings-outline-rules'. +This user option controls outline visibility in the output buffer of +'describe-bindings' when 'describe-bindings-outline' is non-nil. + +--- +*** 'describe-function' shows the function inferred type when available. +For native compiled Lisp functions, 'describe-function' prints (after +the signature) the automatically inferred function type as well. + +--- +*** 'describe-function' now shows the type of the function object. +The text used to say things like "car is a built-in function" whereas it +now says "car is a primitive-function" where "primitive-function" is the +the name of the symbol returned by 'cl-type-of'. You can click on those +words to get information about that type. + +--- +*** 'C-h m' ('describe-mode') uses outlining by default. +Set 'describe-mode-outline' to nil to get back the old behavior. + +--- +*** 'C-h k' ('describe-key') shows Unicode name. +For keybindings which produce single characters via translation or input +methods, 'C-h k' now shows the Unicode name of the produced character in +addition to the character itself, e.g. + +'C-h k C-x 8 E' => + + € 'EURO SIGN' (translated from C-x 8 E) + +--- +*** 'C-h b' ('describe-bindings') shows Unicode names. +For keybindings which produce single characters via translation (such as +those using the 'C-x 8' or 'A-' prefix, or 'dead-acute', 'dead-grave', +etc), the Unicode names will now be shown in addition to the character +itself, i.e. + + A-! ¡ INVERTED EXCLAMATION MARK + A-$ ¤ CURRENCY SIGN + +and so on. + ++++ +*** Multi-character key echo now ends with a suggestion to use Help. +Customize 'echo-keystrokes-help' to nil to prevent that. + +** Customize + ++++ +*** New command 'customize-dirlocals'. +This command pops up a buffer to edit the settings in ".dir-locals.el". + +--- +*** New command 'customize-toggle-option'. +This command can toggle boolean options for the duration of a session. + ++++ +*** New prefix argument for modifying directory-local variables. +The commands 'add-dir-local-variable', 'delete-dir-local-variable' and +'copy-file-locals-to-dir-locals' now take an optional prefix argument, +to enter the file name where you want to modify directory-local +variables. + ++++ +*** New user option 'safe-local-variable-directories'. +This user option names directories in which Emacs will treat all +directory-local variables as safe. + ++++ +** CL Print + ++++ +*** There is a new chapter in the CL manual documenting cl-print.el. +See the Info node "(cl) Printing". + ++++ +*** You can expand the "..." truncation everywhere. +The code that allowed "..." to be expanded in the "*Backtrace*" buffer +should now work anywhere the data is generated by 'cl-print'. + ++++ +*** The 'backtrace-ellipsis' button is replaced by 'cl-print-ellipsis'. + ++++ +*** hash-tables' contents can be expanded via the ellipsis. + ++++ +*** Modes can control the expansion via 'cl-print-expand-ellipsis-function'. + ++++ +*** New setting 'raw' for 'cl-print-compiled'. +This setting causes byte-compiled functions to be printed in full by +'prin1'. A button on this output can be activated to disassemble the +function. + +** Miscellaneous + ++++ +*** New command 'kill-matching-buffers-no-ask'. +This works like 'kill-matching-buffers', but without asking for +confirmation. + ++++ +*** 'recover-file' can show diffs between auto save file and current file. +When answering the prompt with "diff" or "=", it now shows the diffs +between the auto save file and the current file. + ++++ +*** 'read-passwd' can toggle the visibility of passwords. +Use 'TAB' in the minibuffer to show or hide the password. +Alternatively, click the new show-password icon on the mode-line with +'mouse-1' to toggle the visibility of the password. + +*** 'advice-remove' is now an interactive command. +When called interactively, 'advice-remove' now prompts for an advised +function to the advice to remove. + +--- +*** New user option 'uniquify-dirname-transform'. +This can be used to customize how buffer names are uniquified, by +making arbitrary transforms on the buffer's directory name (whose +components are used to uniquify buffer names when they clash). You +can use this to distinguish between buffers visiting files with the +same base name that belong to different projects by using the provided +transform function 'project-uniquify-dirname-transform'. + ++++ +*** New user option 'remote-file-name-inhibit-delete-by-moving-to-trash'. +When non-nil, this option suppresses moving remote files to the local +trash when deleting. Default is nil. + +--- +*** New user option 'remote-file-name-inhibit-auto-save'. +If this user option is non-nil, 'auto-save-mode' will not auto-save +remote buffers. The default is nil. + ++++ +*** New user option 'remote-file-name-access-timeout'. +If a positive number, this option limits the call of 'access-file' +for remote files to that number of seconds. Default is nil. + ++++ +*** New user option 'yes-or-no-prompt'. +This allows the user to customize the prompt that is appended by +'yes-or-no-p' when asking questions. The default value is +"(yes or no) ". + +--- +*** New user option 'menu-bar-close-window'. +When non-nil, selecting "Close" from the "File" menu or clicking +"Close" in the tool bar will result in the current window being +deleted, if possible. The default is nil, and these gestures kill the +buffer shown in the current window, but don't delete the window. + +--- +*** New face 'display-time-date-and-time'. +This is used for displaying the time and date components of +'display-time-mode'. + +--- +*** New face 'appt-notification' for 'appt-display-mode-line'. +It can be used to customize the look of the appointment notification +displayed on the mode line when 'appt-display-mode-line' is non-nil. + +--- +*** New icon images for general use. +Several symbolic icons have been added to "etc/images/symbols", +including plus, minus, check-mark, star, etc. + +--- +*** Emacs now recognizes shebang lines that pass '-S'/'--split-string' to 'env'. +When visiting a script that invokes 'env -S INTERPRETER ARGS...' in +its shebang line, Emacs will now skip over 'env -S' and deduce the +major mode based on the interpreter after 'env -S'. + +*** 'insert-directory-program' is now a user option. +On *BSD and macOS systems, this user option now defaults to the "gls" +executable, if it exists. This should remove the need to change its +value when installing GNU coreutils using something like ports or +Homebrew. + ++++ +*** 'write-region-inhibit-fsync' now defaults to t in interactive mode. +This is the default in batch mode since Emacs 24. + +--- +*** The default value of 'read-process-output-max' was increased to 65536. + ++++ +*** 'url-gateway-broken-resolution' is now obsolete. +This option was intended for use on SunOS 4.x and Ultrix systems, +neither of which have been supported by Emacs since version 23.1. +The user option 'url-gateway-nslookup-program' and the command +'url-gateway-nslookup-host' are consequently also obsolete. + + +* Editing Changes in Emacs 30.1 + ++++ +** New minor mode 'visual-wrap-prefix-mode'. +When enabled, continuation lines displayed for a wrapped long line +will receive a 'wrap-prefix' automatically computed from the line's +surrounding context, such that continuation lines are indented on +display as if they were filled with 'M-q' or similar. Unlike 'M-q', +the indentation only happens on display, and doesn't change the buffer +text in any way. The global minor mode +'global-visual-wrap-prefix-mode' enables this minor mode in all +buffers. + +(This minor mode is the 'adaptive-wrap' ELPA package renamed and +lightly edited for inclusion in Emacs.) + ++++ +** New global minor mode 'kill-ring-deindent-mode'. +When enabled, text being saved to the kill ring will be de-indented by +the column number at its start. For example, saving the entire +function call within an indented block: + +foo () +{ + long_function_with_several_arguments (argument_1_compute (), + argument_2_compute (), + argument_3_compute ()); +} + +will save this to the kill ring: + +long_function_with_several_arguments (argument_1_compute (), + argument_2_compute (), + argument_3_compute ()) + +This omits the two columns of extra indentation that would otherwise be +copied from the second and third lines and saved to the kill ring. + +--- +** New command 'replace-regexp-as-diff'. +It reads a regexp to search for and a string to replace with, then +displays a buffer with replacements as diffs. After reviewing the +changes in the output buffer you can apply the replacements as +a patch to the current file buffer. There are also new commands +'multi-file-replace-regexp-as-diff' that shows as diffs replacements +in a list of specified files, and 'dired-do-replace-regexp-as-diff' +that shows as diffs replacements in the marked files in Dired. + ++++ +** New mode of prompting for register names and showing preview. +The new user option 'register-use-preview' can be customized to the +value t or insist to request a different user interface of prompting for +register names and previewing the registers: Emacs will require +confirmation for overwriting the value of a register, and will show +the preview of registers without delay. You can also customize this +new option to disable the preview completely. + +The default value of 'register-use-preview' preserves the behavior of +Emacs 29 and before. See the Info node "(emacs) Registers" for more +details about the new UI and its variants. + ++++ +** New advanced macro counter commands. +New commands have been added to implement advanced macro counter +functions. + +The commands 'C-x C-k C-r l' and 'C-x C-k C-r s' load and save the +macro counter from and to a number register, respectively. + +The commands 'C-x C-k C-r a =', 'C-x C-k C-r a <', and 'C-x C-k C-r a >' +compare the macro counter with the contents of a number register and +increment the counter by an optional prefix if the comparison succeeds. + +The commands 'C-x C-k C-q =', 'C-x C-k C-q <', and 'C-x C-k C-q >' +compare the macro counter with an optional prefix and terminate the +macro if the comparison succeeds. + ++++ +** New mode 'kmacro-menu-mode' and new command 'list-keyboard-macros'. +The new command 'list-keyboard-macros' is the keyboard-macro version +of commands like 'list-buffers' and 'list-processes', creating a listing +of the currently existing keyboards macros using the new mode +'kmacro-menu-mode'. It allows rearranging the macros in the ring, +duplicating them, deleting them, and editing their counters, formats, +and keys. + +--- +** On X, Emacs now supports input methods which perform "string conversion". +This means an input method can now ask Emacs to delete text +surrounding point and replace it with something else, as well as query +Emacs for surrounding text. If your input method allows you to "undo" +mistaken compositions, this will now work as well. + +--- +** New user option 'duplicate-region-final-position'. +It controls the placement of point and the region after duplicating a +region with 'duplicate-dwim'. + ++++ +** New user option 'mouse-prefer-closest-glyph'. +When enabled, clicking or dragging with the mouse will put the point +or start the drag in front of the buffer position corresponding to the +glyph with the closest X coordinate to the click or start of the drag. +In other words, if the mouse pointer is in the right half of a glyph, +point will be put after the buffer position corresponding to that glyph, +whereas if the mouse pointer is in the left half of a glyph, point +will be put in front the buffer position corresponding to that glyph. +By default this is disabled. + +--- +** New pre-defined values for 'electric-quote-chars'. +The available customization options for 'electric-quote-chars' have been +updated with common pairs of quotation characters, including "‘", "’", +"“", "”", "«", "»", "‹", "›", "‚", "„", "「", "」", "『", and "』". +The default is unchanged. + ++++ +** 'M-TAB' now invokes 'completion-at-point' in Text mode. +By default, Text mode no longer binds 'M-TAB' to 'ispell-complete-word'. +Instead, this mode arranges for 'completion-at-point', globally bound to +'M-TAB', to perform word completion as well. You can have Text mode +binding 'M-TAB' to 'ispell-complete-word' as it did in previous Emacs +versions, or disable Ispell word completion in Text mode altogether, by +customizing the new user option 'text-mode-ispell-word-completion'. + +** Internationalization + +--- +*** Mode-line mnemonics for some coding-systems have changed. +The mode-line mnemonic for 'utf-7' is now the lowercase 'u', to be +consistent with the other encodings of this family. + +The mode-line mnemonic for 'koi8-u' is now 'У', U+0423 CYRILLIC +CAPITAL LETTER U, to distinguish between this encoding and the +UTF-8/UTF-16 family. + +If your terminal cannot display 'У', or if you want to get the old +behavior back for any other reason, you can do that using the +'coding-system-put' function. For example, the following restores the +previous behavior of showing 'U' in the mode line for 'koi8-u': + + (coding-system-put 'koi8-u :mnemonic ?U) + +--- +*** 'vietnamese-tcvn' is now a coding system alias for 'vietnamese-vscii'. +VSCII-1 and TCVN-5712 are different names for the same character +encoding. Therefore, the duplicate coding system definition has been +dropped in favor of an alias. + +The mode-line mnemonic for 'vietnamese-vscii' and its aliases is the +lowercase letter "v". + +--- +*** Users in CJK locales can control width of some non-CJK characters. +Some characters are considered by Unicode as "ambiguous" with respect +to their display width: either "full-width" (i.e., taking 2 columns on +display) or "narrow" (taking 1 column). The actual width depends on +the fonts used for these characters by Emacs or (for text-mode frames) +by the terminal emulator. Traditionally, font sets in CJK locales +were set up so as to display these characters as full-width, and thus +Emacs modified the char-width table in those locales to follow suit. +Lately, the tendency is to display these characters as narrow. The +new user option 'cjk-ambiguous-chars-are-wide' allows users to control +whether Emacs considers these characters as full-width (the default) +or narrow (if the variable is customized to the nil value). + +This setting affects the results of 'string-width' and similar +functions in CJK locales. + +--- +*** New input methods for the Urdu, Pashto, and Sindhi languages. +These languages are spoken in Pakistan and Afghanistan. + +--- +*** New input method "english-colemak". +This input method supports the Colemak keyboard layout. + +--- +*** Additional 'C-x 8' key translations for "æ" and "Æ". +These characters can now be input with 'C-x 8 a e' and 'C-x 8 A E', +respectively, in addition to the existing translations 'C-x 8 / e' and +'C-x 8 / E'. + +--- +*** New 'C-x 8' key translations for "low" quotes "„", and "‚". +These can now be entered with 'C-x , "' and 'C-x , ''. + +--- +*** New German language 'C-x 8' key translations for quotation marks. +The characters "„", "“", and "”" can now be entered with 'C-x 8 v', +'C-x 8 b' and 'C-x 8 n'. The single versions "‚", "‘", and "’" can now +be entered with 'C-x 8 V', 'C-x 8 B' and 'C-x 8 N'. These characters +are used for the official German quoting style. Using them requires +activating German language support via 'iso-transl-set-language'. + +--- +*** "latin-prefix" and "latin-postfix" quotation marks additions. +These input methods can now produce single, double and "low" left and +right quotation marks: + + "‘", "’", "“", "”", "„", and "‚" + +by using "[", "]", and "," for "left", "right", and "low" respectively +to modify "'" and """. + +--- +*** "latin-prefix" and "latin-postfix" guillemets support. +These input methods can now produce single guillemets "‹" and "›". For +"latin-prefix" use "~~<" and "~~>", for "latin-postfix" use "<~" and +">~". Double guillemets ("«" and "»") were already supported. + +--- +*** New French language 'C-x 8' key translations for "‹" and "›". +These characters can now be entered using 'C-x 8 ~ <' and 'C-x 8 ~ >', +respectively, after activating French language support via +'iso-transl-set-language'. Double guillemets were already supported via +'C-x 8 <' and 'C-x 8 >' + +--- +*** Additional 'C-x 8' key translation for Euro "€" currency symbol. +This can now be entered using 'C-x 8 E' in addition to the existing +'C-x 8 * E' translation. + + +* Changes in Specialized Modes and Packages in Emacs 30.1 + +** Outline mode + ++++ +*** New commands to show/hide outlines by regexp. +'C-c / h' ('outline-hide-by-heading-regexp') asks for a regexp and then +hides the body lines of all outlines whose heading lines match the +regexp. 'C-c / s' ('outline-show-by-heading-regexp') does the inverse: +it shows the bodies of outlines that matched a regexp. + ++++ +*** 'outline-minor-mode' is supported in tree-sitter major modes. +It can be used in all tree-sitter major modes that set either the +variable 'treesit-simple-imenu-settings' or 'treesit-outline-predicate'. + +** Info + +--- +*** New user option 'Info-url-alist'. +This user option associates manual names with URLs. It affects the +'Info-goto-node-web' command. By default, associations for all +Emacs-included manuals are set. Further associations can be added for +arbitrary Info manuals. + +--- +*** Emacs can now display Info manuals compressed with 'lzip'. +This requires the 'lzip' program to be installed on your system. + +** GUD (Grand Unified Debugger) + ++++ +*** New user option 'gud-highlight-current-line'. +When enabled, GUD will visually emphasize the line being executed upon +pauses in the debuggee's execution, such as those occasioned by +breakpoints being hit. + ++++ +*** New command 'lldb'. +Run the LLDB debugger, analogous to the 'gud-gdb' command. + +--- +*** Variable order and truncation can now be configured in 'gdb-many-windows'. +The new user option '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'. + +By default, this user option 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'. + +If you want to get back the old behavior, set the user option to the value + + (setopt gdb-locals-table-row-config + `((type . 0) (name . 0) (value . ,gdb-locals-value-limit))) + ++++ +*** New user option 'gdb-display-io-buffer'. +If this is nil, command 'gdb' will neither create nor display a separate +buffer for the I/O of the program being debugged, but will instead +redirect the program's interaction to the GDB execution buffer. The +default is t, to preserve previous behavior. + +** Grep + ++++ +*** New user option 'grep-use-headings'. +When non-nil, the output of Grep is split into sections, one for each +file, instead of having file names prefixed to each line. It is +equivalent to the '--heading' option of some tools such as 'git grep' +and 'rg'. The headings are displayed using the new 'grep-heading' face. +The default is nil. + +** Compilation mode + +--- +*** The 'omake' matching rule is now disabled by default. +This is because it partly acts by modifying other rules which may +occasionally be surprising. It can be re-enabled by adding 'omake' to +'compilation-error-regexp-alist'. + +--- +*** Lua errors and stack traces are now recognized. +Compilation mode now recognizes Lua language errors and stack traces. +Every Lua error is recognized as a compilation error, and every Lua +stack frame is recognized as a compilation info. + +** Project + ++++ +*** New user option 'project-mode-line'. +When non-nil, display the name of the current project on the mode +line. Clicking 'mouse-1' on the project name pops up the project +menu. The default value is nil. + +--- +*** New user option 'project-file-history-behavior'. +Customizing it to 'relativize' makes commands like 'project-find-file' +and 'project-find-dir' display previous history entries relative to +the current project. + +-- +*** New user option 'project-key-prompt-style'. +The look of the key prompt in the project switcher has been changed +slightly. To get the previous one, set this option to 'brackets'. + +--- +*** Function 'project-try-vc' tries harder to find the responsible VCS. +When 'project-vc-extra-root-markers' is non-nil, and causes a +subdirectory project to be detected which is not a VCS root, Project now +additionally traverses the parent directories until a VCS root is found +(if any), so that the ignore rules for that repository are used, and +the file listing's performance is still optimized. + ++++ +*** New commands 'project-any-command' and 'project-prefix-or-any-command'. +The former is now bound to 'C-x p o' by default. +The latter is designed primarily for use as a value of +'project-switch-commands'. If instead of a short menu you prefer to +have access to all keys defined inside 'project-prefix-map', as well +as global bindings (to run other commands inside the project root), +you can add this to your init script: + + (setopt project-switch-commands #'project-prefix-or-any-command) + +--- +*** New variable 'project-files-relative-names'. +If it is non-nil, 'project-files' can return file names relative to the +project root. Project backends can use this to improve the performance +of their 'project-files' implementation. + +** VC + +--- +*** Log-Edit buffers now display a tool bar. +This tool bar contains items for committing log entries and editing or +generating log entries, among other editing operations. + +--- +*** 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. + +--- +*** New value 'no-backend' for user option 'vc-display-status'. +With this value only the revision number is displayed on the mode-line. + +--- +*** Obsolete command 'vc-switch-backend' re-added as 'vc-change-backend'. +The command was previously obsoleted and unbound in Emacs 28. + +--- +*** Support for viewing VC change history across renames. +When a fileset's VC change history ends at a rename, 'C-x v l' now +prints the old name(s) and shows a button which jumps to the history of +the files under the old names. This feature is supported for Git and +Hg. Naturally, 'vc-git-print-log-follow' should be nil for this to work +(or '--follow' should not be in 'vc-hg-log-switches', in Hg's case). +Unlike when the '--follow' switch is used, commands to see the diff of +the old revision ('d'), to check out an old file version ('f') or to +annotate it ('a'), also work on revisions which precede renames. + +--- +*** 'vc-annotate' now abbreviates the Git revision in the buffer name. +When using the Git backend, 'vc-annotate' will use an abbreviated +revision identifier in its buffer name. To restore the previous +behavior, set user option 'vc-annotate-use-short-revision' to nil. + +--- +*** New user option 'vc-git-file-name-changes-switches'. +It allows tweaking the thresholds for rename and copy detection. + +** Diff mode + +--- +*** New user option 'diff-refine-nonmodified'. +When this is non-nil, 'diff-refine-hunk' will highlight lines that were +added or removed in their entirety (as opposed to modified lines, where +some parts of the line were modified), using the same faces as for +highlighting the words added and removed within modified lines. The +default value is nil. + ++++ +*** 'diff-ignore-whitespace-hunk' can now be applied to all hunks. +When called with a non-nil prefix argument, +'diff-ignore-whitespace-hunk' now iterates over all the hunks in the +current diff, regenerating them without whitespace changes. + ++++ +*** New user option 'diff-ignore-whitespace-switches'. +This allows changing which type of whitespace changes are ignored when +regenerating hunks with 'diff-ignore-whitespace-hunk'. Defaults to +the previously hard-coded "-b". + ++++ +*** New command 'diff-apply-buffer' bound to 'C-c RET a'. +It applies the diff in the entire diff buffer and +saves all modified file buffers. + +** Dired + +--- +*** New user option 'dired-movement-style'. +When non-nil, make 'dired-next-line', 'dired-previous-line', +'dired-next-dirline', 'dired-prev-dirline' skip empty lines. +It also controls how to move point when encountering a boundary +(e.g., if every line is visible, invoking 'dired-next-line' at +the last line will move to the first line). The default is nil. + +--- +*** New user option 'dired-filename-display-length'. +It is an integer representing the maximum display length of file names. +The middle part of a file name whose length exceeds the restriction is +hidden and an ellipsis is displayed instead. A value of 'window' +means using the right edge of window as the display restriction. The +default is nil. + +--- +*** New user option 'shell-command-guess-functions'. +It defines how to populate a list of commands available +for 'M-!', 'M-&', '!', '&' and the context menu "Open With" +based on marked files in Dired. Possible backends are +'dired-guess-default', MIME types, XDG configuration +and a universal command such as "open" or "start" +that delegates to the OS. + ++++ +*** New command 'dired-do-open'. +This command is bound to 'E' (mnemonics "External"). Also it can be +used by clicking "Open" in the context menu; it "opens" the marked or +clicked on files according to the OS conventions. For example, on +systems supporting XDG, this runs 'xdg-open' on the files. + ++++ +*** New variable 'dired-guess-shell-alist-optional'. +It contains commands for external viewers and players for various media +formats, moved to this list from 'dired-guess-shell-alist-default'. + +--- +*** The default value of 'dired-omit-size-limit' was increased. +After performance improvements to omitting in large directories, the new +default value is 300k, up from 100k. This means 'dired-omit-mode' will +omit files in directories whose directory listing is up to 300 kilobytes +in size. + ++++ +*** 'dired-listing-switches' handles connection-local values if exist. +This allows to customize different switches for different remote machines. + +** Ediff + +--- +*** New user option 'ediff-floating-control-frame'. +If non-nil, try making the control frame be floating rather than tiled. + +Many X tiling window managers make the Ediff control frame a tiled +window equal in size to the main Emacs frame, which works poorly. +This option is useful to set if you use such a window manager. + +** Buffer Selection + +--- +*** 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 + ++++ +*** You can now run Eshell scripts in batch mode. +By adding the following interpreter directive to an Eshell script, you +can make it executable like other shell scripts: + + #!/usr/bin/env -S emacs --batch -f eshell-batch-file + ++++ +*** New builtin Eshell command 'compile'. +This command runs another command, sending its output to a compilation +buffer when the command would output interactively. This can be useful +when defining aliases so that they produce a compilation buffer when +appropriate, but still allow piping the output elsewhere if desired. +For more information, see the "(eshell) Built-ins" node in the Eshell +manual. + ++++ +*** Eshell's 'env' command now supports running commands. +Like in many other shells, Eshell's 'env' command now lets you run a +command passed as arguments to 'env'. If you pass any initial +arguments of the form 'VAR=VALUE', 'env' will first set 'VAR' to +'VALUE' before running the command. + +--- +*** Eshell's 'umask' command now supports setting the mask symbolically. +Now, you can pass an argument like "u+w,o-r" to Eshell's 'umask' +command, which will give write permission for owners of newly-created +files and deny read permission for users who are not members of the +file's group. See the Info node "(coreutils) File permissions" for +more information on this notation. + +--- +*** Performance improvements for interactive output in Eshell. +Interactive output in Eshell should now be significantly faster, +especially for commands that can print large amounts of output +(e.g. "cat"). For external commands, Eshell saves time by only looking +for password prompts in the last 256 characters of each block of output. +To restore the previous behavior when checking for password prompts, set +'eshell-password-prompt-max-length' to 'most-positive-fixnum'. + +--- +*** Eshell built-in commands can now display progress. +Eshell built-in commands like "cat" and "ls" now update the display +periodically while running to show their progress. + ++++ +*** New special reference type '#<marker POSITION BUFFER>'. +This special reference type returns a marker at 'POSITION' in +'BUFFER'. You can insert it by typing or using the new interactive +command 'eshell-insert-marker'. You can also insert special +references of any type using the new interactive command +'eshell-insert-special-reference'. See the "(eshell) Arguments" node +in the Eshell manual for more details. + ++++ +*** 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. + ++++ +*** You can now splice Eshell globs in-place into argument lists. +By setting 'eshell-glob-splice-results' to a non-nil value, Eshell +will expand glob results in-place as if you had typed each matching +file name individually. For more information, see the "(eshell) +Globbing" node in the Eshell manual. + ++++ +*** Eshell now supports negative numbers and ranges for indices. +Now, you can retrieve the last element of a list with '$my-list[-1]' +or get a sublist of elements 2 through 4 with '$my-list[2..5]'. For +more information, see the "(eshell) Dollars Expansion" node in the +Eshell manual. + ++++ +*** Eshell commands can now be explicitly-remote (or local). +By prefixing a command name in Eshell with a remote identifier, like +"/ssh:user@remote:whoami", you can now run commands on a particular +host no matter your current directory. Likewise, you can run a +command on your local system no matter your current directory via +"/local:whoami". For more information, see the "(eshell) Remote Access" +node in the Eshell manual. + ++++ +*** Eshell's '$UID' and '$GID' variables are now connection-aware. +Now, when expanding '$UID' or '$GID' in a remote directory, the value +is the user or group ID associated with the remote connection. + +--- +*** Eshell now uses 'field' properties in its output. +In particular, this means that pressing the '<home>' key moves the +point to the beginning of your input, not the beginning of the whole +line. If you want to go back to the old behavior, add something like +this to your configuration: + + (keymap-set eshell-mode-map "<home>" #'eshell-bol-ignoring-prompt) + +This also means you no longer need to adjust 'eshell-prompt-regexp' +when customizing your Eshell prompt. + +--- +*** You can now properly unload Eshell. +Calling '(unload-feature 'eshell)' no longer signals an error, and now +correctly unloads Eshell and all of its modules. + ++++ +*** 'eshell-read-aliases-list' is now an interactive command. +After manually editing 'eshell-aliases-file', you can use this command +to load the edited aliases. + ++++ +*** 'rgrep' is now a builtin Eshell command. +Running 'rgrep' in Eshell now uses the Emacs grep facility instead of +calling external rgrep. + ++++ +*** If a command exits abnormally, the Eshell prompt now shows its exit code. + ++++ +*** New user option 'eshell-history-append'. +If non-nil, each Eshell session will save history by appending new +entries of that session to the history file rather than overwriting +the file with the whole history of the session. The default is nil. + +** Pcomplete + +--- +*** New user option 'pcomplete-remote-file-ignore'. +When this option is non-nil, remote file names are not completed by +Pcomplete. Packages, like 'shell-mode', could set this in order to +suppress remote file name completion at all. + +--- +*** Completion for the 'doas' command has been added. +Command completion for 'doas' in Eshell and Shell mode will now work. + +** Shell mode + ++++ +*** New user option 'shell-get-old-input-include-continuation-lines'. +When this user option is non-nil, 'shell-get-old-input' ('C-RET') +includes multiple shell "\" continuation lines from command output. +Default is nil. + ++++ +*** New user option 'shell-history-file-name'. +When this user option is set to t, 'shell-mode' does not read the shell +history file. Setting this user option to a string specifies the name +of the shell history file to be read. A nil value triggers reading the +environment variable 'HISTFILE'. + +In a 'shell' buffer, this user option is connection-local. + +--- +*** Performance improvements for interactive output. +Interactive output in Shell mode now scans more selectively for password +prompts by only examining the last 256 characters of each block of +output, reducing the time spent when printing large amounts of output. +To restore the old behavior, set 'comint-password-prompt-max-length' to +'most-positive-fixnum'. + +** Prog mode + ++++ +*** New command 'prog-fill-reindent-defun'. +This command either fills a single paragraph in a defun, such as a +docstring, or a comment, or (re)indents the surrounding defun if point +is not in a comment or a string. By default, it is bound to 'M-q' in +'prog-mode' and all its descendants. + +** Imenu + ++++ +*** New user option 'imenu-flatten'. +It controls whether to flatten the list of sections in an imenu, and +how to display the sections in the flattened list. + ++++ +*** The sort order of Imenu completions can now be customized. +You can customize the user option 'completion-category-overrides' +and set 'display-sort-function' for the category 'imenu'. + +** Which Function mode + ++++ +*** Which Function mode can now display function names on the header line. +The new user option 'which-func-display' allows choosing where the +function name is displayed. The default is 'mode' to display in the +mode line. 'header' will display in the header line; +'mode-and-header' displays in both the header line and mode line. + ++++ +*** New user option 'which-func-update-delay'. +This replaces the user option 'idle-update-delay', which was previously +used to control the delay before 'which-function-mode' updated its +display. The user option 'idle-update-delay', which was only used by +Which Function mode, is now obsolete. + +** Tramp + ++++ +*** Tramp methods can be optional. +An optional connection method is not enabled by default. The user must +enable it explicitly by the 'tramp-enable-method' command. The existing +methods "fcp", "krlogin", " ksu" and "nc" are optional now. + ++++ +*** New optional connection method "androidsu". +This provides access to system files with elevated privileges granted by +the idiosyncratic 'su' implementations and system utilities customary on +Android. + ++++ +*** New optional connection method "run0". +This connection method is similar to "sudo", but it uses the +'systemd-run' program internally. + ++++ +*** New connection methods "dockercp" and "podmancp". +These are the external methods counterparts of "docker" and "podman". + ++++ +*** New optional connection methods for containers. +There are new optional connection methods "toolbox", "distrobox", +"flatpak", "apptainer" and "nspawn". They allow accessing system +containers provided by Toolbox or Distrobox, sandboxes provided by +Flatpak, instances managed by Apptainer, or accessing systemd-based +light-weight containers.. + ++++ +*** Connection method "kubernetes" supports now optional container name. +The host name for Kubernetes connections can be of kind [CONTAINER.]POD, +in order to specify a dedicated container. If there is just the pod +name, the first container in the pod is taken. The new user options +'tramp-kubernetes-context' and 'tramp-kubernetes-namespace' allow +accessing pods with different context or namespace but the default one. + ++++ +*** Rename 'tramp-use-ssh-controlmaster-options' to 'tramp-use-connection-share'. +The old name still exists as obsolete variable alias. This user +option controls now connection sharing for both ssh-based and +plink-based methods. It allows the values t, nil, and 'suppress'. +The latter suppresses also "ControlMaster" settings in the user's +"~/.ssh/config" file, or connection share configuration in PuTTY +sessions, respectively. + ++++ +*** New command 'tramp-cleanup-some-buffers'. +It kills only a subset of opened remote buffers, subject to the user +option 'tramp-cleanup-some-buffers-hook'. + ++++ +*** New command 'inhibit-remote-files'. +This command disables the handling of file names with the special +remote file name syntax. It should be applied only when remote files +won't be used in this Emacs instance. It provides a slightly improved +performance of file name handling in Emacs. + ++++ +*** New macro 'without-remote-files'. +This macro could wrap code which handles local files only. Due to the +temporary deactivation of remote files, it results in a slightly +improved performance of file name handling in Emacs. + ++++ +*** New user option 'tramp-completion-multi-hop-methods'. +It contains a list of connection methods for which completion should +be attempted at the end of a multi-hop chain. This allows completion +candidates to include a list of, for example, containers running on a +remote docker host. + ++++ +*** New command 'tramp-revert-buffer-with-sudo'. +It reverts the current buffer to visit with "sudo" permissions. The +buffer must either visit a file, or it must run 'dired-mode'. Another +method but "sudo" can be configured with user option +'tramp-file-name-with-method'. + ++++ +*** Direct asynchronous processes are indicated by a connection-local variable. +If direct asynchronous processes shall be used, set the connection-local +variable 'tramp-direct-async-process' to a non-nil value. This has been +changed, in previous Emacs versions this was indicated by the now +deprecated connection property "direct-async-process". See the Tramp +manual "(tramp) Improving performance of asynchronous remote processes". + +--- +*** Direct asynchronous processes use 'tramp-remote-path'. +When a direct asynchronous process is invoked, it uses 'tramp-remote-path' +for setting the remote 'PATH' environment variable. + +** EWW + +--- +*** New mouse bindings in EWW buffers. +Certain form elements that were displayed as buttons, yet could only be +activated by keyboard input, are now operable using 'mouse-2'. With +"Submit" buttons, this triggers submission of the form, while clicks on +other classes of buttons either toggle their values or prompt for user +input, as the case may be. + +--- +*** EWW text input fields and areas are now fields. +In consequence, movement commands and OS input method features now +recognize and confine their activities to the text input field around +point. See also the Info node "(elisp) Fields". + ++++ +*** 'eww-open-file' can now display the file in a new buffer. +By default, the command reuses the "*eww*" buffer, but if called with +the new argument NEW-BUFFER non-nil, it will use a new buffer instead. +Interactively, invoke 'eww-open-file' with a prefix argument to +activate this behavior. + +--- +*** 'eww' URL or keyword prompt now has tab completion. +The interactive minibuffer prompt when invoking 'eww' now has support +for tab completion. + ++++ +*** 'eww' URL and keyword prompt now completes suggested URIs and bookmarks. +The interactive minibuffer prompt when invoking 'eww' now provides +completions from 'eww-suggest-uris'. 'eww-suggest-uris' now includes +bookmark URIs. + ++++ +*** New command 'eww-copy-alternate-url'. +It copies an alternate link on the page currently visited in EWW into +the kill ring. Alternate links are optional metadata that HTML pages +use for linking to their alternative representations, such as +translated versions or associated RSS feeds. + ++++ +*** 'eww-open-in-new-buffer' supports the prefix argument. +When invoked with the prefix argument ('C-u'), +'eww-open-in-new-buffer' will not make the new buffer the current one. +This is useful for continuing reading the URL in the current buffer +when the new URL is fetched. + +--- +*** History navigation in EWW now behaves as in other browsers. +Previously, when navigating back and forward through page history, EWW +would add a duplicate entry to the end of the history list each time. +This made it impossible to navigate to the "end" of the history list. +Now, navigating through history in EWW simply changes your position in +the history list, allowing you to reach the end as expected. In +addition, when browsing to a new page from a "historical" one (i.e., a +page loaded by navigating back through history), EWW deletes the history +entries newer than the current page. To change the behavior when +browsing from "historical" pages, you can customize +'eww-before-browse-history-function'. + ++++ +*** 'eww-readable' now toggles display of the readable parts of a web page. +When called interactively, 'eww-readable' toggles whether to display +only the readable parts of a page or the full page. With a positive +prefix argument, it always displays the readable parts, and with a zero +or negative prefix, it always displays the full page. + ++++ +*** New user option 'eww-readable-urls'. +This is a list of regular expressions matching the URLs where EWW should +display only the readable parts by default. For more details, see +"(eww) Basics" in the EWW manual. + +--- +*** New user option 'eww-readable-adds-to-history'. +When non-nil (the default), calling 'eww-readable' adds a new entry to +the EWW page history. + +** Go-ts mode + ++++ +*** New command 'go-ts-mode-docstring'. +This command adds a docstring comment to the current defun. If a +comment already exists, point is only moved to the comment. It is +bound to 'C-c C-d' in 'go-ts-mode'. + +** Man mode + ++++ +*** New user option 'Man-prefer-synchronous-call'. +When this is non-nil, run the 'man' command synchronously rather than +asynchronously (which is the default behavior). + ++++ +*** New user option 'Man-support-remote-systems'. +This option controls whether the man page is formatted on the remote +system when the current buffer's default-directory is remote. You can +invoke the 'man' command with a prefix argument to countermand the +value of this option for the current invocation of 'man'. + +** DocView + +--- +*** New face 'doc-view-svg-face'. +This replaces 'doc-view-svg-foreground' and 'doc-view-svg-background'. +If you don't like the colors produced by the default definition of +this new face when DocView displays documents, customize this face to +restore the colors you were used to, or to get colors more to your +liking. + +--- +*** DocView buffers now display a new tool bar. +This tool bar contains options for searching and navigating within the +document, replacing the incompatible items for incremental search and +editing within the default tool bar displayed in the past. + +** Shortdoc + ++++ +*** New function 'shortdoc-function-examples'. +This function returns examples of use of a given Emacs Lisp function +from the available shortdoc information. + ++++ +*** New function 'shortdoc-help-fns-examples-function'. +This function inserts into the current buffer examples of use of a +given Emacs Lisp function, which it gleans from the shortdoc +information. If you want 'describe-function' ('C-h f') to insert +examples of using the function into regular "*Help*" buffers, add the +following to your init file: + + (add-hook 'help-fns-describe-function-functions + #'shortdoc-help-fns-examples-function) + +** Package + +--- +*** New user option 'package-vc-register-as-project'. +When non-nil, it will automatically register every package as a +project, that you can quickly select using 'project-switch-project' +('C-x p p'). + +--- +*** New user option 'package-vc-allow-build-commands'. +Controls for which packages Emacs runs extra build commands when +installing directly from the package VCS repository. + +--- +*** New command 'package-vc-log-incoming'. +This commands displays incoming changes for a VC package without +modifying the current checkout. + +--- +*** New command to start an inferior Emacs loading only specific packages. +The new command 'package-isolate' will start a new Emacs process, as +a sub-process of Emacs where you invoke the command, in a way that +causes the new process to load only some of the installed packages. +The command prompts for the packages to activate in this +sub-process, and is intended for testing Emacs and/or the packages +in a clean environment. + +** Flymake + ++++ +*** New user option 'flymake-indicator-type'. +This user option controls which error indicator type Flymake should use +in current buffer. Depending on your preference, this can either use +fringes or margins for indicating errors. + ++++ +*** New user option 'flymake-margin-indicators-string'. +It controls, for each error type, the string and its face to display as +the margin indicator. + ++++ +*** New user option 'flymake-autoresize-margins'. +If non-nil, Flymake will resize the margins when 'flymake-mode' is +turned on or off. +Only relevant if 'flymake-indicator-type' is set to 'margins'. + ++++ +*** New user option 'flymake-margin-indicator-position'. +It controls which margin (left or right) is used for margin +indicators. + ++++ +*** New user option 'flymake-show-diagnostics-at-end-of-line'. +When non-nil, Flymake shows summarized descriptions of diagnostics at +the end of the line. Depending on your preference, this can either be +distracting and easily confused with actual code, or a significant +early aid that relieves you from moving the buffer or reaching for the +mouse to consult an error message. + +** Flyspell + ++++ +*** New user option 'flyspell-check-changes'. +When non-nil, Flyspell mode spell-checks only words that you edited; it +does not check unedited words just because you move point across them. + +--- +** JS mode. +The binding 'M-.' has been removed from the major mode keymaps in +'js-mode' and 'js-ts-mode', having it default to the global binding +which calls 'xref-find-definitions'. If the previous one worked +better for you, use 'define-key' in your init script to bind +'js-find-symbol' to that combination again. + +--- +** Json mode. +'js-json-mode' does not derive from 'js-mode' any more so as not +to confuse tools like Eglot or YASnippet into thinking that those +buffers contain Javascript code. + +** Python mode + +--- +*** New user option 'python-indent-block-paren-deeper'. +If non-nil, increase the indentation of the lines inside parens in a +header of a block when they are indented to the same level as the body +of the block: + + if (some_expression + and another_expression): + do_something() + +instead of: + + if (some_expression + and another_expression): + do_something() + +--- +*** New user option 'python-interpreter-args'. +This allows the user to specify command line arguments to the non +interactive Python interpreter specified by 'python-interpreter'. + +--- +*** New function 'python-shell-send-block'. +It sends the python block delimited by 'python-nav-beginning-of-block' +and 'python-nav-end-of-block' to the inferior Python process. + +** Inferior Python mode + +--- +*** Default value of 'python-shell-compilation-regexp-alist' is changed. +Support for Python's ExceptionGroup has been added, so in the Python +shell, the line indicating the source of an error in the error messages +from ExceptionGroup will be recognized as well. + +** Eldoc + +--- +*** 'eldoc' no longer truncates to a single line by default. +Previously, the entire docstring was not available to eldoc, which made +'eldoc-echo-area-use-multiline-p' ineffective. The old behavior may be +kept by customizing 'eldoc-echo-area-use-multiline-p'. + +--- +** Scheme mode. +Scheme mode now handles the regular expression literal '#/regexp/' that +is available in some Scheme implementations. +Also, it should now handle nested sexp-comments. + +** Use package + ++++ +*** New ':vc' keyword. +This keyword enables the user to install packages using package-vc.el. + ++++ +*** New user option 'use-package-vc-prefer-newest'. +This allows the user to always install the newest commit of a package +when using the ':vc' keyword. + +** Gnus + ++++ +*** New backend 'nnfeed'. +This allows backend developers to easily create new backends for web +feeds, as inheriting backends of 'nnfeed'. + ++++ +*** New backend 'nnatom'. +This allow users to add Atom Syndication Format feeds to Gnus as +servers. + +*** The 'nnweb-type' option 'gmane' has been removed. +The gmane.org website is, sadly, down since a number of years with no +prospect of it coming back. Therefore, it is no longer valid to set +the server variable 'nnweb-type' to 'gmane'. + +--- +*** New user option 'gnus-mode-line-logo'. +This allows the user to either disable the display of any logo or +specify which logo will be displayed as part of the +buffer-identification in the mode-line of Gnus buffers. + +** Rmail + +--- +*** New commands for reading mailing lists. +The new Rmail commands 'rmail-mailing-list-post', +'rmail-mailing-list-unsubscribe', 'rmail-mailing-list-help', and +'rmail-mailing-list-archive' allow, respectively, posting to, +unsubscribing from, requesting help about, and browsing the archives +of, the mailing list from which the current email message was +delivered. + +** Dictionary + +--- +*** New user option 'dictionary-search-interface'. +Controls how the 'dictionary-search' command prompts for and displays +dictionary definitions. Customize this user option to 'help' to have +'dictionary-search' display definitions in a "*Help*" buffer and +provide dictionary-based minibuffer completion for word selection. + +--- +*** New user option 'dictionary-read-word-prompt'. +This allows the user to customize the prompt that is used by +'dictionary-search' when asking for a word to search in the +dictionaries. + +--- +*** New user option 'dictionary-display-definition-function'. +This allows the user to customize the way in which 'dictionary-search' +displays word definitions. If non-nil, this user option should be set +to a function that displays a word definition obtained from a +dictionary server. The new function +'dictionary-display-definition-in-help-buffer' can be used to display +the definition in a "*Help*" buffer, instead of the default +"*Dictionary*" buffer. + +--- +*** New user option 'dictionary-read-word-function'. +This allows the user to customize the way in which 'dictionary-search' +prompts for a word to search in the dictionary. This user option +should be set to a function that lets the user select a word and +returns it as a string. The new function +'dictionary-completing-read-word' can be used to prompt with +completion based on dictionary matches. + +--- +*** New user option 'dictionary-read-dictionary-function'. +This allows the user to customize the way in which 'dictionary-search' +prompts for a dictionary to search in. This user option should be set +to a function that lets the user select a dictionary and returns its +name as a string. The new function +'dictionary-completing-read-dictionary' can be used to prompt with +completion based on dictionaries that the server supports. + +--- +*** The default value of 'dictionary-tooltip-dictionary' has changed. +The new default value is t, which means use the same dictionary as the +value of 'dictionary-default-dictionary'. The previous default value +was nil, which effectively disabled 'dictionary-tooltip-mode', even if +the mode was turned on. + +** Pp + ++++ +*** New 'pp-default-function' user option replaces 'pp-use-max-width'. +Its default value is 'pp-fill', a new default pretty-printing function, +which tries to obey 'fill-column'. + +--- +*** 'pp-to-string' takes an additional PP-FUNCTION argument. +This argument specifies the prettifying algorithm to use. + +--- +*** 'pp' and 'pp-to-string' now always include a terminating newline. +In the past they included a terminating newline in most cases but not all. + +** Emacs Lisp mode + +--- +*** ',@' now has 'prefix' syntax. +Previously, the '@' character, which normally has 'symbol' syntax, +would combine with a following Lisp symbol and interfere with symbol +searching. + ++++ +*** 'emacs-lisp-docstring-fill-column' now defaults to 72. +It was previously 65. The new default formats documentation strings to +fit on fewer lines without negatively impacting readability. + +** CPerl mode + +--- +*** Subroutine signatures are now supported. +CPerl mode fontifies subroutine signatures like variable declarations +which makes them visually distinct from subroutine prototypes. + +--- +*** Syntax of Perl up to version 5.40 is supported. +CPerl mode supports the new keywords for exception handling and the +object oriented syntax which were added in Perl 5.36, 5.38 and 5.40. + +--- +*** New user option 'cperl-fontify-trailer'. +This user option takes the values 'perl-code' or 'comment' and treats +text after an "__END__" or "__DATA__" token accordingly. The default +value of 'perl-code' is useful for trailing POD and for AutoSplit +modules, the value 'comment' makes CPerl mode treat trailers as +comment, like Perl mode does. + +--- +*** New command 'cperl-file-style'. +This command sets the indentation style for the current buffer. To +change the default style, either use the user option with the same name +or use the command 'cperl-set-style'. + +--- +*** New minor mode 'cperl-extra-paired-delimiters-mode'. +Perl 5.36 and newer allows using more than 200 non-ASCII paired +delimiters for quote-like constructs, e.g. "q«text»". Use this minor +mode in buffers where this feature is activated. + +--- +*** Commands using the Perl Info manual are obsolete. +The Perl documentation in Info format is no longer distributed with +Perl or on CPAN since more than 10 years. Perl documentation can be +read with 'cperl-perldoc' instead. + +--- +*** Highlighting trailing whitespace has been removed. +The user option 'cperl-invalid-face' is now obsolete, and does +nothing. See the user option 'show-trailing-whitespace' instead. + +** Emacs Sessions (Desktop) + ++++ +*** Restoring buffers visiting remote files can now time out. +When a buffer is restored which visits a remote file, the restoration +of the session could hang if the remote host is off-line or slow to +respond. Setting the user option 'remote-file-name-access-timeout' to +a positive number will abandon the attempt to restore such buffers +after a timeout of that many seconds, thus allowing the rest of +desktop restoration to continue. + +** Recentf + ++++ +*** Checking recent remote files can now time out. +Similarly to buffer restoration by Desktop, 'recentf-mode' checking +of the accessibility of remote files can now time out if +'remote-file-name-access-timeout' is set to a positive number. + +** Image Dired + ++++ +*** New user option 'image-dired-thumb-naming'. +You can now configure how thumbnails are named using this option. + +** ERT + ++++ +*** New macro 'skip-when' to skip 'ert-deftest' tests. +This can help to avoid some awkward skip conditions. For example +'(skip-unless (not noninteractive))' can be changed to the easier +to read '(skip-when noninteractive)'. + ++++ +*** Syntax highlighting unit testing support. +An ERT extension ('ert-font-lock') now provides support for face +assignment unit testing. For more information, see the "(ert) Syntax +Highlighting Tests" node in the ERT manual. + +** Socks + ++++ +*** Socks supports version 4a. +The 'socks-server' user option accepts '4a' as a value for its version +field. + +** Edmacro + ++++ +*** New command 'edmacro-set-macro-to-region-lines'. +Bound to 'C-c C-r', this command replaces the macro text with the +lines of the region. If needed, the region is extended to include +whole lines. If the region ends at the beginning of a line, that last +line is excluded. + ++++ +*** New user option 'edmacro-reverse-macro-lines'. +When this is non-nil, the lines of key sequences are displayed with +the most recent line first. This is can be useful when working with +macros with many lines, such as from 'kmacro-edit-lossage'. + +** Calc + ++++ +*** Calc parses fractions written using U+2044 FRACTION SLASH. +Fractions of the form "123⁄456" are handled as if written "123:456". +Note in particular the difference in behavior from U+2215 DIVISION SLASH +and U+002F SOLIDUS, which result in division rather than a rational +fraction. In addition, precomposed fraction characters, such as ½ +(U+00BD VULGAR FRACTION ONE HALF), are also recognized as rational +fractions. (They have been recognized since 2004, but it looks like it +was never mentioned in the NEWS, or even the Calc manual.) + +** IELM + +--- +*** IELM now remembers input history between sessions. +The new user option 'ielm-history-file-name' is the name of the file +where IELM input history will be saved. Customize it to nil to revert +to the old behavior of not remembering input history between sessions. + +** EasyPG + ++++ +*** New user option 'epa-keys-select-method'. +This allows the user to customize the key selection method, which can be +either by using a pop-up buffer or from the minibuffer. The pop-up +buffer method is the default, which preserves previous behavior. + +** Widget + ++++ +*** New face 'widget-unselected'. +Customize this face to a non-default value to visually distinguish the +labels of unselected active radio-button or checkbox widgets from the +labels of unselected inactive widgets (the default value inherits from +the 'widget-inactive' face). + ++++ +*** New user option 'widget-skip-inactive'. +If non-nil, moving point forward or backward between widgets by typing +'TAB' or 'S-TAB' skips over inactive widgets. The default value is nil. + +** Ruby mode + +--- +*** New user option 'ruby-rubocop-use-bundler'. +By default it retains the previous behavior: read the contents of +Gemfile and act accordingly. But you can also set it to t or nil to +skip the check. + +** Thingatpt + +--- +*** New variables for providing custom thingatpt implementations. +The new variables 'bounds-of-thing-at-point-provider-alist' and +'forward-thing-provider-alist' now allow defining custom implementations +of 'bounds-of-thing-at-point' and 'forward-thing', respectively. + +--- +*** New helper functions for text property-based thingatpt providers. +The new helper functions 'thing-at-point-for-char-property', +'bounds-of-thing-at-point-for-char-property', and +'forward-thing-for-char-property' can help to implement custom thingatpt +providers for "things" that are defined by text properties. + +--- +*** 'bug-reference-mode' now supports 'thing-at-point'. +Now, calling '(thing-at-point 'url)' when point is on a bug reference +will return the URL for that bug. + +** Miscellaneous + ++++ +*** New user option 'rcirc-log-time-format'. +This allows for rcirc logs to use a custom timestamp format, which the +chat buffers use by default. + +--- +*** New user option 'Buffer-menu-group-by'. +It controls how buffers are divided into groups that are displayed with +headings using Outline minor mode. Using commands that mark buffers +on the outline heading line will mark all buffers in the outline. + ++++ +*** New command 'Buffer-menu-toggle-internal'. +This command toggles the display of internal buffers in Buffer Menu mode; +that is, buffers not visiting a file and whose names start with a space. +Previously, such buffers were never shown. This command is bound to 'I' +in Buffer Menu mode. + +--- +*** 'ffap-lax-url' now defaults to nil. +Previously, it was set to t, but this broke remote file name detection. + +--- +*** More control on automatic update of Proced buffers. +The user option 'proced-auto-update-flag' can now be set to two +additional values, which control automatic updates of Proced buffers +that are not displayed in some window. + +--- +*** nXML Mode now comes with schemas for Mono/.NET development. +The following new XML schemas are now supported: +- MSBuild project files +- Dotnet package properties files +- Dotnet resource extension files +- Dotnet Application config files +- Nuget config file +- Nuget package specification file +- Nuget packages config file + +--- +*** color.el now supports the Oklab color representation. + ++++ +*** New user option 'xwidget-webkit-disable-javascript'. +This allows disabling JavaScript in xwidget Webkit sessions. + +--- +*** 'ls-lisp--insert-directory' supports more long options of 'ls'. +'ls-lisp--insert-directory', the ls-lisp implementation of +'insert-directory', now supports the '--time=TIME' and '--sort=time' +options of GNU 'ls'. + +--- +*** 'M-x ping' can now give additional flags to the 'ping' program. +Typing 'C-u M-x ping' prompts first for the host, and then for the flags +to give to the 'ping' command. + +--- +*** Webjump now assumes URIs are HTTPS instead of HTTP. +For links in 'webjump-sites' without an explicit URI scheme, it was +previously assumed that they should be prefixed with "http://". Such +URIs are now prefixed with "https://" instead. + +--- +*** Added prefixes in titdic-cnv library. +Most of the variables and functions in the file have been renamed to +make sure they all use a 'tit-' namespace prefix. + +--- +*** 'xref-revert-buffer' is now an alias of 'revert-buffer'. +The Xref buffer now sets up 'revert-buffer-function' such that +'revert-buffer' behaves like 'xref-revert-buffer' did in previous Emacs +versions, and the latter is now an alias of the former. + +--- +*** The Makefile browser is now obsolete. +The command 'makefile-switch-to-browser' command is now obsolete, +together with related commands used in the "*Macros and Targets*" +buffer. We recommend using an alternative like 'imenu' instead. + + +* New Modes and Packages in Emacs 30.1 + +** New major modes based on the tree-sitter library + ++++ +*** New major mode 'elixir-ts-mode'. +A major mode based on the tree-sitter library for editing Elixir files. + ++++ +*** New major mode 'heex-ts-mode'. +A major mode based on the tree-sitter library for editing HEEx files. + ++++ +*** New major mode 'html-ts-mode'. +An optional major mode based on the tree-sitter library for editing +HTML files. + ++++ +*** New major mode 'lua-ts-mode'. +A major mode based on the tree-sitter library for editing Lua files. + ++++ +*** New major mode 'php-ts-mode'. +A major mode based on the tree-sitter library for editing PHP files. + ++++ +** New package EditorConfig. +This package provides support for the EditorConfig standard, +an editor-neutral way to provide directory local (project-wide) settings. +It is enabled via a new global minor mode 'editorconfig-mode' +which makes Emacs obey the '.editorconfig' files. +There is also a new major mode 'editorconfig-conf-mode' +to edit those configuration files. + ++++ +** New global minor mode 'etags-regen-mode'. +This minor mode generates the tags table automatically based on the +current project configuration, and later updates it as you edit the +files and save the changes. + ++++ +** New package 'which-key'. +The 'which-key' package from GNU ELPA is now included in Emacs. It +implements the global minor mode 'which-key-mode' that displays a table +of key bindings upon entering a partial key chord and waiting for a +moment. For example, after enabling the minor mode, if you enter 'C-x' +and wait for one second, the minibuffer will expand with all available +key bindings that follow 'C-x' (or as many as space allows). + ++++ +** New minor mode 'completion-preview-mode'. +This minor mode shows you symbol completion suggestions as you type, +using an inline preview. New user options in the 'completion-preview' +customization group control exactly when Emacs displays this preview. +'completion-preview-mode' is buffer-local, to enable it globally use +'global-completion-preview-mode'. + ++++ +** New package Window-Tool-Bar. +This provides a new minor mode, 'window-tool-bar-mode'. When this minor +mode is enabled, a tool bar is displayed at the top of a window. To +conserve space, no tool bar is shown if 'tool-bar-map' is nil. The +global minor mode 'global-window-tool-bar-mode' enables this minor mode +in all buffers. + ++++ +** New library Track-Changes. +This library is a layer of abstraction above 'before-change-functions' +and 'after-change-functions' which provides a superset of +the functionality of 'after-change-functions': +- It provides the actual previous text rather than only its length. +- It takes care of accumulating and bundling changes until a time when + its client finds it convenient to react to them. +- It detects most cases where some changes were not properly + reported (calls to 'before/after-change-functions' that are + incorrectly paired, missing, etc...) and reports them adequately. + ++++ +** New global minor mode 'minibuffer-regexp-mode'. +This is a minor mode for editing regular expressions in the minibuffer, +for example in 'query-replace-regexp'. It correctly highlights parens +via 'show-paren-mode' and 'blink-matching-paren' in a user-friendly way, +avoids reporting alleged paren mismatches and makes sexp navigation more +intuitive. + +--- +** The highly accessible Modus themes collection has eight items. +The 'modus-operandi' and 'modus-vivendi' are the main themes that have +been part of Emacs since version 28. The former is light, the latter +dark. In addition to these, we now have 'modus-operandi-tinted' and +'modus-vivendi-tinted' for easier legibility, as well as +'modus-operandi-deuteranopia', 'modus-vivendi-deuteranopia', +'modus-operandi-tritanopia', and 'modus-vivendi-tritanopia' to cover +the needs of users with red-green or blue-yellow color deficiency. +The Info manual "(modus-themes) Top" describes the details and +showcases all their user options. + ++++ +** New library PEG. +Emacs now includes a library for writing Parsing Expression +Grammars (PEG), an approach to text parsing that provides more structure +than regular expressions, but less complexity than context-free +grammars. The Info manual "(elisp) Parsing Expression Grammars" has +documentation and examples. + +--- +** New major mode 'shell-command-mode'. +This mode is used by default for the output of asynchronous 'shell-command'. +To revert to the previous behavior, set the (also new) variable +'async-shell-command-mode' to 'shell-mode'. Any hooks or mode-specific +variables used should be adapted appropriately. + ++++ +** New package Compat. +Emacs now comes with a stub implementation of the +forwards-compatibility Compat package from GNU ELPA. This allows +built-in packages to use the library more effectively, and helps +preventing the installation of Compat if unnecessary. + + +* Incompatible Lisp Changes in Emacs 30.1 + ++++ +** Evaluating a 'lambda' returns an object of type 'interpreted-function'. +Instead of representing interpreted functions as lists that start with +either 'lambda' or 'closure', Emacs now represents them as objects +of their own 'interpreted-function' type, which is very similar +to 'byte-code-function' objects (the argument list, docstring, and +interactive forms are placed in the same slots). +Lists that start with 'lambda' are now used only for non-evaluated +functions (in other words, for source code), but for backward compatibility +reasons, 'functionp' still recognizes them as functions and you can +still call them as before. +Thus code that attempts to "dig" into the internal structure of an +interpreted function's object with the likes of 'car' or 'cdr' will +no longer work and will need to use 'aref' instead to extract its +various subparts (when 'interactive-form', 'documentation', and +'help-function-arglist' aren't adequate). + +--- +** The escape sequence '\x' not followed by hex digits is now an error. +Previously, '\x' without at least one hex digit denoted character code +zero (NUL) but as this was neither intended nor documented or even +known by anyone, it is now treated as an error by the Lisp reader. + +--- +** 'subr-native-elisp-p' is renamed to 'native-comp-function-p'. +The previous name still exists but is marked as obsolete. + ++++ +** 'define-globalized-minor-mode' requires that modes use 'run-mode-hooks'. +Minor modes defined with 'define-globalized-minor-mode', such as +'global-font-lock-mode', will not be enabled any more in those buffers +whose major modes fail to use 'run-mode-hooks'. Major modes defined +with 'define-derived-mode' are not affected. 'run-mode-hooks' has been the +recommended way to run major mode hooks since Emacs 22. + ++++ +** 'buffer-match-p' and 'match-buffers' take '&rest ARGS'. +They used to take a single '&optional ARG' and were documented to use +an unreliable hack to try and support condition predicates that +don't accept this optional ARG. +The new semantics makes no such accommodation, but the code still +supports it (with a warning) for backward compatibility. + +--- +** 'post-gc-hook' runs after updating 'gcs-done' and 'gc-elapsed'. + +--- +** Connection-local variables are applied in buffers visiting remote files. +This overrides possible directory-local or file-local variables with +the same name. + ++++ +** 'copy-tree' now copies records when its optional 2nd argument is non-nil. + ++++ +** Regexp zero-width assertions followed by operators are better defined. +Previously, regexps such as "xy\\B*" would have ill-defined behavior. +Now any operator following a zero-width assertion applies to that +assertion only (which is useless). For historical compatibility, an +operator character following '^' or '\`' becomes literal, but we +advise against relying on this. + ++++ +** Infinities and NaNs no longer act as symbols on non-IEEE platforms. +On old platforms like the VAX that do not support IEEE floating-point, +tokens like '0.0e+NaN' and '1.0e+INF' are no longer read as symbols. +Instead, the Lisp reader approximates an infinity with the nearest +finite value, and a NaN with some other non-numeric object that +provokes an error if used numerically. + ++++ +** Conversion of strings to and from byte-arrays works with multibyte strings. +The functions 'dbus-string-to-byte-array' and +'dbus-byte-array-to-string' now accept and return multibyte Lisp +strings, encoding to UTF-8 and decoding from UTF-8 internally. This +means that the argument to 'dbus-byte-array-to-string' must be a valid +UTF-8 byte sequence, and the optional parameter MULTIBYTE of +'dbus-byte-array-to-string' is now obsolete and unused. The argument of +'dbus-string-to-byte-array' should be a regular Lisp string, not a +unibyte string. + ++++ +** 'minibuffer-allow-text-properties' now can be set buffer-local. +'read-from-minibuffer' and functions that use it can take the +buffer-local value from the minibuffer. + ++++ +** 'minibuffer-allow-text-properties' also affects completions. +When it has a non-nil value, then completion functions like +'completing-read' don't discard text properties from the returned +completion candidate. + ++++ +** X color support compatibility aliases are now obsolete. +The compatibility aliases 'x-defined-colors', 'x-color-defined-p', +'x-color-values', and 'x-display-color-p' are now obsolete. + ++++ +** 'easy-mmode-define-{minor,global}-mode' aliases are now obsolete. +Use 'define-minor-mode' and 'define-globalized-minor-mode' instead. + ++++ +** The 'millisec' argument of 'sleep-for' is now obsolete. +Use a float value for the first argument instead. + +--- +** User options 'eshell-NAME-unload-hook' are now obsolete. +These hooks were named incorrectly, and so they never actually ran +when unloading the corresponding feature. Instead, you should use +hooks named after the feature name, like 'esh-mode-unload-hook'. + +** User options 'eshell-process-wait-{seconds,milliseconds}' are now obsolete. +Instead, use 'eshell-process-wait-time', which supports floating-point +values. + +--- +** User option 'tramp-completion-reread-directory-timeout' has been removed. +This user option has been obsoleted in Emacs 27, use +'remote-file-name-inhibit-cache' instead. + ++++ +** The obsolete calling convention of 'sit-for' has been removed. +That convention was: '(sit-for SECONDS MILLISEC &optional NODISP)'. + +--- +** 'defadvice' is marked as obsolete. +See the "(elisp) Porting Old Advice" Info node for help converting +them to use 'advice-add' or 'define-advice' instead. + +--- +** 'cl-old-struct-compat-mode' is marked as obsolete. +You may need to recompile your code if it was compiled with Emacs < 24.3. + +--- +** Old derived.el functions removed. +The following functions have been deleted because they were only used +by code compiled with Emacs < 21: +'derived-mode-init-mode-variables', 'derived-mode-merge-abbrev-tables', +'derived-mode-merge-keymaps', 'derived-mode-merge-syntax-tables', +'derived-mode-run-hooks', 'derived-mode-set-abbrev-table', +'derived-mode-set-keymap', 'derived-mode-set-syntax-table', +'derived-mode-setup-function-name'. + + +* Lisp Changes in Emacs 30.1 + ++++ +** The 'wheel-up/down/left/right' events are now bound unconditionally. +The 'mouse-wheel-up/down/left/right-event' variables are thus used only +to specify the 'mouse-4/5/6/7' events that might still happen to be +generated by some old packages (or if 'mouse-wheel-buttons' has been set +to nil). + +--- +** Xterm Mouse mode now emits 'wheel-up/down/right/left' events. +This is instead of 'mouse-4/5/6/7' events for the mouse wheel. It uses +the new variable 'mouse-wheel-buttons' to decide which button maps to +which wheel event (if any). + +--- +** In batch mode, tracing now sends the trace to stdout. + ++++ +** New hook 'hack-dir-local-get-variables-functions'. +This can be used to provide support for other directory-local settings +beside ".dir-locals.el". + ++++ +** 'auto-coding-functions' can know the name of the file. +The functions on this hook can now find the name of the file to +which the text belongs by consulting the variable 'auto-coding-file-name'. + ++++ +** New user option 'compilation-safety' to control safety of native code. +It is now possible to control how safe is the code generated by native +compilation, by customizing this user option. It is also possible to +control this at function granularity by using the new 'safety' parameter +in the function's 'declare' form. + ++++ +** New types 'closure' and 'interpreted-function'. +'interpreted-function' is the new type used for interpreted functions, +and 'closure' is the common parent type of 'interpreted-function' +and 'byte-code-function'. + +Those new types come with the associated new predicates 'closurep' and +'interpreted-function-p' as well as a new constructor +'make-interpreted-closure'. + +--- +** New function 'help-fns-function-name'. +For named functions, it just returns the name and otherwise +it returns a short "unique" string that identifies the function. +In either case, the string is propertized so clicking on it gives +further details. + ++++ +** New function 'char-to-name'. +This is a convenience function to return the Unicode name of a char (if +it has one). + ++++ +** New function 'cl-type-of'. +This function is like 'type-of' except that it sometimes returns +a more precise type. For example, for nil and t it returns 'null' +and 'boolean' respectively, instead of just 'symbol'. + ++++ +** New functions 'primitive-function-p' and 'cl-functionp'. +'primitive-function-p' is like 'subr-primitive-p' except that it returns +t only if the argument is a function rather than a special-form, +and 'cl-functionp' is like 'functionp' except it returns nil +for lists and symbols. + +--- +** Built-in types now have corresponding classes. +At the Lisp level, this means that things like '(cl-find-class 'integer)' +will now return a class object, and at the UI level it means that +things like 'C-h o integer RET' will show some information about that type. + +--- +** New variable 'major-mode-remap-defaults' and function 'major-mode-remap'. +The first is like Emacs-29's 'major-mode-remap-alist' but to be set by +packages (instead of users). The second looks up those two variables. + ++++ +** Pcase's functions (in 'pred' and 'app') can specify the argument position. +For example, instead of '(pred (< 5))' you can write '(pred (> _ 5))'. + ++++ +** 'define-advice' now sets the new advice's 'name' property to NAME. +Named advices defined with 'define-advice' can now be removed with +'(advice-remove SYMBOL NAME)' in addition to '(advice-remove SYMBOL +SYMBOL@NAME)'. + ++++ +** New function 'require-with-check' to detect new versions shadowing. +This is like 'require', but it checks whether the argument 'feature' +is already loaded, in which case it either signals an error or +forcibly reloads the file that defines the feature. + ++++ +** New variable 'lisp-eval-depth-reserve'. +It puts a limit to the amount by which Emacs can temporarily increase +'max-lisp-eval-depth' when handling signals. + ++++ +** New special form 'handler-bind'. +It provides a functionality similar to 'condition-case' except it runs +the handler code without unwinding the stack, such that we can record +the backtrace and other dynamic state at the point of the error. See +the Info node "(elisp) Handling Errors". + ++++ +** New text properties add tooltips on fringes. +It is now possible to provide tooltips on fringes by adding special text +properties 'left-fringe-help' and 'right-fringe-help'. See the "(elisp) +Special Properties" Info node in the Emacs Lisp Reference Manual for +more details. + ++++ +** New 'display-buffer' action alist entry 'pop-up-frames'. +This has the same effect as the variable of the same name and takes +precedence over the variable when present. + +--- +** New function 'merge-ordered-lists'. +Mostly used internally to do a kind of topological sort of +inheritance hierarchies. + ++++ +** 'drop' is now an alias for the function 'nthcdr'. + ++++ +** New polymorphic comparison function 'value<'. +This function returns non-nil if the first argument is less than the +second. It works for any two values of the same type with reasonable +ordering for numbers, strings, symbols, bool-vectors, markers, buffers +and processes. Conses, lists, vectors and records are ordered +lexicographically. +It is intended as a convenient ordering predicate for sorting, and is +likely to be faster than hand-written Lisp functions. + ++++ +** New 'sort' arguments and features. +The 'sort' function can now be called using the signature + + (sort SEQ &rest KEYWORD-ARGUMENTS) + +where arguments after the first are keyword/value pairs, all optional: +':key' specifies a function that produces the sorting key from an element, +':lessp' specifies the ordering predicate, defaulting to 'value<', +':reverse' is used to reverse the sorting order, +':in-place is used for in-place sorting, as the default is now to +sort a copy of the input. + +The new signature is less error-prone and reduces the need to write +ordering predicates by hand. We recommend that you use the ':key' +argument instead of ':lessp' unless a suitable ordering predicate is +already available. This can also be used for multi-key sorting: + + (sort seq :key (lambda (x) (list (age x) (size x) (cost x)))) + +sorts by the return value of 'age', then by 'size', then by 'cost'. + +The old signature, '(sort SEQ PREDICATE)', can still be used and sorts +its input in-place as before. + +** New API for 'derived-mode-p' and control of the graph of major modes. + ++++ +*** 'derived-mode-p' now takes the list of modes as a single argument. +The same holds for 'provided-mode-derived-p'. +The old calling convention where multiple modes are passed as +separate arguments is deprecated. + ++++ +*** New functions to access the graph of major modes. +While 'define-derived-mode' still only supports single inheritance, +modes can declare additional parents (for tests like 'derived-mode-p') +with 'derived-mode-add-parents'. +Accessing the 'derived-mode-parent' property directly is now +deprecated in favor of the new functions 'derived-mode-set-parent' +and 'derived-mode-all-parents'. + ++++ +** Drag-and-drop functions can now be called once for compound drops. +It is now possible for drag-and-drop handler functions to respond to +drops incorporating more than one URL. Functions capable of this must +set their 'dnd-multiple-handler' symbol properties to a non-nil value. +See the Info node "(elisp) Drag and Drop". + +The function 'dnd-handle-one-url' has been made obsolete, since it +cannot take these new handlers into account. + ++++ +** 'notifications-notify' can use Icon Naming Specification for ':app-icon'. +You can use a symbol as the value for ':app-icon' to provide icon name +without specifying a file, like this: + + (notifications-notify + :title "I am playing music" :app-icon 'multimedia-player) + +--- +** New function 're-disassemble' to see the innards of a regexp. +If you built Emacs with '--enable-checking', you can use this to help +debug either your regexp performance problems or the regexp engine. + ++++ +** XLFDs are no longer restricted to 255 characters. +'font-xlfd-name' now returns an XLFD even if it is greater than 255 +characters in length, provided that the LONG_XLFDs argument is true. +Other features in Emacs which employ XLFDs have been modified to +produce and understand XLFDs larger than 255 characters. + ++++ +** New macro 'static-if' for conditional evaluation of code. +This macro hides a form from the evaluator or byte-compiler based on a +compile-time condition. This is handy for avoiding byte-compilation +warnings about code that will never actually run under some conditions. + ++++ +** Desktop notifications are now supported on the Haiku operating system. +The new function 'haiku-notifications-notify' provides a subset of the +capabilities of the 'notifications-notify' function in a manner +analogous to 'w32-notification-notify'. + +** New Haiku specific variable 'haiku-pass-control-tab-to-system'. +This sets whether Emacs should pass 'C-TAB' on to the system instead of +handling it, fixing a problem where window switching would not activate +if an Emacs frame had focus on the Haiku operating system. + ++++ +** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. +It results in 'insert-file-contents' erasing the buffer instead of +preserving markers if the file being inserted is not a regular file, +rather than signaling an error. + ++++ +** New variable 'current-key-remap-sequence'. +It is bound to the key sequence that caused a call to a function bound +within 'function-key-map' or 'input-decode-map' around those calls. + ++++ +** The function 'key-translate' can now remove translations. +If the second argument TO is nil, the existing key translation is +removed. + ++++ +** New variables describing the names of built in programs. +The new variables 'ctags-program-name', 'ebrowse-program-name', +'etags-program-name', 'hexl-program-name', 'emacsclient-program-name' +'movemail-program-name', and 'rcs2log-program-name' should be used +instead of "ctags", "ebrowse", "etags", "hexl", "emacsclient", and +"rcs2log", when starting one of these built in programs in a subprocess. + ++++ +** New variable 'case-symbols-as-words' affects case operations for symbols. +If non-nil, then case operations such as 'upcase-initials' or +'replace-match' (with nil FIXEDCASE) will treat the entire symbol name +as a single word. This is useful for programming languages and styles +where only the first letter of a symbol's name is ever capitalized. +The default value of this variable is nil. + +--- +** Bytecode is now always loaded eagerly. +Bytecode compiled with older Emacs versions for lazy loading using +'byte-compile-dynamic' is now loaded all at once. +As a consequence, 'fetch-bytecode' has no use, does nothing, and is +now obsolete. The variable 'byte-compile-dynamic' has no effect any +more; compilation will always yield bytecode for eager loading. + ++++ +** Returned strings from functions and macros are never docstrings. +Functions and macros whose bodies consist of a single string literal now +only return that string, and will not use it as a docstring. Example: + + (defun sing-a-song () + "Sing a song.") + +The above function returns the string "Sing a song." and has no +docstring. Previously, that string was used as both the docstring and +return value, which was never what the programmer wanted. If you want +the string to be a docstring, add an explicit return value. + +This change applies to 'defun', 'defsubst', 'defmacro' and 'lambda' +forms; other defining forms such as 'cl-defun' already worked this way. + +** New or changed byte-compilation warnings + +--- +*** Warn about missing 'lexical-binding' directive. +The compiler now warns if an Elisp file lacks the standard +'-*- lexical-binding: ... -*-' cookie on the first line. +This line typically looks something like + + ;;; My little pony mode -*- lexical-binding: t -*- + +It is needed to inform the compiler about which dialect of ELisp +your code is using: the modern dialect with lexical binding or +the old dialect with only dynamic binding. + +Lexical binding avoids some name conflicts and allows the compiler to +detect more mistakes and generate more efficient code, so it is +recommended. For how to adapt your code to lexical binding, see the +manual section "(elisp) Converting to Lexical Binding". + +If your code cannot be converted to lexical binding, you can insert +the line + + ;;; -*- lexical-binding: nil -*- + +first in the file to declare that it uses the old dialect. + +--- +*** 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: + + (when (> x 2)) + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'empty-body'. + +--- +*** 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: + + (condition-case nil + (/ x y) + ('arith-error "division by zero")) + +Quoting them adds the error name 'quote' to those handled or ignored +respectively, which was probably not intended. + +--- +*** 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: + + (eq x "hello") + +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'. + +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. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'suspicious'. + +--- +*** Warn about 'condition-case' without handlers. +The compiler now warns when the 'condition-case' form is used without +any actual handlers, as in + + (condition-case nil (read buffer)) + +because it has no effect other than the execution of the body form. +In particular, no errors are caught or suppressed. If the intention +was to catch all errors, add an explicit handler for 'error', or use +'ignore-error' or 'ignore-errors'. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'suspicious'. + +--- +*** Warn about 'unwind-protect' without unwind forms. +The compiler now warns when the 'unwind-protect' form is used without +any unwind forms, as in + + (unwind-protect (read buffer)) + +because the behavior is identical to that of the argument; there is +no protection of any kind. Perhaps the intended unwind forms have +been misplaced or forgotten, or the use of 'unwind-protect' could be +simplified away. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'suspicious'. + +--- +*** Warn about useless trailing 'cond' clauses. +The compiler now warns when a 'cond' form contains clauses following a +default (unconditional) clause. Example: + + (cond ((= x 0) (say "none")) + (t (say "some")) + (say "goodbye")) + +Such a clause will never be executed, and is likely to be a mistake, +perhaps due to misplaced parens. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'suspicious'. + +--- +*** Warn about mutation of constant values. +The compiler now warns about code that modifies program constants in +some obvious cases. Examples: + + (setcar '(1 2) 7) + (aset [3 4] 0 8) + (aset "abc" 1 ?d) + +Such code may have unpredictable behavior because the constants are part +of the program and are not data structures generated afresh during +execution; the compiler does not expect them to change. + +To avoid the warning, operate on an object created by the program +(maybe a copy of the constant), or use a non-destructive operation +instead. + +This warning can be suppressed using 'with-suppressed-warnings' with +the warning name 'mutate-constant'. + +--- +*** Warn about more ignored function return values. +The compiler now warns when the return value from certain functions is +implicitly ignored. Example: + + (progn (nreverse my-list) my-list) + +will elicit a warning because it is usually pointless to call +'nreverse' on a list without using the returned value. + +To silence the warning, make use of the value in some way, such as +assigning it to a variable. You can also wrap the function call in +'(ignore ...)', or use 'with-suppressed-warnings' with the warning +name 'ignored-return-value'. + +The warning will only be issued for calls to functions declared +'important-return-value' or 'side-effect-free' (but not 'error-free'). + +--- +*** Warn about docstrings that contain control characters. +The compiler now warns about docstrings with control characters other +than newline and tab. This is often a result of improper escaping. +Example: + + (defun my-fun () + "Uses c:\remote\dir\files and the key \C-x." + ...) + +where the docstring contains the four control characters 'CR', 'DEL', +'FF' and 'C-x'. + +The warning name is 'docstrings-control-chars'. + +--- +*** The warning about wide docstrings can now be disabled separately. +Its warning name is 'docstrings-wide'. + ++++ +** 'fset', 'defalias' and 'defvaralias' now signal an error for cyclic aliases. +Previously, 'fset', 'defalias' and 'defvaralias' could be made to +build circular function and variable indirection chains as in + + (defalias 'able 'baker) + (defalias 'baker 'able) + +but trying to use them would sometimes make Emacs hang. Now, an attempt +to create such a loop results in an error. + +Since circular alias chains now cannot occur, 'function-alias-p', +'indirect-function' and 'indirect-variable' will never signal an error. +Their 'noerror' arguments have no effect and are therefore obsolete. + +** Touch Screen support + ++++ +*** 'x-popup-menu' now understands touch screen events. +When a 'touchscreen-begin' or 'touchscreen-end' event is passed as the +POSITION argument, it will behave as if that event was a mouse event. + ++++ +*** New functions for handling touch screen events. +The new functions 'touch-screen-track-tap' and 'touch-screen-track-drag' +handle tracking common touch screen gestures from within a command. + ++++ +*** New parameter to 'touchscreen-end' events. +CANCEL non-nil establishes that the touch sequence has been intercepted +by programs such as window managers and should be ignored with Emacs. + +--- +** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill. + ++++ +** New variable 'secondary-tool-bar-map'. +If non-nil, this variable contains a keymap of menu items that are +displayed along tool bar items defined by 'tool-bar-map'. These items +are displayed below the tool bar if the value of 'tool-bar-position' is +'top', and above it if the value is 'bottom'. This is used by +'modifier-bar-mode'. + +--- +** New variable 'completion-lazy-hilit'. +Lisp programs that present completion candidates may bind this +variable non-nil around calls to functions such as +'completion-all-completions'. This tells the underlying completion +styles to skip eager fontification of completion candidates, which +improves performance. Such a Lisp program can then use the +'completion-lazy-hilit' function to fontify candidates just in time. + ++++ +** New primitive 'buffer-last-name'. +It returns the name of a buffer before the last time it was renamed or +killed. + ++++ +** New primitive 'marker-last-position'. +It returns the last position of a marker in its buffer even if that +buffer has been killed. ('marker-position' would return nil in that +case.) + +** Functions and variables to transpose sexps + +--- +*** New helper variable 'transpose-sexps-function'. +Lisp programs can now set this variable to customize the behavior of the +'transpose-sexps' command. + +--- +*** New function 'transpose-sexps-default-function'. +The previous implementation of 'transpose-sexps' was moved into its own +function, to be used in 'transpose-sexps-function'. + +--- +*** New function 'treesit-transpose-sexps'. +Tree-sitter now unconditionally sets 'transpose-sexps-function' for all +tree-sitter enabled modes to this function. + +** Functions and variables to move by program statements + ++++ +*** New variable 'forward-sentence-function'. +Major modes can now set this variable to customize the behavior of the +'forward-sentence' command. + +--- +*** New function 'forward-sentence-default-function'. +The previous implementation of 'forward-sentence' is moved into its +own function, to be bound by 'forward-sentence-function'. + ++++ +*** New function 'treesit-forward-sentence'. +All tree-sitter enabled modes that define 'sentence' in +'treesit-thing-settings' now set 'forward-sentence-function' to call +'treesit-forward-sentence'. + +** Functions and variables to move by program sexps + ++++ +*** New function 'treesit-forward-sexp'. +Tree-sitter conditionally sets 'forward-sexp-function' for major modes +that have defined 'sexp' in 'treesit-thing-settings' to enable +sexp-related motion commands. + +--- +** New user option 'native-comp-async-warnings-errors-kind'. +It allows control of what kinds of warnings and errors from asynchronous +native compilation are reported to the parent Emacs process. The +default is to report all errors and only important warnings. If you +were used to customizing 'native-comp-async-report-warnings-errors' to +nil or 'silent', we suggest that you now leave it at its default value, +and see if you get only warnings that matter. + +** Function 'declare' forms + ++++ +*** New 'ftype' function declaration. +The declaration '(ftype TYPE)' specifies the type of a function. +Example: + + (defun hello (x y) + (declare (ftype (function (integer boolean) string))) + ...) + +specifies that the function takes two arguments, an integer and a +boolean, and returns a string. If the compilation happens with +'compilation-safety' set to zero, this information can be used by the +native compiler to produce better code, but specifying an incorrect type +may lead to Emacs crashing. See the Info node "(elisp) Declare Form" +for further information. + ++++ +*** New 'important-return-value' function declaration and property. +The declaration '(important-return-value t)' sets the +'important-return-value' property which indicates that the function +return value should probably not be thrown away implicitly. + ++++ +** New functions 'file-user-uid' and 'file-group-gid'. +These functions are like 'user-uid' and 'group-gid', respectively, but +are aware of file name handlers, so they will return the remote UID or +GID for remote files (or -1 if the connection has no associated user). + ++++ +** 'treesit-font-lock-rules' now accepts additional global keywords. +When supplied with ':default-language LANGUAGE', rules after it will +default to use 'LANGUAGE'. + +--- +** New optional argument to 'modify-dir-local-variable'. +A 5th argument, optional, has been added to +'modify-dir-local-variable'. It can be used to specify which +dir-locals file to modify. + +** Connection local variables + ++++ +*** New macros 'connection-local-p' and 'connection-local-value'. +The former macro returns non-nil if a variable has a connection-local +binding. The latter macro returns the connection-local value of a +variable if any, or its current value. + +** Hash tables + ++++ +*** ':rehash-size' and ':rehash-threshold' args no longer have any effect. +These keyword arguments are now ignored by 'make-hash-table'. Emacs +manages the memory for all hash table objects in the same way. +The functions 'hash-table-rehash-size' and 'hash-table-rehash-threshold' +remain for compatibility but now always return the old default values. + ++++ +*** The printed representation has been shrunk and simplified. +The 'test' parameter is omitted if it is 'eql' (the default), as is +'data' if empty. 'rehash-size', 'rehash-threshold' and 'size' are +always omitted, and ignored if present when the object is read back in. + +** Obarrays + ++++ +*** New obarray type. +Obarrays are now represented by an opaque type instead of using vectors. +They are created by 'obarray-make' and manage their internal storage +automatically, which means that the size parameter to 'obarray-make' can +safely be omitted. That is, they do not become slower as they fill up. + +The old vector representation is still accepted by functions operating +on obarrays, but 'obarrayp' only returns t for obarray objects. +'type-of' now returns 'obarray' for obarray objects. + +Old code which (incorrectly) created "obarrays" as Lisp vectors filled +with something other than 0, as in '(make-vector N nil)', will no longer +work, and should be rewritten to use 'obarray-make'. Alternatively, you +can fill the vector with 0. + ++++ +*** New function 'obarray-clear' removes all symbols from an obarray. + +--- +*** 'obarray-size' and 'obarray-default-size' are now obsolete. +They pertained to the internal storage size which is now irrelevant. + ++++ +** 'treesit-install-language-grammar' can handle local directory instead of URL. +It is now possible to pass a directory of a local repository as URL +inside 'treesit-language-source-alist', so that calling +'treesit-install-language-grammar' would avoid cloning the repository. +It may be useful, for example, for the purposes of bisecting a +treesitter grammar. + ++++ +** New buffer-local variable 'tabulated-list-groups'. +It controls display and separate sorting of groups of entries. + ++++ +** New variable 'revert-buffer-restore-functions'. +It helps to preserve various states after reverting the buffer. + +--- +** New text property 'context-menu-functions'. +Like the variable with the same name, it adds menus from the list that +is the value of the property to context menus shown when clicking on the +text which as this property. + +--- +** Detecting the end of an iteration of a keyboard macro. +'read-event', 'read-char', and 'read-char-exclusive' no longer return -1 +when called at the end of an iteration of the execution of a keyboard +macro. Instead, they will transparently continue reading available input +(e.g., from the keyboard). If you need to detect the end of a macro +iteration, check the following condition before calling one of the +aforementioned functions: + + (and (arrayp executing-kbd-macro) + (>= executing-kbd-macro-index (length executing-kbd-macro))) + ++++ +** 'vtable-update-object' updates an existing object with just two arguments. +It is now possible to update the representation of an object in a vtable +by calling 'vtable-update-object' with just the vtable and the object as +arguments. (Previously, the OLD-OBJECT argument was required which, in +this case, would mean repeating the object in the argument list.) When +replacing an object with a different one, passing both the new and old +objects is still necessary. + +** 'vtable-insert-object' can insert "before" or at an index. +The signature of 'vtable-insert-object' has changed and is now: + + (vtable-insert-object TABLE OBJECT &optional LOCATION BEFORE) + +LOCATION corresponds to the old AFTER-OBJECT argument; if BEFORE is +non-nil, the new object is inserted before the LOCATION object, making +it possible to insert a new object at the top of the table. (Before, +this was not possible.) In addition, LOCATION can be an integer, a +(zero-based) index into the table at which the new object is inserted +(BEFORE is ignored in this case). + ++++ +** New function 'sqlite-execute-batch'. +This function lets the user execute multiple SQL statements in one go. +It is useful, for example, when a Lisp program needs to evaluate an +entire SQL file. + +** JSON + +--- +*** The parser keeps duplicated object keys in alist and plist output. +A JSON object such as '{"a":1,"a":2}' will now be translated into the +Lisp values '((a . 1) (a . 2))' or '(:a 1 :a 2)' if alist or plist +object types are requested. + +--- +*** The parser sometimes signals different types of errors. +It will now signal 'json-utf8-decode-error' for inputs that are not +correctly UTF-8 encoded. + +--- +*** The parser and encoder now accept arbitrarily large integers. +Previously, they were limited to the range of signed 64-bit integers. + +** New tree-sitter functions and variables for defining and using "things" + ++++ +*** New variable 'treesit-thing-settings'. +It allows modes to define "things" like 'defun', 'text', 'sexp', and +'sentence' for navigation commands and tree-traversal functions. + ++++ +*** New functions for navigating "things". +There are new navigation functions 'treesit-thing-prev', +'treesit-thing-next', 'treesit-navigate-thing', +'treesit-beginning-of-thing', and 'treesit-end-of-thing'. + ++++ +*** New functions 'treesit-thing-at', 'treesit-thing-at-point'. + ++++ +*** Tree-traversing functions. +The functions 'treesit-search-subtree', 'treesit-search-forward', +'treesit-search-forward-goto', and 'treesit-induce-sparse-tree' now +accept more kinds of predicates. Lisp programs can now use thing +symbols (defined in 'treesit-thing-settings') and any thing definitions +for the predicate argument. + +** Other tree-sitter function and variable changes + ++++ +*** 'treesit-parser-list' now takes additional optional arguments. +The additional arguments are LANGUAGE and TAG. If LANGUAGE is given, +only return parsers for that language. If TAG is given, only return +parsers with that tag. Note that passing nil as tag doesn't mean return +all parsers, but rather "all parsers with no tags". + ++++ +*** New variable 'treesit-primary-parser'. +This variable should be set by multi-langauge major modes before calling +'treesit-major-mode-setup', in order for tree-sitter integration +functionalities to operate correctly. + + +* Changes in Emacs 30.1 on Non-Free Operating Systems + +** MS-Windows + ++++ +*** You can now opt out of following MS-Windows' Dark mode. +By default, Emacs on MS-Windows follows the system's Dark mode for its +title bars' and scroll bars' appearance. If the new user option +'w32-follow-system-dark-mode' is customized to the nil value, Emacs +will disregard the system's Dark mode and will always use the default +Light mode. + +--- +*** You can now use Image-Dired even if the 'convert' program is not installed. +If you don't have GraphicsMagick or ImageMagick installed, and thus the +'gm convert'/'convert' program is not available, Emacs on MS-Windows +will now use its own function 'w32image-create-thumbnail' to create +thumbnail images and show them in the thumbnail buffer. Unlike with +using 'convert', this fallback method is synchronous, so Emacs will wait +until all the thumbnails are created and displayed, before showing them. + +--- +*** Emacs on MS-Windows now supports the ':stipple' face attribute. + + +---------------------------------------------------------------------- +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/refcards/ru-refcard.tex b/etc/refcards/ru-refcard.tex index a394688a8a0..a013f7695ed 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]{30} % version of Emacs this is for +\newcommand{\versionemacs}[0]{31} % version of Emacs this is for \newcommand{\cyear}[0]{2024} % copyright year \newcommand\shortcopyrightnotice[0]{\vskip 1ex plus 2 fill diff --git a/exec/Makefile.in b/exec/Makefile.in index 36f0c0c74a9..7e681c0c3d8 100644 --- a/exec/Makefile.in +++ b/exec/Makefile.in @@ -44,6 +44,9 @@ FIND_DELETE = @FIND_DELETE@ OBJS = @OBJS@ LOADOBJS = $(patsubst %.s,%.o,$(LOADER)) +# Compilation parameters. + is_mips = @is_mips@ + # Set up automatic dependency tracking. AUTO_DEPEND = @AUTO_DEPEND@ @@ -82,6 +85,8 @@ Makefile: config.status Makefile.in .SUFFIXES: .c .s .c.o: $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEPFLAGS) -I. -I$(srcdir) $< -o $@ + +ifeq ($(is_mips),yes) .s.o: $(M4) $< > $(notdir $<).s $(AS) $(ASFLAGS) $(notdir $<).s -o $@ @@ -91,6 +96,10 @@ Makefile: config.status Makefile.in config-mips.m4: config-mips.m4.in cd $(srcdir) && ./config.status $@ $(LOADOBJS): config-mips.m4 +else +.s.o: + $(AS) $(ASFLAGS) $< -o $@ +endif # Set up rules to build libexec.a. diff --git a/exec/README b/exec/README index f7eb21cfc84..a1534503247 100644 --- a/exec/README +++ b/exec/README @@ -1,3 +1,6 @@ This directory holds the source code to a library used to replace the `execve' and `execveat' system calls, used by the Android port of Emacs to start executables without intervention from the system. + +The most edifying resource for developers will be GDB, or to be precise, +the Linux target implementations for architectures of interest. diff --git a/exec/configure.ac b/exec/configure.ac index a473a1dc633..c3e895740be 100644 --- a/exec/configure.ac +++ b/exec/configure.ac @@ -42,11 +42,6 @@ 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/>. */]) -AC_ARG_WITH([reentrancy], - [AS_HELP_STRING([--with-reentrancy], - [Generate library which can be used within a signal handler.])], - [AC_DEFINE([REENTRANT], [1])]) - AC_USE_SYSTEM_EXTENSIONS AC_PROG_CC AC_PROG_CPP @@ -74,9 +69,9 @@ AC_CHECK_FUNC([process_vm_readv], ]])])]) AC_CHECK_HEADERS([sys/param.h sys/uio.h]) AC_CHECK_MEMBERS([siginfo_t.si_syscall], [], [], - [[ +[[ #include <signal.h> - ]]) +]]) AH_BOTTOM([ #ifdef HAVE_STDBOOL_H @@ -120,6 +115,7 @@ AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.]) AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.]) AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.]) +AH_TEMPLATE([PROGRAM_COUNTER], [Define to register holding the program counter.]) AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.]) AH_TEMPLATE([USER_WORD], [Define to word type used by tracees.]) AH_TEMPLATE([USER_SWORD], [Define to signed word type used by tracees.]) @@ -134,7 +130,8 @@ AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call. AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.]) AH_TEMPLATE([OPEN_SYSCALL], [Define to number of the `open' system call.]) AH_TEMPLATE([OPENAT_SYSCALL], [Define to number of the `openat' system call.]) -AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.]) +AH_TEMPLATE([HAVE_SECCOMP], [Define to 1 if secure computing filters are available +to accelerate interception of system calls.]) AC_CANONICAL_HOST @@ -250,6 +247,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [rdx]) AC_DEFINE([SYSCALL_ARG3_REG], [r10]) AC_DEFINE([STACK_POINTER], [rsp]) + AC_DEFINE([PROGRAM_COUNTER], [rip]) AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -283,6 +281,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [edx]) AC_DEFINE([SYSCALL_ARG3_REG], [esi]) AC_DEFINE([STACK_POINTER], [esp]) + AC_DEFINE([PROGRAM_COUNTER], [eip]) AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -314,6 +313,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [[regs[2]]]) AC_DEFINE([SYSCALL_ARG3_REG], [[regs[3]]]) AC_DEFINE([STACK_POINTER], [sp]) + AC_DEFINE([PROGRAM_COUNTER], [pc]) AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -346,6 +346,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]]) AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]]) AC_DEFINE([STACK_POINTER], [[uregs[13]]]) + AC_DEFINE([PROGRAM_COUNTER], [[uregs[15]]]) AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -371,6 +372,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]]) AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]]) AC_DEFINE([STACK_POINTER], [[uregs[13]]]) + AC_DEFINE([STACK_POINTER], [[uregs[15]]]) AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -402,6 +404,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2 AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3 AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp + AC_DEFINE([PROGRAM_COUNTER], [[cp0_epc]]) # pc AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -432,6 +435,7 @@ AS_CASE([$host], [x86_64-*linux*], AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2 AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3 AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp + AC_DEFINE([PROGRAM_COUNTER], [[cp0_epc]]) # pc AC_DEFINE([EXEC_SYSCALL], [__NR_execve]) AC_DEFINE([USER_WORD], [uintptr_t]) AC_DEFINE([USER_SWORD], [intptr_t]) @@ -480,6 +484,12 @@ AC_ARG_VAR([LOADERFLAGS], [Flags used to link the loader.]) AC_ARG_VAR([ARFLAGS], [Flags for the archiver.]) AC_ARG_VAR([ASFLAGS], [Flags for the assembler.]) +# Search for seccomp headers and declarations. +AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h], + [AC_CHECK_DECLS([SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC, SECCOMP_RET_TRACE], + [AC_DEFINE([HAVE_SECCOMP], [1])], [], + [[#include <linux/seccomp.h>]])]) + # Make the assembler optimize for code size. Don't do this on MIPS, # as the assembler code manages branch delays manually. @@ -547,7 +557,9 @@ FIND_DELETE=$exec_cv_find_delete AC_SUBST([FIND_DELETE]) AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([Makefile config-mips.m4]) +AC_CONFIG_FILES([Makefile]) +AS_IF([test "x$is_mips" = xyes], + [AC_CONFIG_FILES ([config-mips.m4])]) AC_SUBST([AUTO_DEPEND]) AC_SUBST([LOADERFLAGS]) @@ -556,5 +568,6 @@ AC_SUBST([ASFLAGS]) AC_SUBST([exec_loader]) AC_SUBST([MIPS_N32]) AC_SUBST([OBJS]) +AC_SUBST([is_mips]) AC_OUTPUT diff --git a/exec/exec.c b/exec/exec.c index cbe22d4f18c..775a8b06b96 100644 --- a/exec/exec.c +++ b/exec/exec.c @@ -292,7 +292,9 @@ write_load_command (program_header *header, bool use_alternate, struct exec_map_command command1; USER_WORD start, end; bool need_command1; +#ifndef PAGE_MASK static long pagesize; +#endif /* !PAGE_MASK */ /* First, write the commands necessary to map the specified segment itself. @@ -306,14 +308,14 @@ write_load_command (program_header *header, bool use_alternate, #ifdef HAVE_GETPAGESIZE if (!pagesize) pagesize = getpagesize (); -#else /* HAVE_GETPAGESIZE */ +#else /* !HAVE_GETPAGESIZE */ if (!pagesize) pagesize = sysconf (_SC_PAGESIZE); -#endif /* HAVE_GETPAGESIZE */ +#endif /* !HAVE_GETPAGESIZE */ #define PAGE_MASK (~(pagesize - 1)) #define PAGE_SIZE (pagesize) -#endif /* PAGE_MASK */ +#endif /* !PAGE_MASK */ start = header->p_vaddr & PAGE_MASK; end = ((header->p_vaddr + header->p_filesz @@ -895,10 +897,6 @@ format_pid (char *in, unsigned int pid) with #!; in that case, find the program to open and use that instead. - If REENTRANT is not defined, NAME is actually a buffer of size - PATH_MAX + 80. In that case, copy over the file name actually - opened. - Next, read the executable header, and add the necessary memory mappings for each file. Finally, return the action data and its size in *SIZE. @@ -978,9 +976,7 @@ exec_0 (char *name, struct exec_tracee *tracee, memcpy (rewrite, name, strnlen (name, remaining)); /* Replace name with buffer1. */ -#ifndef REENTRANT strcpy (name, buffer1); -#endif /* REENTRANT */ } } diff --git a/exec/exec.h b/exec/exec.h index 3ce06c35311..59963587573 100644 --- a/exec/exec.h +++ b/exec/exec.h @@ -152,6 +152,16 @@ struct exec_tracee completion. */ USER_WORD sp; + /* Name of the executable being run. */ + char *exec_file; + + /* Pointer to a storage area holding instructions for loading an + executable if an `exec' system call is outstanding, or NULL. */ + char *exec_data; + + /* Number of bytes in exec_data. */ + size_t data_size; + /* The thread ID of this process. */ pid_t pid; @@ -162,11 +172,6 @@ struct exec_tracee /* Whether or not the tracee has been created but is not yet processed by `handle_clone'. */ bool new_child : 1; - -#ifndef REENTRANT - /* Name of the executable being run. */ - char *exec_file; -#endif /* !REENTRANT */ }; diff --git a/exec/exec1.c b/exec/exec1.c index aaff9a94c62..cbd756d3d5c 100644 --- a/exec/exec1.c +++ b/exec/exec1.c @@ -42,6 +42,9 @@ main (int argc, char **argv) extern char **environ; int wstatus; + /* Provide the file name of the loader. */ + exec_init (argv[1]); + pid1 = getpid (); pid = fork (); @@ -58,9 +61,6 @@ main (int argc, char **argv) } else { - /* Provide the file name of the loader. */ - exec_init (argv[1]); - if (after_fork (pid)) exit (127); diff --git a/exec/loader-x86.s b/exec/loader-x86.s index 216bc88f976..3d132dd99e8 100644 --- a/exec/loader-x86.s +++ b/exec/loader-x86.s @@ -1,71 +1,68 @@ -define(`CC', ` -dnl') - -CC Copyright (C) 2023-2024 Free Software Foundation, Inc. -CC -CC This file is part of GNU Emacs. -CC -CC GNU Emacs is free software: you can redistribute it and/or modify -CC it under the terms of the GNU General Public License as published -CC by the Free Software Foundation, either version 3 of the License, -CC or (at your option) any later version. -CC -CC GNU Emacs is distributed in the hope that it will be useful, but -CC WITHOUT ANY WARRANTY; without even the implied warranty of -CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -CC General Public License for more details. -CC -CC You should have received a copy of the GNU General Public License -CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. +# Copyright (C) 2023-2024 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/>. .section .text .global _start _start: -dnl movl $162, %eax CC SYS_nanosleep -dnl leal timespec, %ebx -dnl xorl %ecx, %ecx -dnl int $0x80 - leal 8(%esp), %ebp CC ebp = start of load area - subl $8, %esp CC (%esp) = primary fd, 4(%esp) = secondary fd +# movl $162, %eax # SYS_nanosleep +# leal timespec, %ebx +# xorl %ecx, %ecx +# int $0x80 + leal 8(%esp), %ebp # ebp = start of load area + subl $8, %esp # (%esp) = primary fd, 4(%esp) = secondary fd movl $-1, 4(%esp) .next_action: - movl (%ebp), %edx CC edx = action number + movl (%ebp), %edx # edx = action number andl $-17, %edx - cmpl $0, %edx CC open file? + cmpl $0, %edx # open file? je .open_file - cmpl $3, %edx CC jump? + cmpl $3, %edx # jump? je .rest_of_exec - cmpl $4, %edx CC anonymous mmap? + cmpl $4, %edx # anonymous mmap? je .do_mmap_anon .do_mmap: subl $24, %esp - movl $90, %eax CC SYS_old_mmap + movl $90, %eax # SYS_old_mmap movl %esp, %ebx - movl 4(%ebp), %ecx CC address + movl 4(%ebp), %ecx # address movl %ecx, (%esp) - movl 16(%ebp), %ecx CC length + movl 16(%ebp), %ecx # length movl %ecx, 4(%esp) - movl 12(%ebp), %ecx CC protection + movl 12(%ebp), %ecx # protection movl %ecx, 8(%esp) - movl 20(%ebp), %ecx CC flags + movl 20(%ebp), %ecx # flags movl %ecx, 12(%esp) - testl $16, (%ebp) CC primary? + testl $16, (%ebp) # primary? movl 28(%esp), %ecx cmovzl 24(%esp), %ecx - movl %ecx, 16(%esp) CC fd - movl 8(%ebp), %ecx CC offset + movl %ecx, 16(%esp) # fd + movl 8(%ebp), %ecx # offset movl %ecx, 20(%esp) .do_mmap_1: int $0x80 - addl $24, %esp CC restore esp - cmpl $-1, %eax CC mmap failed? + addl $24, %esp # restore esp + cmpl $-1, %eax # mmap failed? je .perror - movl 24(%ebp), %ecx CC clear + movl 24(%ebp), %ecx # clear testl %ecx, %ecx jz .continue - movl 4(%ebp), %esi CC start of mapping - addl 16(%ebp), %esi CC end of mapping - subl %ecx, %esi CC start of clear area + movl 4(%ebp), %esi # start of mapping + addl 16(%ebp), %esi # end of mapping + subl %ecx, %esi # start of clear area .again: testl %ecx, %ecx jz .continue @@ -77,58 +74,58 @@ dnl int $0x80 jmp .next_action .do_mmap_anon: subl $24, %esp - movl $90, %eax CC SYS_old_mmap + movl $90, %eax # SYS_old_mmap movl %esp, %ebx - movl 4(%ebp), %ecx CC address + movl 4(%ebp), %ecx # address movl %ecx, (%esp) - movl 16(%ebp), %ecx CC length + movl 16(%ebp), %ecx # length movl %ecx, 4(%esp) - movl 12(%ebp), %ecx CC protection + movl 12(%ebp), %ecx # protection movl %ecx, 8(%esp) - movl 20(%ebp), %ecx CC flags + movl 20(%ebp), %ecx # flags movl %ecx, 12(%esp) - movl $-1, 16(%esp) CC fd - movl 8(%ebp), %ecx CC offset + movl $-1, 16(%esp) # fd + movl 8(%ebp), %ecx # offset movl %ecx, 20(%esp) jmp .do_mmap_1 .open_file: - movl $5, %eax CC SYS_open - leal 4(%ebp), %ebx CC ebx = %esp + 8 + movl $5, %eax # SYS_open + leal 4(%ebp), %ebx # ebx = %esp + 8 pushl %ebx - xorl %ecx, %ecx CC flags = O_RDONLY - xorl %edx, %edx CC mode = 0 + xorl %ecx, %ecx # flags = O_RDONLY + xorl %edx, %edx # mode = 0 int $0x80 - cmpl $-1, %eax CC open failed? + cmpl $-1, %eax # open failed? jle .perror - movl %ebp, %esi CC (esi) = original action number - popl %ebp CC ebp = start of string - movl %ebp, %ecx CC char past separator + movl %ebp, %esi # (esi) = original action number + popl %ebp # ebp = start of string + movl %ebp, %ecx # char past separator decl %ebp .nextc: incl %ebp - movb (%ebp), %dl CC dl = *ebp - cmpb $47, %dl CC dl == '\?'? + movb (%ebp), %dl # dl = *ebp + cmpb $47, %dl # dl == '\?'? jne .nextc1 - leal 1(%ebp), %ecx CC ecx = char past separator + leal 1(%ebp), %ecx # ecx = char past separator .nextc1: - cmpb $0, %dl CC dl == 0? + cmpb $0, %dl # dl == 0? jne .nextc - addl $4, %ebp CC adjust past ebp prior to rounding - andl $-4, %ebp CC round ebp up to the next long - testl $16, (%esi) CC original action number & 16? + addl $4, %ebp # adjust past ebp prior to rounding + andl $-4, %ebp # round ebp up to the next long + testl $16, (%esi) # original action number & 16? jz .primary - movl %eax, 4(%esp) CC secondary fd = eax + movl %eax, 4(%esp) # secondary fd = eax jmp .next_action .primary: pushl %ebp - xorl %esi, %esi CC arg3 - movl %eax, 4(%esp) CC primary fd = eax - xorl %edx, %edx CC arg2 - movl $15, %ebx CC PR_SET_NAME, arg1 = ecx - xorl %edi, %edi CC arg4 - movl $172, %eax CC SYS_prctl - xorl %ebp, %ebp CC arg5 - int $0x80 CC syscall + xorl %esi, %esi # arg3 + movl %eax, 4(%esp) # primary fd = eax + xorl %edx, %edx # arg2 + movl $15, %ebx # PR_SET_NAME, arg1 = ecx + xorl %edi, %edi # arg4 + movl $172, %eax # SYS_prctl + xorl %ebp, %ebp # arg5 + int $0x80 # syscall popl %ebp jmp .next_action .perror: @@ -137,28 +134,28 @@ dnl int $0x80 movl $1, %eax int $0x80 .rest_of_exec: - movl 8(%esp), %ecx CC ecx = original stack pointer - movl (%ecx), %esi CC esi = argc - leal 8(%ecx, %esi, 4), %ecx CC ecx = start of environ + movl 8(%esp), %ecx # ecx = original stack pointer + movl (%ecx), %esi # esi = argc + leal 8(%ecx, %esi, 4), %ecx # ecx = start of environ .skip_environ: - movl (%ecx), %esi CC envp[N] + movl (%ecx), %esi # envp[N] addl $4, %ecx - testl %esi, %esi CC envp[n] ? - jnz .skip_environ CC otherwise, esi is now at the start of auxv + testl %esi, %esi # envp[n] ? + jnz .skip_environ # otherwise, esi is now at the start of auxv .one_auxv: - movl (%ecx), %esi CC auxv type - leal 8(%ecx), %ecx CC skip to next auxv - testl %esi, %esi CC is 0? + movl (%ecx), %esi # auxv type + leal 8(%ecx), %ecx # skip to next auxv + testl %esi, %esi # is 0? jz .cleanup - cmpl $3, %esi CC is AT_PHDR + cmpl $3, %esi # is AT_PHDR je .replace_phdr - cmpl $4, %esi CC is AT_PHENT? + cmpl $4, %esi # is AT_PHENT? je .replace_phent - cmpl $5, %esi CC is AT_PHNUM? + cmpl $5, %esi # is AT_PHNUM? je .replace_phnum - cmpl $9, %esi CC is AT_ENTRY? + cmpl $9, %esi # is AT_ENTRY? je .replace_entry - cmpl $7, %esi CC is AT_BASE + cmpl $7, %esi # is AT_BASE je .replace_base jmp .one_auxv .replace_phdr: @@ -182,21 +179,21 @@ dnl int $0x80 movl %esi, -4(%ecx) jmp .one_auxv .cleanup: - movl $6, %eax CC SYS_close - cmpl $-1, 4(%esp) CC see if interpreter fd is set + movl $6, %eax # SYS_close + cmpl $-1, 4(%esp) # see if interpreter fd is set je .cleanup_1 movl 4(%esp), %ebx int $0x80 - movl $6, %eax CC SYS_close + movl $6, %eax # SYS_close .cleanup_1: movl (%esp), %ebx int $0x80 .enter: pushl $0 - popfl CC restore floating point state - movl 8(%esp), %esp CC restore initial stack pointer - xorl %edx, %edx CC clear rtld_fini - jmpl *4(%ebp) CC entry + popfl # restore floating point state + movl 8(%esp), %esp # restore initial stack pointer + xorl %edx, %edx # clear rtld_fini + jmpl *4(%ebp) # entry timespec: .long 10 diff --git a/exec/loader-x86_64.s b/exec/loader-x86_64.s index 2ef779e4504..ea2958b91e0 100644 --- a/exec/loader-x86_64.s +++ b/exec/loader-x86_64.s @@ -1,64 +1,61 @@ -define(`CC', ` -dnl') - -CC Copyright (C) 2023-2024 Free Software Foundation, Inc. -CC -CC This file is part of GNU Emacs. -CC -CC GNU Emacs is free software: you can redistribute it and/or modify -CC it under the terms of the GNU General Public License as published -CC by the Free Software Foundation, either version 3 of the License, -CC or (at your option) any later version. -CC -CC GNU Emacs is distributed in the hope that it will be useful, but -CC WITHOUT ANY WARRANTY; without even the implied warranty of -CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -CC General Public License for more details. -CC -CC You should have received a copy of the GNU General Public License -CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. +# Copyright (C) 2023-2024 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/>. .section .text .global _start _start: -dnl movq $35, %rax CC SYS_nanosleep -dnl leaq timespec(%rip), %rdi -dnl xorq %rsi, %rsi -dnl syscall - popq %r13 CC original SP - popq %r15 CC size of load area. - movq $-1, %r12 CC r12 is the interpreter fd +# movq $35, %rax # SYS_nanosleep +# leaq timespec(%rip), %rdi +# xorq %rsi, %rsi +# syscall + popq %r13 # original SP + popq %r15 # size of load area. + movq $-1, %r12 # r12 is the interpreter fd .next_action: - movq (%rsp), %r14 CC action number - movq %r14, %r15 CC original action number + movq (%rsp), %r14 # action number + movq %r14, %r15 # original action number andq $-17, %r14 - cmpq $0, %r14 CC open file? + cmpq $0, %r14 # open file? je .open_file - cmpq $3, %r14 CC jump? + cmpq $3, %r14 # jump? je .rest_of_exec - cmpq $4, %r14 CC anonymous mmap? + cmpq $4, %r14 # anonymous mmap? je .do_mmap_anon .do_mmap: - movq $9, %rax CC SYS_mmap - movq 8(%rsp), %rdi CC address - movq 16(%rsp), %r9 CC offset - movq 24(%rsp), %rdx CC protection - movq 32(%rsp), %rsi CC length - movq 40(%rsp), %r10 CC flags - CC set r8 to the primary fd unless r15 & 16 + movq $9, %rax # SYS_mmap + movq 8(%rsp), %rdi # address + movq 16(%rsp), %r9 # offset + movq 24(%rsp), %rdx # protection + movq 32(%rsp), %rsi # length + movq 40(%rsp), %r10 # flags + # set r8 to the primary fd unless r15 & 16 testq $16, %r15 movq %r12, %r8 cmovzq %rbx, %r8 .do_mmap_1: syscall - cmpq $-1, %rax CC mmap failed + cmpq $-1, %rax # mmap failed je .perror - movq 48(%rsp), %r9 CC clear + movq 48(%rsp), %r9 # clear testq %r9, %r9 jz .continue - movq 8(%rsp), %r10 CC start of mapping - addq 32(%rsp), %r10 CC end of mapping - subq %r9, %r10 CC start of clear area + movq 8(%rsp), %r10 # start of mapping + addq 32(%rsp), %r10 # end of mapping + subq %r9, %r10 # start of clear area .again: testq %r9, %r9 jz .continue @@ -69,124 +66,124 @@ dnl syscall leaq 56(%rsp), %rsp jmp .next_action .do_mmap_anon: - movq $9, %rax CC SYS_mmap - movq 8(%rsp), %rdi CC address - movq 16(%rsp), %r9 CC offset - movq 24(%rsp), %rdx CC protection - movq 32(%rsp), %rsi CC length - movq 40(%rsp), %r10 CC flags - movq $-1, %r8 CC -1 + movq $9, %rax # SYS_mmap + movq 8(%rsp), %rdi # address + movq 16(%rsp), %r9 # offset + movq 24(%rsp), %rdx # protection + movq 32(%rsp), %rsi # length + movq 40(%rsp), %r10 # flags + movq $-1, %r8 # -1 jmp .do_mmap_1 .open_file: - movq $2, %rax CC SYS_open - leaq 8(%rsp), %rdi CC rdi = %rsp + 8 - xorq %rsi, %rsi CC flags = O_RDONLY - xorq %rdx, %rdx CC mode = 0 + movq $2, %rax # SYS_open + leaq 8(%rsp), %rdi # rdi = %rsp + 8 + xorq %rsi, %rsi # flags = O_RDONLY + xorq %rdx, %rdx # mode = 0 syscall - cmpq $-1, %rax CC open failed + cmpq $-1, %rax # open failed jle .perror - movq %rdi, %rsp CC rsp = start of string + movq %rdi, %rsp # rsp = start of string subq $1, %rsp - movq %rsp, %r14 CC r14 = start of string + movq %rsp, %r14 # r14 = start of string .nextc: addq $1, %rsp - movb (%rsp), %dil CC rdi = *rsp - cmpb $47, %dil CC *rsp == '/'? + movb (%rsp), %dil # rdi = *rsp + cmpb $47, %dil # *rsp == '/'? jne .nextc1 - movq %rsp, %r14 CC r14 = rsp - addq $1, %r14 CC r14 = char past separator + movq %rsp, %r14 # r14 = rsp + addq $1, %r14 # r14 = char past separator .nextc1: - cmpb $0, %dil CC *rsp == 0? + cmpb $0, %dil # *rsp == 0? jne .nextc - addq $8, %rsp CC adjust past rsp prior to rounding - andq $-8, %rsp CC round rsp up to the next quad - testq $16, %r15 CC r15 & 16? + addq $8, %rsp # adjust past rsp prior to rounding + andq $-8, %rsp # round rsp up to the next quad + testq $16, %r15 # r15 & 16? jz .primary - movq %rax, %r12 CC otherwise, move fd to r12 + movq %rax, %r12 # otherwise, move fd to r12 jmp .next_action .primary: - movq %rax, %rbx CC if not, move fd to rbx - movq $157, %rax CC SYS_prctl - movq $15, %rdi CC PR_SET_NAME - movq %r14, %rsi CC arg1 - xorq %rdx, %rdx CC arg2 - xorq %r10, %r10 CC arg3 - xorq %r8, %r8 CC arg4 - xorq %r9, %r9 CC arg5 + movq %rax, %rbx # if not, move fd to rbx + movq $157, %rax # SYS_prctl + movq $15, %rdi # PR_SET_NAME + movq %r14, %rsi # arg1 + xorq %rdx, %rdx # arg2 + xorq %r10, %r10 # arg3 + xorq %r8, %r8 # arg4 + xorq %r9, %r9 # arg5 syscall jmp .next_action .perror: - movq %rax, %r12 CC error code + movq %rax, %r12 # error code negq %r12 - movq $1, %rax CC SYS_write - movq $1, %rdi CC stdout - leaq error(%rip), %rsi CC buffer - movq $23, %rdx CC count + movq $1, %rax # SYS_write + movq $1, %rdi # stdout + leaq error(%rip), %rsi # buffer + movq $23, %rdx # count syscall - movq $60, %rax CC SYS_exit - movq %r12, %rdi CC code + movq $60, %rax # SYS_exit + movq %r12, %rdi # code syscall -.rest_of_exec: CC rsp now points to six quads: - movq %rsp, %r8 CC now, they are r8 - movq %r13, %rsp CC restore SP - popq %r10 CC argc - leaq 8(%rsp,%r10,8), %rsp CC now at start of environ +.rest_of_exec: # rsp now points to six quads: + movq %rsp, %r8 # now, they are r8 + movq %r13, %rsp # restore SP + popq %r10 # argc + leaq 8(%rsp,%r10,8), %rsp # now at start of environ .skip_environ: - popq %r10 CC envp[N] - testq %r10, %r10 CC envp[n]? - jnz .skip_environ CC otherwise, rsp is now at the start of auxv + popq %r10 # envp[N] + testq %r10, %r10 # envp[n]? + jnz .skip_environ # otherwise, rsp is now at the start of auxv .one_auxv: - popq %rcx CC auxv type - addq $8, %rsp CC skip value - testq %rcx, %rcx CC is 0? + popq %rcx # auxv type + addq $8, %rsp # skip value + testq %rcx, %rcx # is 0? jz .cleanup - cmpq $3, %rcx CC is AT_PHDR? + cmpq $3, %rcx # is AT_PHDR? je .replace_phdr - cmpq $4, %rcx CC is AT_PHENT? + cmpq $4, %rcx # is AT_PHENT? je .replace_phent - cmpq $5, %rcx CC is AT_PHNUM? + cmpq $5, %rcx # is AT_PHNUM? je .replace_phnum - cmpq $9, %rcx CC is AT_ENTRY? + cmpq $9, %rcx # is AT_ENTRY? je .replace_entry - cmpq $7, %rcx CC is AT_BASE? + cmpq $7, %rcx # is AT_BASE? je .replace_base jmp .one_auxv .replace_phdr: movq 40(%r8), %r9 - movq %r9, -8(%rsp) CC set at_phdr + movq %r9, -8(%rsp) # set at_phdr jmp .one_auxv .replace_phent: movq 24(%r8), %r9 - movq %r9, -8(%rsp) CC set at_phent + movq %r9, -8(%rsp) # set at_phent jmp .one_auxv .replace_phnum: movq 32(%r8), %r9 - movq %r9, -8(%rsp) CC set at_phnum + movq %r9, -8(%rsp) # set at_phnum jmp .one_auxv .replace_entry: movq 16(%r8), %r9 - movq %r9, -8(%rsp) CC set at_entry + movq %r9, -8(%rsp) # set at_entry jmp .one_auxv .replace_base: movq 48(%r8), %r9 - movq %r9, -8(%rsp) CC set at_base + movq %r9, -8(%rsp) # set at_base jmp .one_auxv .cleanup: - movq $3, %rax CC SYS_close - cmpq $-1, %r12 CC see if interpreter fd is set + movq $3, %rax # SYS_close + cmpq $-1, %r12 # see if interpreter fd is set je .cleanup_1 movq %r12, %rdi syscall - movq $3, %rax CC SYS_close + movq $3, %rax # SYS_close .cleanup_1: movq %rbx, %rdi syscall .enter: pushq $0 - popfq CC clear FP state - movq %r13, %rsp CC restore SP - xorq %rdx, %rdx CC clear rtld_fini - jmpq *8(%r8) CC entry + popfq # clear FP state + movq %r13, %rsp # restore SP + xorq %rdx, %rdx # clear rtld_fini + jmpq *8(%r8) # entry error: .ascii "_start: internal error." diff --git a/exec/mipsel-user.h b/exec/mipsel-user.h index 04f4a2a5089..14d8f6d0d5e 100644 --- a/exec/mipsel-user.h +++ b/exec/mipsel-user.h @@ -24,10 +24,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <sys/user.h> -#ifndef ELF_NGREG -#define ELF_NGREG 45 -#endif /* ELF_NGREG */ - /* This file defines a structure containing user mode general purpose @@ -36,7 +32,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ struct mipsel_regs { /* General purpose registers. */ - uint64_t gregs[ELF_NGREG]; + uint64_t gregs[32]; + + /* Saved special registers. */ + uint64_t lo; + uint64_t hi; + uint64_t cp0_epc; + uint64_t cp0_badvaddr; + uint64_t cp0_status; + uint64_t cp0_cause; }; #endif /* _MIPSEL_USER_H_ */ diff --git a/exec/trace.c b/exec/trace.c index 05d862f5b9f..2af6d867efe 100644 --- a/exec/trace.c +++ b/exec/trace.c @@ -49,11 +49,21 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #ifndef SYS_SECCOMP #define SYS_SECCOMP 1 -#endif /* SYS_SECCOMP */ +#endif /* !defined SYS_SECCOMP */ #ifndef PTRACE_GETEVENTMSG #define PTRACE_GETEVENTMSG 0x4201 -#endif /* PTRACE_GETEVENTMSG */ +#endif /* !defined PTRACE_GETEVENTMSG */ + +#ifdef HAVE_SECCOMP +#include <linux/seccomp.h> +#include <linux/filter.h> + +#include <sys/utsname.h> +#include <sys/prctl.h> + +#include <stdio.h> +#endif /* !defined HAVE_SECCOMP */ @@ -70,6 +80,15 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ /* Number of tracees children are allowed to create. */ #define MAX_TRACEES 4096 +#ifdef HAVE_SECCOMP + +/* Whether to enable seccomp acceleration. */ +static bool use_seccomp_p; + +#else /* !HAVE_SECCOMP */ +#define use_seccomp_p (false) +#endif /* HAVE_SECCOMP */ + #ifdef __aarch64__ /* Place PID's registers into *REGS. Return 1 upon failure, else @@ -105,8 +124,7 @@ aarch64_set_regs (pid_t pid, USER_REGS_STRUCT *regs, iov.iov_base = regs; iov.iov_len = sizeof *regs; - rc = ptrace (PTRACE_SETREGSET, pid, NT_PRSTATUS, - &iov); + rc = ptrace (PTRACE_SETREGSET, pid, NT_PRSTATUS, &iov); if (rc < 0) return 1; @@ -367,14 +385,17 @@ remove_tracee (struct exec_tracee *tracee) /* Link the tracee onto the list of free tracees. */ tracee->next = free_tracees; -#ifndef REENTRANT /* Free the exec file, if any. */ free (tracee->exec_file); tracee->exec_file = NULL; -#endif /* REENTRANT */ - free_tracees = tracee; + /* Likewise with any loader instructions that might be + present. */ + free (tracee->exec_data); + tracee->exec_data = NULL; + /* Return this tracee to the list of free ones. */ + free_tracees = tracee; return; } else @@ -419,7 +440,6 @@ find_tracee (pid_t process) static void handle_clone_prepare (struct exec_tracee *parent) { -#ifndef REENTRANT long rc; unsigned long pid; struct exec_tracee *tracee; @@ -440,7 +460,8 @@ handle_clone_prepare (struct exec_tracee *parent) assert (tracee->new_child); tracee->new_child = false; tracee->exec_file = NULL; - ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, 0); if (parent->exec_file) tracee->exec_file = strdup (parent->exec_file); @@ -457,12 +478,9 @@ handle_clone_prepare (struct exec_tracee *parent) tracee = &static_tracees[tracees]; tracees++; } -#ifndef REENTRANT - /* Try to allocate a tracee using `malloc' if this library is - not being built to run inside a signal handler. */ + /* Try to allocate a tracee using `malloc'. */ else if ((tracee = malloc (sizeof *tracee))) ; -#endif /* REENTRANT */ else return; @@ -477,7 +495,6 @@ handle_clone_prepare (struct exec_tracee *parent) if (parent->exec_file) tracee->exec_file = strdup (parent->exec_file); -#endif /* REENTRANT */ } /* Handle the completion of a `clone' or `clone3' system call, @@ -513,21 +530,18 @@ handle_clone (struct exec_tracee *tracee, pid_t pid) tracee = &static_tracees[tracees]; tracees++; } -#ifndef REENTRANT - /* Try to allocate a tracee using `malloc' if this library is - not being built to run inside a signal handler. */ + /* Try to allocate a tracee using `malloc'. */ else if ((tracee = malloc (sizeof *tracee))) ; -#endif /* REENTRANT */ else return 1; tracee->pid = pid; tracee->next = tracing_processes; tracee->waiting_for_syscall = false; -#ifndef REENTRANT tracee->exec_file = NULL; -#endif /* REENTRANT */ + tracee->exec_data = NULL; + tracee->data_size = 0; tracing_processes = tracee; tracee->new_child = true; @@ -549,6 +563,11 @@ handle_clone (struct exec_tracee *tracee, pid_t pid) flags |= PTRACE_O_TRACESYSGOOD; flags |= PTRACE_O_TRACEEXIT; +#ifdef HAVE_SECCOMP + if (use_seccomp_p) + flags |= PTRACE_O_TRACESECCOMP; +#endif /* HAVE_SECCOMP */ + rc = ptrace (PTRACE_SETOPTIONS, pid, 0, flags); if (rc) @@ -559,7 +578,8 @@ handle_clone (struct exec_tracee *tracee, pid_t pid) /* The new tracee is currently stopped. Continue it until the next system call. */ - rc = ptrace (PTRACE_SYSCALL, pid, 0, 0); + rc = ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, 0); if (rc) goto bail; @@ -618,9 +638,11 @@ check_signal (struct exec_tracee *tracee, int status) { if (siginfo.si_code < 0) /* SIGTRAP delivered from userspace. Pass it on. */ - ptrace (PTRACE_SYSCALL, tracee->pid, 0, SIGTRAP); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, SIGTRAP); else - ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, 0); return 1; } @@ -639,26 +661,28 @@ check_signal (struct exec_tracee *tracee, int status) it. */ #ifdef HAVE_SIGINFO_T_SI_SYSCALL #ifndef __arm__ - ptrace (PTRACE_SYSCALL, tracee->pid, + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), tracee->pid, 0, ((siginfo.si_code == SYS_SECCOMP && siginfo.si_syscall == -1) ? 0 : status)); #else /* __arm__ */ - ptrace (PTRACE_SYSCALL, tracee->pid, + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), tracee->pid, 0, ((siginfo.si_code == SYS_SECCOMP && siginfo.si_syscall == 222) ? 0 : status)); #endif /* !__arm__ */ #else /* !HAVE_SIGINFO_T_SI_SYSCALL */ /* Drop this signal, since what caused it is unknown. */ - ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), tracee->pid, + 0, 0); #endif /* HAVE_SIGINFO_T_SI_SYSCALL */ return 1; #endif /* SIGSYS */ default: /* Continue the process until the next syscall. */ - ptrace (PTRACE_SYSCALL, tracee->pid, 0, status); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, status); return 1; } @@ -667,17 +691,16 @@ check_signal (struct exec_tracee *tracee, int status) -/* Handle an `exec' system call from the given TRACEE. REGS are the - tracee's current user-mode registers. +/* Handle the first stage of an `exec' system call from the given + TRACEE. REGS are the tracee's current user-mode registers. Rewrite the system call arguments to use the loader binary. Then, - continue the system call until the loader is loaded. Write the - information necessary to load the original executable into the - loader's stack. + resume the process till the loader is loaded and about to begin + execution. Save instructions to load the original executable into + TRACEE->exec_data. Value is 0 upon success, 1 upon a generic failure before the loader - is loaded, 2 if the process has stopped, and 3 if something failed, - but it is too late to handle it. + is loaded. Set errno appropriately upon returning a generic failure. */ @@ -687,16 +710,10 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) char buffer[PATH_MAX + 80], *area; USER_REGS_STRUCT original; size_t size, loader_size; - USER_WORD loader, size1, sp; - int rc, wstatus; - siginfo_t siginfo; - - /* Save the old stack pointer. */ - sp = regs->STACK_POINTER; + USER_WORD loader; /* Read the file name. */ - read_memory (tracee, buffer, PATH_MAX, - regs->SYSCALL_ARG_REG); + read_memory (tracee, buffer, PATH_MAX, regs->SYSCALL_ARG_REG); /* Make sure BUFFER is NULL terminated. */ @@ -722,8 +739,18 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) return 1; } - /* Rewrite the first argument to point to the loader. */ + /* Save this area in the tracee. */ + assert (!tracee->exec_data); + tracee->exec_data = malloc (size); + if (!tracee->exec_data) + { + errno = ENOMEM; + return 1; + } + memcpy (tracee->exec_data, area, size); + tracee->data_size = size; + /* Rewrite the first argument to point to the loader. */ loader_size = strlen (loader_name) + 1; loader = user_alloca (tracee, &original, regs, loader_size); @@ -731,14 +758,14 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) if (!loader) { errno = ENOMEM; - return 1; + goto free_data_error; } if (user_copy (tracee, (unsigned char *) loader_name, loader, loader_size)) { errno = EIO; - return 1; + goto free_data_error; } regs->SYSCALL_ARG_REG = loader; @@ -748,151 +775,118 @@ handle_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) if (aarch64_set_regs (tracee->pid, regs, false)) { errno = EIO; - return 1; + goto free_data_error; } #else /* !__aarch64__ */ - if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, - regs)) + if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs)) { errno = EIO; - return 1; + goto free_data_error; } #endif /* __aarch64__ */ - /* Continue the system call until loader starts. */ + /* Resume the process till the loader is executed. */ if (ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL)) { errno = EIO; - return 1; + goto free_data_error; } -#ifndef REENTRANT - /* Now that the loader has started, record the value to use for - /proc/self/exe. Don't give up just because strdup fails. + /* Now that the loader has been executed, record the value to + substitute for /proc/self/exe. Don't give up just because strdup + fails. Note that exec_0 copies the absolute file name into buffer. */ if (tracee->exec_file) free (tracee->exec_file); tracee->exec_file = strdup (buffer); -#endif /* REENTRANT */ - - again: - rc = waitpid (tracee->pid, &wstatus, __WALL); - if (rc == -1 && errno == EINTR) - goto again; - - if (rc < 0) - return 1; - - if (!WIFSTOPPED (wstatus)) - /* The process has been killed in response to a signal. - In this case, simply return 2. */ - return 2; - else - { - /* Then, check if STATUS is not a syscall-stop, and try again if - it isn't. */ - rc = check_signal (tracee, wstatus); - - if (rc == -1) - return 2; - else if (rc) - goto again; - - /* Retrieve the signal information and determine whether or not - the system call has completed. */ - - if (ptrace (PTRACE_GETSIGINFO, tracee->pid, 0, - &siginfo)) - return 3; - - if (!syscall_trap_p (&siginfo)) - { - /* Continue. */ - if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0)) - return 3; - - goto again; - } - } - -#ifdef __aarch64__ - - if (aarch64_get_regs (tracee->pid, &original)) - return 3; + return 0; -#else /* !__aarch64__ */ + free_data_error: + free (tracee->exec_data); + tracee->exec_data = NULL; + return 1; +} - /* The system call has now completed. Get the registers again. */ +/* Complete an `exec' system call issued by TRACEE. Write the + instructions stored in TRACEE->exec_data to an appropriate location + in TRACEE's stack, and resume TRACEE, releasing TRACEE->exec_data. + REGS should be the TRACEE's user registers. If the reissued system + call did not succeed in starting the executable loader, restore + TRACEE->sp (recorded by process_system_call or seccomp_system_call), + and resume execution, so that the failure may be reported. */ - if (ptrace (PTRACE_GETREGS, tracee->pid, NULL, - &original)) - return 3; +static void +finish_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) +{ + USER_WORD size1, loader; + USER_REGS_STRUCT original; -#endif /* __aarch64__ */ + size1 = tracee->data_size; - *regs = original; + /* Record the registers' values as they originally were. */ + memcpy (&original, regs, sizeof *regs); - /* Upon failure, wait for the next system call and return - success. */ + /* Any non-zero value of `original.SYSCALL_RET_REG' indicates that the + reissued `exec' call was unsuccessful, and the loader is not + executing. Restore the previous stack pointer and permit the + tracee to run to completion. */ if (original.SYSCALL_RET_REG) { - /* Restore the original stack pointer. */ - regs->STACK_POINTER = sp; - + regs->STACK_POINTER = tracee->sp; #ifdef __aarch64__ aarch64_set_regs (tracee->pid, regs, false); #else /* !__aarch64__ */ ptrace (PTRACE_SETREGS, tracee->pid, NULL, regs); #endif /* __aarch64__ */ - goto exec_failure; + /* Continue; not much in the way of remediation is available if + either of PTRACE_SETREGS and this resumption fails. */ + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, 0); + goto error; } /* Write the loader area to the stack, followed by its size and the original stack pointer. */ loader = user_alloca (tracee, &original, regs, - size + sizeof loader * 2); + size1 + sizeof loader * 2); if (!loader) - return 3; - - size1 = size; + goto error; #ifndef STACK_GROWS_DOWNWARDS - - NOT_IMPLEMENTED; - + not implemented, you lose. #else /* STACK_GROWS_DOWNWARDS */ - if (user_copy (tracee, (unsigned char *) area, - loader + sizeof size1 * 2, size) + if (user_copy (tracee, (unsigned char *) tracee->exec_data, + loader + sizeof size1 * 2, size1) || user_copy (tracee, (unsigned char *) &size1, loader + sizeof size1, sizeof size1)) - return 3; + goto error; size1 = original.STACK_POINTER; if (user_copy (tracee, (unsigned char *) &size1, loader, sizeof size1)) - return 3; + goto error; #endif /* STACK_GROWS_DOWNWARDS */ /* Continue. */ - if (ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0)) - return 3; - - return 0; + if (ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, 0)) + goto error; - exec_failure: - return 3; + error: + free (tracee->exec_data); + tracee->exec_data = NULL; } @@ -1007,13 +1001,6 @@ static int handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs, struct exec_tracee *tracee, USER_WORD *result) { -#ifdef REENTRANT - /* readlinkat cannot be handled specially when the library is built - to be reentrant, as the file name information cannot be - recorded. */ - return 0; -#else /* !REENTRANT */ - char buffer[PATH_MAX + 1]; USER_WORD address, return_buffer, size; size_t length; @@ -1086,7 +1073,6 @@ handle_readlinkat (USER_WORD callno, USER_REGS_STRUCT *regs, *result = length; return 2; -#endif /* REENTRANT */ } /* Handle an `open' or `openat' system call. @@ -1104,12 +1090,6 @@ static int handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs, struct exec_tracee *tracee, USER_WORD *result) { -#ifdef REENTRANT - /* readlinkat cannot be handled specially when the library is built - to be reentrant, as the file name information cannot be - recorded. */ - return 0; -#else /* !REENTRANT */ char buffer[PATH_MAX + 1]; USER_WORD address; size_t length; @@ -1199,7 +1179,6 @@ handle_openat (USER_WORD callno, USER_REGS_STRUCT *regs, fail: errno = EIO; return 1; -#endif /* REENTRANT */ } /* Process the system call at which TRACEE is stopped. If the system @@ -1229,30 +1208,43 @@ process_system_call (struct exec_tracee *tracee) /* Save the stack pointer. */ sp = regs.STACK_POINTER; - /* Now dispatch based on the system call. */ - callno = regs.SYSCALL_NUM_REG; + /* Now dispatch based on the system call. If TRACEE->exec_data is + set, this must be exec, whatever the value of SYSCALL_NUM_REG, + which is erased when exec loads another image. */ + + callno = (!tracee->exec_data ? regs.SYSCALL_NUM_REG : EXEC_SYSCALL); switch (callno) { case EXEC_SYSCALL: - /* exec system calls should be handled synchronously. */ - assert (!tracee->waiting_for_syscall); - rc = handle_exec (tracee, ®s); - - switch (rc) + if (!tracee->waiting_for_syscall) { - case 3: - /* It's too late to do anything about this error,. */ - break; + /* The outstanding syscall flag must not be inconsistent with + the presence of instructions for the loader. */ + assert (!tracee->exec_data); + rc = handle_exec (tracee, ®s); - case 2: - /* The process has gone away. */ - remove_tracee (tracee); - break; + if (rc) + /* An error has occurred; errno is set to the error. */ + goto report_syscall_error; + + /* The process has been resumed. Assert that the instructions + for loading this executable have been generated and + recorded, and set waiting_for_syscall. */ + tracee->waiting_for_syscall = true; + assert (tracee->exec_data); - case 1: - /* An error has occurred; errno is set to the error. */ - goto report_syscall_error; + /* Record the initial stack pointer also. */ + tracee->sp = sp; + } + else + { + assert (tracee->exec_data); + finish_exec (tracee, ®s); + + /* The process has been resumed and has become capable of + executing independently. */ + tracee->waiting_for_syscall = false; } break; @@ -1311,7 +1303,7 @@ process_system_call (struct exec_tracee *tracee) regs.STACK_POINTER = tracee->sp; #ifdef __aarch64__ - if (aarch64_set_regs (tracee->pid, ®s, true)) + if (aarch64_set_regs (tracee->pid, ®s, false)) return; #else /* !__aarch64__ */ if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s)) @@ -1327,11 +1319,35 @@ process_system_call (struct exec_tracee *tracee) will DTRT upon the next call to PTRACE_SYSCALL after the syscall-trap signal is delivered. */ - rc = ptrace (PTRACE_SYSCALL, tracee->pid, + rc = ptrace (((use_seccomp_p + /* open and openat are not processed synchronously, + nor can they afford to dispense with + post-syscall finalization. */ + + && ((callno != OPENAT_SYSCALL +#ifdef OPEN_SYSCALL + && callno != OPEN_SYSCALL +#endif /* OPEN_SYSCALL */ + ) + /* Since syscall initialization should be + reserved for seccomp_system_call, resume the + process if this system call is already + complete. */ + || !tracee->waiting_for_syscall)) + ? PTRACE_CONT : PTRACE_SYSCALL), tracee->pid, NULL, NULL); if (rc < 0) return; +#ifdef HAVE_SECCOMP + if (!(use_seccomp_p + && ((callno != OPENAT_SYSCALL +#ifdef OPEN_SYSCALL + && callno != OPEN_SYSCALL +#endif /* OPEN_SYSCALL */ + ) + || !tracee->waiting_for_syscall))) +#endif /* !HAVE_SECCOMP */ tracee->waiting_for_syscall = !tracee->waiting_for_syscall; } @@ -1345,9 +1361,10 @@ process_system_call (struct exec_tracee *tracee) reporting_error = false; common: - /* Reporting an error or emulating a system call works by setting - the system call number to -1, letting it continue, and then - substituting errno for ENOSYS in the case of an error. + /* Reporting an error or emulating a system call works by replacing + the system call number with -1 or another nonexistent syscall, + letting it continue, and then substituting errno for ENOSYS in the + case of an error. Make sure that the stack pointer is restored to its original position upon exit, or bad things can happen. */ @@ -1426,13 +1443,13 @@ process_system_call (struct exec_tracee *tracee) #endif /* __aarch64__ */ /* Now wait for the next system call to happen. */ - ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, NULL, NULL); } else { /* No error is being reported. Return the result in the appropriate registers. */ - #ifdef __mips__ /* MIPS systems place errno in v0 and set a3 to 1. */ regs.gregs[2] = result; @@ -1449,14 +1466,367 @@ process_system_call (struct exec_tracee *tracee) #endif /* __aarch64__ */ /* Now wait for the next system call to happen. */ - ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, NULL, NULL); } } +#ifdef HAVE_SECCOMP + +/* Seccomp acceleration. + + Seccomp enables selectively filtering signals so that the tracing + process is only notified of such system calls as it is interested in + intercepting, i.e., exec and open*. This improves performance + enormously over the traditional approach of pausing the tracee before + each system call. */ + +/* Whether the kernel's version is 4.7.x or earlier. */ +static bool kernel_4_7_or_earlier; + +/* Array of system calls this module is interested in intercepting. */ +static int interesting_syscalls[] = + { + EXEC_SYSCALL, +#ifdef OPEN_SYSCALL + OPEN_SYSCALL, +#endif /* OPEN_SYSCALL */ + OPENAT_SYSCALL, +#ifdef READLINK_SYSCALL + READLINK_SYSCALL, +#endif /* READLINK_SYSCALL */ + READLINKAT_SYSCALL, + }; + +/* Number of elements in an array. */ +#define ARRAYELTS(arr) (sizeof (arr) / sizeof (arr)[0]) + +/* Install a secure computing filter that will notify attached tracers + when a system call of interest to this module is received. Value is + 0 if successful, 1 otherwise. */ + +static int +establish_seccomp_filter (void) +{ + struct sock_filter statements[1 + ARRAYELTS (interesting_syscalls) + 2]; + struct sock_fprog program; + int index, rc; + + index = 0; + + /* As the exec wrapper will reject executables for an inappropriate + architecture, verifying the same here would only be redundant. + Proceed to load the current system call number. */ + + statements[index++] = ((struct sock_filter) + BPF_STMT (BPF_LD + BPF_W + BPF_ABS, + offsetof (struct seccomp_data, nr))); + + /* Search for system calls of interest. */ + + statements[index] + = ((struct sock_filter) + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, EXEC_SYSCALL, + ARRAYELTS (interesting_syscalls), 0)); index++; +#ifdef OPEN_SYSCALL + statements[index] + = ((struct sock_filter) + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, OPEN_SYSCALL, + ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; +#endif /* OPEN_SYSCALL */ + statements[index] + = ((struct sock_filter) + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, OPENAT_SYSCALL, + ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; +#ifdef READLINK_SYSCALL + statements[index] + = ((struct sock_filter) + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, READLINK_SYSCALL, + ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; +#endif /* READLINK_SYSCALL */ + statements[index] + = ((struct sock_filter) + BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K, READLINKAT_SYSCALL, + ARRAYELTS (interesting_syscalls) - index + 1, 0)); index++; + + /* If not intercepted above, permit this system call to execute as + normal. */ + statements[index++] + = (struct sock_filter) BPF_STMT (BPF_RET + BPF_K, SECCOMP_RET_ALLOW); + statements[index++] + = (struct sock_filter) BPF_STMT (BPF_RET + BPF_K, SECCOMP_RET_TRACE); + + rc = prctl (PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + if (rc) + return 1; + + program.len = ARRAYELTS (statements); + program.filter = statements; + rc = prctl (PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &program); + if (rc) + return 1; + + return 0; +} + +/* Intercept or resume and dismiss the system call at which TRACEE is + paused, similarly to process_system_call. */ + +static void +seccomp_system_call (struct exec_tracee *tracee) +{ + USER_REGS_STRUCT regs; + int rc, wstatus, save_errno; + USER_WORD callno, sp; + USER_WORD result; + bool reporting_error; + + if (kernel_4_7_or_earlier) + { + /* On kernel 4.7 and earlier, following a PTRACE_EVENT_SECCOMP by + a PTRACE_SYSCALL will give rise to a syscall-entry stop event, + and seccomp filters will be suppressed till the system call + runs its course. */ + ptrace (PTRACE_SYSCALL, tracee->pid, 0, 0); + return; + } + +#ifdef __aarch64__ + rc = aarch64_get_regs (tracee->pid, ®s); +#else /* !__aarch64__ */ + rc = ptrace (PTRACE_GETREGS, tracee->pid, NULL, + ®s); +#endif /* __aarch64__ */ + + /* TODO: what to do if this fails? */ + if (rc < 0) + return; + + /* On kernel 4.8, processes resumed after being paused so as to + produce a PTRACE_EVENT_SECCOMP will execute till the system call + completes, or indefinitely if resumed with PTRACE_CONT. + + In this context processes are resumed with PTRACE_CONT unless it is + an `open' syscall that is being intercepted, which, if successfully + intercepted, they must receive adjustments to their stack pointer + upon completion of said system call. */ + assert (!tracee->waiting_for_syscall); + + /* Save the stack pointer. */ + sp = regs.STACK_POINTER; + + /* Now dispatch based on the system call. */ + callno = regs.SYSCALL_NUM_REG; + switch (callno) + { + case EXEC_SYSCALL: + assert (!tracee->exec_data); + rc = handle_exec (tracee, ®s); + + if (rc) + /* An error has occurred; errno is set to the error. */ + goto report_syscall_error; + + /* The process has been resumed. Assert that the instructions for + loading this executable have been generated and recorded, and + set waiting_for_syscall. */ + tracee->waiting_for_syscall = true; + assert (tracee->exec_data); + + /* Record the initial stack pointer also. */ + tracee->sp = sp; + break; + +#ifdef READLINK_SYSCALL + case READLINK_SYSCALL: +#endif /* READLINK_SYSCALL */ + case READLINKAT_SYSCALL: + /* Handle this readlinkat system call. */ + rc = handle_readlinkat (callno, ®s, tracee, + &result); + + /* rc means the same as in `handle_exec'. */ + + if (rc == 1) + goto report_syscall_error; + else if (rc == 2) + goto emulate_syscall; + + goto continue_syscall; + +#ifdef OPEN_SYSCALL + case OPEN_SYSCALL: +#endif /* OPEN_SYSCALL */ + case OPENAT_SYSCALL: + /* Handle this open system call. */ + rc = handle_openat (callno, ®s, tracee, &result); + + /* rc means the same as in `handle_exec', except that `open' + is never emulated. */ + + if (rc == 1) + goto report_syscall_error; + + /* The stack pointer must be restored after it was modified + by `user_alloca'; record sp in TRACEE, which will be + restored after this system call completes. */ + tracee->sp = sp; + + /* As such, arrange to enter `process_system_call' on its + completion. */ + rc = ptrace (PTRACE_SYSCALL, tracee->pid, + NULL, NULL); + if (rc < 0) + return; + + tracee->waiting_for_syscall = !tracee->waiting_for_syscall; + break; + + default: + continue_syscall: + rc = ptrace (PTRACE_CONT, tracee->pid, NULL, NULL); + if (rc < 0) + return; + } + + return; + + report_syscall_error: + reporting_error = true; + goto common; + + emulate_syscall: + reporting_error = false; + common: + + /* Reporting an error or emulating a system call works by replacing + the system call number with -1 or another nonexistent syscall, + letting it continue, and then substituting errno for ENOSYS in the + case of an error. + + Make sure that the stack pointer is restored to its original + position upon exit, or bad things can happen. */ + + /* First, save errno; system calls below will clobber it. */ + save_errno = errno; + + regs.SYSCALL_NUM_REG = -1; + regs.STACK_POINTER = sp; + +#ifdef __aarch64__ + if (aarch64_set_regs (tracee->pid, ®s, true)) + return; +#else /* !__aarch64__ */ + +#ifdef __arm__ + /* On ARM systems, a special request is used to update the system + call number as known to the kernel. In addition, the system call + number must be valid, so use `tuxcall'. Hopefully, nobody will + run this on a kernel with Tux. */ + + if (ptrace (PTRACE_SET_SYSCALL, tracee->pid, NULL, 222)) + return; +#endif /* __arm__ */ + + if (ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s)) + return; +#endif /* __aarch64__ */ + + /* Do this invalid system call. */ + if (ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL)) + return; + + again1: + rc = waitpid (tracee->pid, &wstatus, __WALL); + if (rc == -1 && errno == EINTR) + goto again1; + + /* Return if waitpid fails. */ + + if (rc == -1) + return; + + /* If the process received a signal, see if the signal is SIGSYS + and/or from seccomp. If so, discard it. */ + + if (WIFSTOPPED (wstatus)) + { + rc = check_signal (tracee, wstatus); + + if (rc == -1) + return; + else if (rc) + goto again1; + } + + if (!WIFSTOPPED (wstatus)) + /* The process has been killed in response to a signal. In this + case, simply unlink the tracee and return. */ + remove_tracee (tracee); + else if (reporting_error) + { +#ifdef __mips__ + /* MIPS systems place errno in v0 and set a3 to 1. */ + regs.gregs[2] = save_errno; + regs.gregs[7] = 1; +#else /* !__mips__ */ + regs.SYSCALL_RET_REG = -save_errno; +#endif /* __mips__ */ + + /* Report errno. */ +#ifdef __aarch64__ + aarch64_set_regs (tracee->pid, ®s, false); +#else /* !__aarch64__ */ + ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s); +#endif /* __aarch64__ */ + + /* Resume the process till the next interception by its filter. */ + ptrace (PTRACE_CONT, tracee->pid, NULL, NULL); + } + else + { + /* No error is being reported. Return the result in the + appropriate registers. */ + +#ifdef __mips__ + /* MIPS systems place errno in v0 and set a3 to 1. */ + regs.gregs[2] = result; + regs.gregs[7] = 0; +#else /* !__mips__ */ + regs.SYSCALL_RET_REG = result; +#endif /* __mips__ */ + + /* Report errno. */ +#ifdef __aarch64__ + aarch64_set_regs (tracee->pid, ®s, false); +#else /* !__aarch64__ */ + ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s); +#endif /* __aarch64__ */ + + /* Resume the process till the next interception by its filter. */ + ptrace (PTRACE_CONT, tracee->pid, NULL, NULL); + } +} + +#ifndef PTRACE_EVENT_SECCOMP +#define PTRACE_EVENT_SECCOMP 7 +#endif /* !PTRACE_EVENT_SECCOMP */ + +#ifndef PTRACE_O_TRACESECCOMP +#define PTRACE_O_TRACESECCOMP (1 << PTRACE_EVENT_SECCOMP) +#endif /* !PTRACE_O_TRACESECCOMP */ + +#ifndef SIGSYS +#define SIGSYS 31 +#endif /* !SIGSYS */ +#endif /* HAVE_SECCOMP */ + + + /* Like `execve', but asks the parent to begin tracing this thread. - Fail if tracing is unsuccessful. */ + Fail by returning a non-zero value if tracing is unsuccessful. */ int tracing_execve (const char *file, char *const *argv, @@ -1471,6 +1841,13 @@ tracing_execve (const char *file, char *const *argv, /* Notify the parent to enter signal-delivery-stop. */ raise (SIGSTOP); + +#ifdef HAVE_SECCOMP + /* Install the seccomp filter. */ + if (use_seccomp_p && establish_seccomp_filter ()) + return 1; +#endif /* HAVE_SECCOMP */ + return execve (file, argv, envp); } @@ -1486,6 +1863,10 @@ after_fork (pid_t pid) { int wstatus, rc, flags; struct exec_tracee *tracee; +#if defined HAVE_SECCOMP && __ANDROID__ + int statusarg; + USER_REGS_STRUCT regs; +#endif /* defined HAVE_SECCOMP && __ANDROID__ */ /* First, wait for something to happen to PID. */ again: @@ -1510,6 +1891,10 @@ after_fork (pid_t pid) flags |= PTRACE_O_TRACEFORK; flags |= PTRACE_O_TRACESYSGOOD; flags |= PTRACE_O_TRACEEXIT; +#ifdef HAVE_SECCOMP + if (use_seccomp_p) + flags |= PTRACE_O_TRACESECCOMP; +#endif /* HAVE_SECCOMP */ rc = ptrace (PTRACE_SETOPTIONS, pid, 0, flags); @@ -1521,12 +1906,86 @@ after_fork (pid_t pid) return 1; } - /* Request that the child stop upon the next system call. */ - rc = ptrace (PTRACE_SYSCALL, pid, 0, 0); +#if defined HAVE_SECCOMP && __ANDROID__ + /* Certain Android kernels have received backports of those new + PTRACE_EVENT_SECCOMP semantics which were introduced in kernel + version 4.8, so that it is necessary to actively establish which + variant is in place. */ + + if (kernel_4_7_or_earlier && use_seccomp_p) + { + /* Request that the child stop upon the next `exec' system call, + one of which is assumed to always be issued by the child, as + below, but await the next stop, and examine its contents. + Anciently, the syscall-stop preceeded events marked + PTRACE_EVENT_SECCOMP, whereas this sequence is reversed in + 4.8+, and in releases with these changes backported. */ + + rc = ptrace (PTRACE_SYSCALL, pid, 0, 0); + if (rc) + return 1; + + while (true) + { + rc = waitpid (pid, &wstatus, __WALL); + if (rc != pid) + return 1; + + if (WIFSTOPPED (wstatus)) + { + /* Verify that this system call is `exec', not one issued + between PTRACE_TRACEME and `exec' intercepted by + PTRACE_SYSCALL. */ +#ifdef __aarch64__ + rc = aarch64_get_regs (pid, ®s); +#else /* !__aarch64__ */ + rc = ptrace (PTRACE_GETREGS, pid, NULL, ®s); +#endif /* __aarch64__ */ + if (rc) + return 1; + + if (regs.SYSCALL_NUM_REG == EXEC_SYSCALL) + { + statusarg = ((wstatus & 0xfff00) >> 8); + + if (statusarg == (SIGTRAP | (PTRACE_EVENT_SECCOMP << 8))) + { + /* The first event to be delivered is a seccomp + stop, indicating that this is an unmodified + <4.7 kernel. Return to await the subsequent + syscall-stop, which should be received and + acted on by process_system_call. */ + rc = ptrace (PTRACE_SYSCALL, pid, 0, 0); + break; + } + else if (statusarg == (SIGTRAP | 0x80)) + { + /* Syscall-traps take priority. This is a + doctored 4.7 kernel. */ + kernel_4_7_or_earlier = false; + rc = ptrace (PTRACE_CONT, pid, 0, 0); + break; + } + } + + rc = ptrace (PTRACE_SYSCALL, pid, 0, 0); + if (rc) + return 1; + } + else + return 1; + } + } + else +#endif /* HAVE_SECCOMP && __ANDROID__ */ + /* Request that the child stop upon the next system call, or the + next filter event. */ + rc = ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, 0); if (rc) return 1; - /* Enter the child in `tracing_processes'. */ + /* Enroll the child into `tracing_processes'. */ if (free_tracees) { @@ -1543,9 +2002,9 @@ after_fork (pid_t pid) tracee->next = tracing_processes; tracee->waiting_for_syscall = false; tracee->new_child = false; -#ifndef REENTRANT tracee->exec_file = NULL; -#endif /* REENTRANT */ + tracee->exec_data = NULL; + tracee->data_size = 0; tracing_processes = tracee; return 0; } @@ -1604,9 +2063,11 @@ exec_waitpid (pid_t pid, int *wstatus, int options) { if (siginfo.si_code < 0) /* SIGTRAP delivered from userspace. Pass it on. */ - ptrace (PTRACE_SYSCALL, pid, 0, SIGTRAP); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, SIGTRAP); else - ptrace (PTRACE_SYSCALL, pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, 0); return -1; } @@ -1644,8 +2105,16 @@ exec_waitpid (pid_t pid, int *wstatus, int options) /* These events are handled by tracing SIGSTOP signals sent to unknown tracees. Make sure not to pass through status, as there's no signal really being delivered. */ - ptrace (PTRACE_SYSCALL, pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), pid, 0, 0); + return -1; + +#ifdef HAVE_SECCOMP + case SIGTRAP | (PTRACE_EVENT_SECCOMP << 8): + /* Intercept and process this system call if the event was + produced by our filter. */ + seccomp_system_call (tracee); return -1; +#endif /* HAVE_SECCOMP */ #ifdef SIGSYS case SIGSYS: @@ -1657,24 +2126,28 @@ exec_waitpid (pid_t pid, int *wstatus, int options) it. */ #ifdef HAVE_SIGINFO_T_SI_SYSCALL #ifndef __arm__ - ptrace (PTRACE_SYSCALL, pid, 0, ((siginfo.si_code == SYS_SECCOMP - && siginfo.si_syscall == -1) - ? 0 : status)); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, ((siginfo.si_code == SYS_SECCOMP + && siginfo.si_syscall == -1) + ? 0 : status)); #else /* __arm__ */ - ptrace (PTRACE_SYSCALL, pid, 0, ((siginfo.si_code == SYS_SECCOMP - && siginfo.si_syscall == 222) - ? 0 : status)); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, ((siginfo.si_code == SYS_SECCOMP + && siginfo.si_syscall == 222) + ? 0 : status)); #endif /* !__arm__ */ #else /* !HAVE_SIGINFO_T_SI_SYSCALL */ /* Drop this signal, since what caused it is unknown. */ - ptrace (PTRACE_SYSCALL, pid, 0, 0); + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), pid, + 0, 0); #endif /* HAVE_SIGINFO_T_SI_SYSCALL */ return -1; #endif /* SIGSYS */ default: - /* Continue the process until the next syscall. */ - ptrace (PTRACE_SYSCALL, pid, 0, status); + /* Resume the process as appropriate. */ + ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + pid, 0, status); return -1; } } @@ -1698,5 +2171,36 @@ exec_waitpid (pid_t pid, int *wstatus, int options) void exec_init (const char *loader) { +#ifdef HAVE_SECCOMP + struct utsname u; + int major, minor; +#endif /* HAVE_SECCOMP */ + loader_name = loader; +#ifdef HAVE_SECCOMP + errno = 0; + prctl (PR_GET_SECCOMP); + + /* PR_GET_SECCOMP should not set errno if the kernel was configured + with support for seccomp. */ + if (!errno) + use_seccomp_p = true; + else + return; + + /* Establish whether the kernel is 4.7.x or older. */ + uname (&u); + if ((sscanf (u.release, "%d.%d", &major, &minor) == 2)) + { + /* Certain required ptrace features were introduced in kernel + 3.5. */ + if (major < 3 || (major == 3 && minor < 5)) + use_seccomp_p = false; + else + { + if (major < 4 || (major == 4 && minor <= 7)) + kernel_4_7_or_earlier = true; + } + } +#endif /* HAVE_SECCOMP */ } diff --git a/java/Makefile.in b/java/Makefile.in index 465f99162ec..3d5165d3186 100644 --- a/java/Makefile.in +++ b/java/Makefile.in @@ -57,7 +57,6 @@ else GZIP_PROG = endif - # Android 4.3 and earlier require Emacs to be signed with a different # digital signature algorithm. @@ -77,6 +76,11 @@ else AAPT_ASSET_ARGS = endif +# This will be replaced by `--no-build-details' if details of the build +# system are not to be recorded in generated packages. +BUILD_DETAILS = @BUILD_DETAILS@ +GEN_BUILD_DETAILS := $(if $(BUILD_DETAILS),true ||,) + SIGN_EMACS = -keystore $(srcdir)/emacs.keystore -storepass \ emacs1 $(JARSIGNER_FLAGS) SIGN_EMACS_V2 = sign --v2-signing-enabled --ks \ @@ -249,13 +253,13 @@ install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES) \ | xargs ${GZIP_PROG} -9n ; \ } # Produce metadata files providing build information and suchlike. - $(AM_V_SILENT) \ + -$(AM_V_SILENT) $(GEN_BUILD_DETAILS) \ { (cd $(top_srcdir) \ && git rev-parse HEAD || echo "Unknown") \ && (git rev-parse --abbrev-ref HEAD \ || echo "Unknown") } 2> /dev/null > \ install_temp/assets/version - $(AM_V_SILENT) \ + -$(AM_V_SILENT) $(GEN_BUILD_DETAILS) \ { hostname; date +%s; } > install_temp/assets/build_info # Produce the file index. $(AM_V_SILENT) $(libsrc)/asset-directory-tool \ diff --git a/lib/acl-internal.c b/lib/acl-internal.c index 9ebb6e544b0..ae5398306af 100644 --- a/lib/acl-internal.c +++ b/lib/acl-internal.c @@ -89,6 +89,14 @@ acl_access_nontrivial (acl_t acl) group:Administrators:rwx mask::r-x other::r-x + or + user::rwx + group::r-x + group:SYSTEM:rwx + group:Administrators:rwx + group:Users:rwx + mask::rwx + other::r-x */ case ACL_GROUP: { @@ -105,9 +113,12 @@ acl_access_nontrivial (acl_t acl) /* Ignore the ace if the group_sid is one of - S-1-5-18 (group "SYSTEM") - S-1-5-32-544 (group "Administrators") - Cf. <https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids> */ + - S-1-5-32-545 (group "Users") + Cf. <https://learn.microsoft.com/en-us/windows/win32/secauthz/well-known-sids> + and look at the output of the 'mkgroup' command. */ ignorable = (strcmp (group_sid, "S-1-5-18") == 0 - || strcmp (group_sid, "S-1-5-32-544") == 0); + || strcmp (group_sid, "S-1-5-32-544") == 0 + || strcmp (group_sid, "S-1-5-32-545") == 0); } } if (!ignorable) diff --git a/lib/gnulib.mk.in b/lib/gnulib.mk.in index 832b245edc2..948269e744d 100644 --- a/lib/gnulib.mk.in +++ b/lib/gnulib.mk.in @@ -545,6 +545,7 @@ GL_GNULIB_NANOSLEEP = @GL_GNULIB_NANOSLEEP@ GL_GNULIB_NONBLOCKING = @GL_GNULIB_NONBLOCKING@ GL_GNULIB_OBSTACK_PRINTF = @GL_GNULIB_OBSTACK_PRINTF@ GL_GNULIB_OBSTACK_PRINTF_POSIX = @GL_GNULIB_OBSTACK_PRINTF_POSIX@ +GL_GNULIB_OBSTACK_ZPRINTF = @GL_GNULIB_OBSTACK_ZPRINTF@ GL_GNULIB_OPEN = @GL_GNULIB_OPEN@ GL_GNULIB_OPENAT = @GL_GNULIB_OPENAT@ GL_GNULIB_OPENDIR = @GL_GNULIB_OPENDIR@ @@ -645,6 +646,7 @@ GL_GNULIB_TIME_RZ = @GL_GNULIB_TIME_RZ@ GL_GNULIB_TMPFILE = @GL_GNULIB_TMPFILE@ GL_GNULIB_TRUNCATE = @GL_GNULIB_TRUNCATE@ GL_GNULIB_TTYNAME_R = @GL_GNULIB_TTYNAME_R@ +GL_GNULIB_TZNAME = @GL_GNULIB_TZNAME@ GL_GNULIB_TZSET = @GL_GNULIB_TZSET@ GL_GNULIB_UNISTD_H_GETOPT = @GL_GNULIB_UNISTD_H_GETOPT@ GL_GNULIB_UNISTD_H_NONBLOCKING = @GL_GNULIB_UNISTD_H_NONBLOCKING@ @@ -656,6 +658,7 @@ GL_GNULIB_UNSETENV = @GL_GNULIB_UNSETENV@ GL_GNULIB_USLEEP = @GL_GNULIB_USLEEP@ GL_GNULIB_UTIMENSAT = @GL_GNULIB_UTIMENSAT@ GL_GNULIB_VASPRINTF = @GL_GNULIB_VASPRINTF@ +GL_GNULIB_VAZSPRINTF = @GL_GNULIB_VAZSPRINTF@ GL_GNULIB_VDPRINTF = @GL_GNULIB_VDPRINTF@ GL_GNULIB_VFPRINTF = @GL_GNULIB_VFPRINTF@ GL_GNULIB_VFPRINTF_POSIX = @GL_GNULIB_VFPRINTF_POSIX@ @@ -665,8 +668,12 @@ GL_GNULIB_VPRINTF_POSIX = @GL_GNULIB_VPRINTF_POSIX@ GL_GNULIB_VSCANF = @GL_GNULIB_VSCANF@ GL_GNULIB_VSNPRINTF = @GL_GNULIB_VSNPRINTF@ GL_GNULIB_VSPRINTF_POSIX = @GL_GNULIB_VSPRINTF_POSIX@ +GL_GNULIB_VZSNPRINTF = @GL_GNULIB_VZSNPRINTF@ +GL_GNULIB_VZSPRINTF = @GL_GNULIB_VZSPRINTF@ GL_GNULIB_WCTOMB = @GL_GNULIB_WCTOMB@ GL_GNULIB_WRITE = @GL_GNULIB_WRITE@ +GL_GNULIB_ZSNPRINTF = @GL_GNULIB_ZSNPRINTF@ +GL_GNULIB_ZSPRINTF = @GL_GNULIB_ZSPRINTF@ GL_GNULIB__EXIT = @GL_GNULIB__EXIT@ GL_STDC_BIT_CEIL = @GL_STDC_BIT_CEIL@ GL_STDC_BIT_FLOOR = @GL_STDC_BIT_FLOOR@ @@ -928,7 +935,6 @@ HAVE_UTIMENSAT = @HAVE_UTIMENSAT@ HAVE_VASPRINTF = @HAVE_VASPRINTF@ HAVE_VDPRINTF = @HAVE_VDPRINTF@ HAVE_WCHAR_H = @HAVE_WCHAR_H@ -HAVE_WCHAR_T = @HAVE_WCHAR_T@ HAVE_WINSOCK2_H = @HAVE_WINSOCK2_H@ HAVE_XSERVER = @HAVE_XSERVER@ HAVE__EXIT = @HAVE__EXIT@ @@ -1412,6 +1418,7 @@ XSYNC_CFLAGS = @XSYNC_CFLAGS@ XSYNC_LIBS = @XSYNC_LIBS@ XWIDGETS_OBJ = @XWIDGETS_OBJ@ X_TOOLKIT_TYPE = @X_TOOLKIT_TYPE@ +ZIP = @ZIP@ ZIPALIGN = @ZIPALIGN@ ac_ct_CC = @ac_ct_CC@ ac_ct_CXX = @ac_ct_CXX@ @@ -3200,7 +3207,6 @@ stddef.h: stddef.in.h $(top_builddir)/config.status -e 's|@''STDDEF_NOT_IDEMPOTENT''@|$(STDDEF_NOT_IDEMPOTENT)|g' \ -e 's|@''REPLACE_NULL''@|$(REPLACE_NULL)|g' \ -e 's|@''HAVE_MAX_ALIGN_T''@|$(HAVE_MAX_ALIGN_T)|g' \ - -e 's|@''HAVE_WCHAR_T''@|$(HAVE_WCHAR_T)|g' \ $(srcdir)/stddef.in.h > $@-t $(AM_V_at)mv $@-t $@ else @@ -3305,6 +3311,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's/@''GNULIB_GETLINE''@/$(GL_GNULIB_GETLINE)/g' \ -e 's/@''GNULIB_OBSTACK_PRINTF''@/$(GL_GNULIB_OBSTACK_PRINTF)/g' \ -e 's/@''GNULIB_OBSTACK_PRINTF_POSIX''@/$(GL_GNULIB_OBSTACK_PRINTF_POSIX)/g' \ + -e 's/@''GNULIB_OBSTACK_ZPRINTF''@/$(GL_GNULIB_OBSTACK_ZPRINTF)/g' \ -e 's/@''GNULIB_PCLOSE''@/$(GL_GNULIB_PCLOSE)/g' \ -e 's/@''GNULIB_PERROR''@/$(GL_GNULIB_PERROR)/g' \ -e 's/@''GNULIB_POPEN''@/$(GL_GNULIB_POPEN)/g' \ @@ -3323,6 +3330,7 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's/@''GNULIB_STDIO_H_SIGPIPE''@/$(GL_GNULIB_STDIO_H_SIGPIPE)/g' \ -e 's/@''GNULIB_TMPFILE''@/$(GL_GNULIB_TMPFILE)/g' \ -e 's/@''GNULIB_VASPRINTF''@/$(GL_GNULIB_VASPRINTF)/g' \ + -e 's/@''GNULIB_VAZSPRINTF''@/$(GL_GNULIB_VAZSPRINTF)/g' \ -e 's/@''GNULIB_VDPRINTF''@/$(GL_GNULIB_VDPRINTF)/g' \ -e 's/@''GNULIB_VFPRINTF''@/$(GL_GNULIB_VFPRINTF)/g' \ -e 's/@''GNULIB_VFPRINTF_POSIX''@/$(GL_GNULIB_VFPRINTF_POSIX)/g' \ @@ -3332,6 +3340,10 @@ stdio.h: stdio.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) -e 's/@''GNULIB_VPRINTF_POSIX''@/$(GL_GNULIB_VPRINTF_POSIX)/g' \ -e 's/@''GNULIB_VSNPRINTF''@/$(GL_GNULIB_VSNPRINTF)/g' \ -e 's/@''GNULIB_VSPRINTF_POSIX''@/$(GL_GNULIB_VSPRINTF_POSIX)/g' \ + -e 's/@''GNULIB_VZSNPRINTF''@/$(GL_GNULIB_VZSNPRINTF)/g' \ + -e 's/@''GNULIB_VZSPRINTF''@/$(GL_GNULIB_VZSPRINTF)/g' \ + -e 's/@''GNULIB_ZSNPRINTF''@/$(GL_GNULIB_ZSNPRINTF)/g' \ + -e 's/@''GNULIB_ZSPRINTF''@/$(GL_GNULIB_ZSPRINTF)/g' \ -e 's/@''GNULIB_MDA_FCLOSEALL''@/$(GL_GNULIB_MDA_FCLOSEALL)/g' \ -e 's/@''GNULIB_MDA_FDOPEN''@/$(GL_GNULIB_MDA_FDOPEN)/g' \ -e 's/@''GNULIB_MDA_FILENO''@/$(GL_GNULIB_MDA_FILENO)/g' \ @@ -4005,6 +4017,7 @@ time.h: time.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H) $( -e 's/@''GNULIB_TIMESPEC_GETRES''@/$(GL_GNULIB_TIMESPEC_GETRES)/g' \ -e 's/@''GNULIB_TIME_R''@/$(GL_GNULIB_TIME_R)/g' \ -e 's/@''GNULIB_TIME_RZ''@/$(GL_GNULIB_TIME_RZ)/g' \ + -e 's/@''GNULIB_TZNAME''@/$(GL_GNULIB_TZNAME)/g' \ -e 's/@''GNULIB_TZSET''@/$(GL_GNULIB_TZSET)/g' \ -e 's/@''GNULIB_MDA_TZSET''@/$(GL_GNULIB_MDA_TZSET)/g' \ -e 's|@''HAVE_DECL_LOCALTIME_R''@|$(HAVE_DECL_LOCALTIME_R)|g' \ diff --git a/lib/stddef.in.h b/lib/stddef.in.h index 63bb500e262..0abc4497043 100644 --- a/lib/stddef.in.h +++ b/lib/stddef.in.h @@ -149,11 +149,6 @@ typedef long max_align_t; # endif #endif -/* Some platforms lack wchar_t. */ -#if !@HAVE_WCHAR_T@ -# define wchar_t int -#endif - /* Some platforms lack max_align_t. The check for _GCC_MAX_ALIGN_T is a hack in case the configure-time test was done with g++ even though we are currently compiling with gcc. diff --git a/lib/stdio.in.h b/lib/stdio.in.h index 1c0c9661bfe..cf2d8c999bc 100644 --- a/lib/stdio.in.h +++ b/lib/stdio.in.h @@ -1075,13 +1075,39 @@ _GL_CXXALIASWARN (getw); # endif #endif +#if @GNULIB_OBSTACK_ZPRINTF@ +struct obstack; +/* Grows an obstack with formatted output. Returns the number of + bytes added to OBS. No trailing nul byte is added, and the + object should be closed with obstack_finish before use. + Upon memory allocation error, calls obstack_alloc_failed_handler. + Upon other error, returns -1 with errno set. + + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is through + obstack_alloc_failed_handler. */ +_GL_FUNCDECL_SYS (obstack_zprintf, ptrdiff_t, + (struct obstack *obs, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (obstack_zprintf, ptrdiff_t, + (struct obstack *obs, const char *format, ...)); +_GL_FUNCDECL_SYS (obstack_vzprintf, ptrdiff_t, + (struct obstack *obs, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (obstack_vzprintf, ptrdiff_t, + (struct obstack *obs, const char *format, va_list args)); +#endif + #if @GNULIB_OBSTACK_PRINTF@ || @GNULIB_OBSTACK_PRINTF_POSIX@ struct obstack; -/* Grow an obstack with formatted output. Return the number of +/* Grows an obstack with formatted output. Returns the number of bytes added to OBS. No trailing nul byte is added, and the - object should be closed with obstack_finish before use. Upon - memory allocation error, call obstack_alloc_failed_handler. Upon - other error, return -1. */ + object should be closed with obstack_finish before use. + Upon memory allocation error, calls obstack_alloc_failed_handler. + Upon other error, returns -1. */ # if @REPLACE_OBSTACK_PRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define obstack_printf rpl_obstack_printf @@ -1433,7 +1459,31 @@ _GL_CXXALIASWARN (scanf); # endif #endif +#if @GNULIB_ZSNPRINTF@ +/* Prints formatted output to string STR. Similar to sprintf, but the + additional parameter SIZE limits how much is written into STR. + STR may be NULL, in which case nothing will be written. + Returns the string length of the formatted string (which may be larger + than SIZE). Upon failure, returns -1 with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is ENOMEM. */ +_GL_FUNCDECL_SYS (zsnprintf, ptrdiff_t, + (char *restrict str, size_t size, + const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 4) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_SYS (zsnprintf, ptrdiff_t, + (char *restrict str, size_t size, + const char *restrict format, ...)); +#endif + #if @GNULIB_SNPRINTF@ +/* Prints formatted output to string STR. Similar to sprintf, but the + additional parameter SIZE limits how much is written into STR. + STR may be NULL, in which case nothing will be written. + Returns the string length of the formatted string (which may be larger + than SIZE). Upon failure, returns a negative value. */ # if @REPLACE_SNPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define snprintf rpl_snprintf @@ -1470,6 +1520,23 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - " # endif #endif +#if @GNULIB_ZSPRINTF@ +/* Prints formatted output to string STR. + Returns the string length of the formatted string. Upon failure, + returns -1 with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is ENOMEM. */ +_GL_FUNCDECL_SYS (zsprintf, ptrdiff_t, + (char *restrict str, + const char *restrict format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (zsprintf, ptrdiff_t, + (char *restrict str, + const char *restrict format, ...)); +#endif + /* Some people would argue that all sprintf uses should be warned about (for example, OpenBSD issues a link warning for it), since it can cause security holes due to buffer overruns. @@ -1480,6 +1547,9 @@ _GL_WARN_ON_USE (snprintf, "snprintf is unportable - " GNULIB_POSIXCHECK is defined. */ #if @GNULIB_SPRINTF_POSIX@ +/* Prints formatted output to string STR. + Returns the string length of the formatted string. Upon failure, + returns a negative value. */ # if @REPLACE_SPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define sprintf rpl_sprintf @@ -1559,6 +1629,29 @@ _GL_WARN_ON_USE (tmpfile, "tmpfile is not usable on mingw - " # endif #endif +#if @GNULIB_VAZSPRINTF@ +/* Prints formatted output to a string dynamically allocated with malloc(). + If the memory allocation succeeds, it stores the address of the string in + *RESULT and returns the number of resulting bytes, excluding the trailing + NUL. Upon memory allocation error, or some other error, it returns -1 + with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is ENOMEM. */ +_GL_FUNCDECL_SYS (azsprintf, ptrdiff_t, + (char **result, const char *format, ...) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 3) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (azsprintf, ptrdiff_t, + (char **result, const char *format, ...)); +_GL_FUNCDECL_SYS (vazsprintf, ptrdiff_t, + (char **result, const char *format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (vazsprintf, ptrdiff_t, + (char **result, const char *format, va_list args)); +#endif + #if @GNULIB_VASPRINTF@ /* Write formatted output to a string dynamically allocated with malloc(). If the memory allocation succeeds, store the address of the string in @@ -1769,7 +1862,31 @@ _GL_CXXALIASWARN (vscanf); # endif #endif +#if @GNULIB_VZSNPRINTF@ +/* Prints formatted output to string STR. Similar to sprintf, but the + additional parameter SIZE limits how much is written into STR. + STR may be NULL, in which case nothing will be written. + Returns the string length of the formatted string (which may be larger + than SIZE). Upon failure, returns -1 with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is ENOMEM. */ +_GL_FUNCDECL_SYS (vzsnprintf, ptrdiff_t, + (char *restrict str, size_t size, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) + _GL_ARG_NONNULL ((3))); +_GL_CXXALIAS_SYS (vzsnprintf, ptrdiff_t, + (char *restrict str, size_t size, + const char *restrict format, va_list args)); +#endif + #if @GNULIB_VSNPRINTF@ +/* Prints formatted output to string STR. Similar to vsprintf, but the + additional parameter SIZE limits how much is written into STR. + STR may be NULL, in which case nothing will be written. + Returns the string length of the formatted string (which may be larger + than SIZE). Upon failure, returns a negative value. */ # if @REPLACE_VSNPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vsnprintf rpl_vsnprintf @@ -1806,7 +1923,27 @@ _GL_WARN_ON_USE (vsnprintf, "vsnprintf is unportable - " # endif #endif +#if @GNULIB_VZSPRINTF@ +/* Prints formatted output to string STR. + Returns the string length of the formatted string. Upon failure, + returns -1 with errno set. + Failure code EOVERFLOW can only occur when a width > INT_MAX is used. + Therefore, if the format string is valid and does not use %ls/%lc + directives nor widths, the only possible failure code is ENOMEM. */ +_GL_FUNCDECL_SYS (vzsprintf, ptrdiff_t, + (char *restrict str, + const char *restrict format, va_list args) + _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (2, 0) + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_SYS (vzsprintf, ptrdiff_t, + (char *restrict str, + const char *restrict format, va_list args)); +#endif + #if @GNULIB_VSPRINTF_POSIX@ +/* Prints formatted output to string STR. + Returns the string length of the formatted string. Upon failure, + returns a negative value. */ # if @REPLACE_VSPRINTF@ # if !(defined __cplusplus && defined GNULIB_NAMESPACE) # define vsprintf rpl_vsprintf diff --git a/lib/strftime.c b/lib/strftime.c index 5f1e76833f7..9b1b27a1fc8 100644 --- a/lib/strftime.c +++ b/lib/strftime.c @@ -25,9 +25,8 @@ #ifdef _LIBC # define USE_IN_EXTENDED_LOCALE_MODEL 1 # define HAVE_STRUCT_ERA_ENTRY 1 -# define HAVE_TM_GMTOFF 1 +# define HAVE_STRUCT_TM_TM_GMTOFF 1 # define HAVE_STRUCT_TM_TM_ZONE 1 -# define HAVE_TZNAME 1 # include "../locale/localeinfo.h" #else # include <libc-config.h> @@ -60,10 +59,6 @@ #include <errno.h> #include <time.h> -#if HAVE_TZNAME && !HAVE_DECL_TZNAME -extern char *tzname[]; -#endif - /* Do multibyte processing if multibyte encodings are supported, unless multibyte sequences are safe in formats. Multibyte sequences are safe if they cannot contain byte sequences that look like format @@ -87,18 +82,16 @@ extern char *tzname[]; #endif #include <limits.h> +#include <locale.h> #include <stdckdint.h> #include <stddef.h> #include <stdlib.h> #include <string.h> -#if USE_C_LOCALE && HAVE_STRFTIME_L -# include <locale.h> -#endif - #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM -# include <locale.h> # include "localename.h" +#elif defined _WIN32 && !defined __CYGWIN__ +# include <wchar.h> #endif #include "attribute.h" @@ -377,6 +370,15 @@ memcpy_uppcase (CHAR_T *dest, const CHAR_T *src, size_t len LOCALE_PARAM) #endif +/* Note: We assume that HAVE_STRFTIME_LZ implies HAVE_STRFTIME_L. + Otherwise, we would have to write (HAVE_STRFTIME_L || HAVE_STRFTIME_LZ) + instead of HAVE_STRFTIME_L everywhere. */ + +/* Define to 1 if we can use the system's native functions that takes a + timezone_t argument. As of 2024, this is only true on NetBSD. */ +#define HAVE_NATIVE_TIME_Z \ + (USE_C_LOCALE && HAVE_STRFTIME_L ? HAVE_STRFTIME_LZ : HAVE_STRFTIME_Z) + #if USE_C_LOCALE && HAVE_STRFTIME_L /* Cache for the C locale object. @@ -396,6 +398,27 @@ c_locale (void) #endif +#if HAVE_NATIVE_TIME_Z + +/* On NetBSD a null tz has undefined behavior, so use a non-null tz. + Cache the UTC time zone object in a volatile variable for improved + thread safety. This is good enough in practice, although in theory + stdatomic.h should be used. */ +static volatile timezone_t utc_timezone_cache; + +/* Return the UTC time zone object, or (timezone_t) 0 with errno set + if it cannot be created. */ +static timezone_t +utc_timezone (void) +{ + timezone_t tz = utc_timezone_cache; + if (!tz) + utc_timezone_cache = tz = tzalloc ("UTC0"); + return tz; +} + +#endif + #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM @@ -747,7 +770,7 @@ should_remove_ampm (void) #endif -#if ! HAVE_TM_GMTOFF +#if ! HAVE_STRUCT_TM_TM_GMTOFF /* Yield the difference between *A and *B, measured in seconds, ignoring leap seconds. */ # define tm_diff ftime_tm_diff @@ -772,7 +795,7 @@ tm_diff (const struct tm *a, const struct tm *b) + (a->tm_min - b->tm_min)) + (a->tm_sec - b->tm_sec)); } -#endif /* ! HAVE_TM_GMTOFF */ +#endif @@ -810,9 +833,9 @@ static CHAR_T const c_month_names[][sizeof "September"] = #endif -/* When compiling this file, GNU applications can #define my_strftime - to a symbol (typically nstrftime) to get an extended strftime with - extra arguments TZ and NS. */ +/* When compiling this file, Gnulib-using applications should #define + my_strftime to a symbol (typically nstrftime) to name their + extended strftime with extra arguments TZ and NS. */ #ifdef my_strftime # define extra_args , tz, ns @@ -837,6 +860,200 @@ static size_t __strftime_internal (STREAM_OR_CHAR_T *, STRFTIME_ARG (size_t) bool, enum pad_style, int, bool * extra_args_spec LOCALE_PARAM); +#if !defined _LIBC \ + && (!(USE_C_LOCALE && !HAVE_STRFTIME_L) || !HAVE_STRUCT_TM_TM_ZONE) + +/* Make sure we're calling the actual underlying strftime. + In some cases, time.h contains something like + "#define strftime rpl_strftime". */ +# ifdef strftime +# undef strftime +# endif + +/* Assuming the time zone is TZ, store into UBUF, of size UBUFSIZE, a + ' ' followed by the result of calling strftime with the format + "%MF" where M is MODIFIER (or is omitted if !MODIFIER) and F is + FORMAT_CHAR, along with the time information specified by *TP. + Return the number of bytes stored if successful, zero otherwise. */ +static size_t +underlying_strftime (timezone_t tz, char *ubuf, size_t ubufsize, + char modifier, char format_char, struct tm const *tp) +{ + /* The relevant information is available only via the + underlying strftime implementation, so use that. */ + char ufmt[5]; + char *u = ufmt; + + /* The space helps distinguish strftime failure from empty + output. */ + *u++ = ' '; + *u++ = '%'; + *u = modifier; + u += !!modifier; + *u++ = format_char; + *u = '\0'; + +# if HAVE_NATIVE_TIME_Z + if (!tz) + { + tz = utc_timezone (); + if (!tz) + return 0; /* errno is set here */ + } +# endif + +# if !HAVE_NATIVE_TIME_Z + if (tz && tz != local_tz) + { + tz = set_tz (tz); + if (!tz) + return 0; + } +# endif + + size_t len; +# if USE_C_LOCALE && HAVE_STRFTIME_L + locale_t locale = c_locale (); + if (!locale) + return 0; /* errno is set here */ +# if HAVE_STRFTIME_LZ + len = strftime_lz (tz, ubuf, ubufsize, ufmt, tp, locale); +# else + len = strftime_l (ubuf, ubufsize, ufmt, tp, locale); +# endif +# else +# if HAVE_STRFTIME_Z + len = strftime_z (tz, ubuf, ubufsize, ufmt, tp); +# else + len = strftime (ubuf, ubufsize, ufmt, tp); +# endif +# endif + +# if !HAVE_NATIVE_TIME_Z + if (tz && !revert_tz (tz)) + return 0; +# endif + + if (len != 0) + { +# if ((__GLIBC__ == 2 && __GLIBC_MINOR__ < 31) \ + || defined __NetBSD__ || defined __sun) + /* glibc < 2.31, NetBSD, Solaris */ + if (format_char == 'c') + { + /* The output of the strftime %c directive consists of the + date, the time, and the time zone. But the time zone is + wrong, since neither TZ nor ZONE was passed as argument. + Therefore, remove the the last space-delimited word. + In order not to accidentally remove a date or a year + (that contains no letter) or an AM/PM indicator (that has + length 2), remove that last word only if it contains a + letter and has length >= 3. */ + char *space; + for (space = ubuf + len - 1; *space != ' '; space--) + continue; + if (space > ubuf) + { + /* Found a space. */ + if (strlen (space + 1) >= 3) + { + /* The last word has length >= 3. */ + bool found_letter = false; + const char *p; + for (p = space + 1; *p != '\0'; p++) + if ((*p >= 'A' && *p <= 'Z') + || (*p >= 'a' && *p <= 'z')) + { + found_letter = true; + break; + } + if (found_letter) + { + /* The last word contains a letter. */ + *space = '\0'; + len = space - ubuf; + } + } + } + } +# if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM + /* The output of the strftime %p and %r directives contains + an AM/PM indicator even for locales where it is not + suitable, such as French. Remove this indicator. */ + if (format_char == 'p') + { + bool found_ampm = (len > 1); + if (found_ampm && should_remove_ampm ()) + { + ubuf[1] = '\0'; + len = 1; + } + } + else if (format_char == 'r') + { + char last_char = ubuf[len - 1]; + bool found_ampm = !(last_char >= '0' && last_char <= '9'); + if (found_ampm && should_remove_ampm ()) + { + char *space; + for (space = ubuf + len - 1; *space != ' '; space--) + continue; + if (space > ubuf) + { + *space = '\0'; + len = space - ubuf; + } + } + } +# endif +# endif + } + return len; +} +#endif + +/* Return a time zone abbreviation for TZ. Use BUF, of size BUFSIZE, + to store it if needed. If MODIFIER use the strftime format + "%mZ" to format it, where m is the MODIFIER; otherwise + use plain "%Z". Format an abbreviation appropriate for + TP and EXTRA_ARGS_SPEC. Return the empty string on failure. */ +static char const * +get_tm_zone (timezone_t tz, char *ubuf, int ubufsize, int modifier, + struct tm const *tp) +{ +#if HAVE_STRUCT_TM_TM_ZONE + /* The POSIX test suite assumes that setting + the environment variable TZ to a new value before calling strftime() + will influence the result (the %Z format) even if the information in + *TP is computed with a totally different time zone. + This is bogus: though POSIX allows bad behavior like this, + POSIX does not require it. Do the right thing instead. */ + return tp->tm_zone; +#else + if (!tz) + return "UTC"; + +# if !HAVE_NATIVE_TIME_Z + timezone_t old_tz = tz; + if (tz != local_tz) + { + old_tz = set_tz (tz); + if (!old_tz) + return ""; + } +# endif + + int zsize = underlying_strftime (tz, ubuf, ubufsize, 0, 'Z', tp); + +# if !HAVE_NATIVE_TIME_Z + if (!revert_tz (old_tz)) + return ""; +# endif + + return zsize ? ubuf + 1 : ""; +#endif +} + /* Write information from TP into S according to the format string FORMAT, writing no more that MAXSIZE characters (including the terminating '\0') and returning number of @@ -927,10 +1144,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) # define ampm (L_("AMPM") + 2 * (tp->tm_hour > 11)) # define ap_len 2 #endif -#if HAVE_TZNAME - char **tzname_vec = tzname; -#endif - const char *zone; size_t i = 0; STREAM_OR_CHAR_T *p = s; const CHAR_T *f; @@ -938,47 +1151,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) const char *format_end = NULL; #endif - zone = NULL; -#if HAVE_STRUCT_TM_TM_ZONE - /* The POSIX test suite assumes that setting - the environment variable TZ to a new value before calling strftime() - will influence the result (the %Z format) even if the information in - TP is computed with a totally different time zone. - This is bogus: though POSIX allows bad behavior like this, - POSIX does not require it. Do the right thing instead. */ - zone = (const char *) tp->tm_zone; -#endif -#if HAVE_TZNAME - if (!tz) - { - if (! (zone && *zone)) - zone = "GMT"; - } - else - { -# if !HAVE_STRUCT_TM_TM_ZONE - /* Infer the zone name from *TZ instead of from TZNAME. */ - tzname_vec = tz->tzname_copy; -# endif - } - /* The tzset() call might have changed the value. */ - if (!(zone && *zone) && tp->tm_isdst >= 0) - { - /* POSIX.1 requires that local time zone information be used as - though strftime called tzset. */ -# ifndef my_strftime - if (!*tzset_called) - { - tzset (); - *tzset_called = true; - } -# endif - zone = tzname_vec[tp->tm_isdst != 0]; - } -#endif - if (! zone) - zone = ""; - if (hour12 > 12) hour12 -= 12; else @@ -1293,7 +1465,21 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) subfmt = L_("%a %b %e %H:%M:%S %Y"); #elif defined _WIN32 && !defined __CYGWIN__ /* On native Windows, "%c" is "%d/%m/%Y %H:%M:%S" by default. */ - subfmt = L_("%a %b %e %H:%M:%S %Y"); + bool is_c_locale; + /* This code is equivalent to is_c_locale = !hard_locale (LC_TIME). */ +# if defined _MSC_VER + const wchar_t *locale = _wsetlocale (LC_TIME, NULL); + is_c_locale = + (wcscmp (locale, L"C") == 0 || wcscmp (locale, L"POSIX") == 0); +# else + const char *locale = setlocale (LC_TIME, NULL); + is_c_locale = + (strcmp (locale, "C") == 0 || strcmp (locale, "POSIX") == 0); +# endif + if (is_c_locale) + subfmt = L_("%a %b %e %H:%M:%S %Y"); + else + subfmt = L_("%a %e %b %Y %H:%M:%S"); #else goto underlying_strftime; #endif @@ -1314,40 +1500,13 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) } break; -#if !((defined _NL_CURRENT && HAVE_STRUCT_ERA_ENTRY) || (USE_C_LOCALE && !HAVE_STRFTIME_L)) +#if !defined _LIBC && !(USE_C_LOCALE && !HAVE_STRFTIME_L) underlying_strftime: { - /* The relevant information is available only via the - underlying strftime implementation, so use that. */ - char ufmt[5]; - char *u = ufmt; char ubuf[1024]; /* enough for any single format in practice */ size_t len; - /* Make sure we're calling the actual underlying strftime. - In some cases, config.h contains something like - "#define strftime rpl_strftime". */ -# ifdef strftime -# undef strftime - size_t strftime (char *, size_t, const char *, struct tm const *); -# endif - - /* The space helps distinguish strftime failure from empty - output. */ - *u++ = ' '; - *u++ = '%'; - if (modifier != 0) - *u++ = modifier; - *u++ = format_char; - *u = '\0'; - -# if USE_C_LOCALE /* implies HAVE_STRFTIME_L */ - locale_t locale = c_locale (); - if (!locale) - return 0; /* errno is set here */ - len = strftime_l (ubuf, sizeof ubuf, ufmt, tp, locale); -# else - len = strftime (ubuf, sizeof ubuf, ufmt, tp); -# endif + len = underlying_strftime (tz, ubuf, sizeof ubuf, + modifier, format_char, tp); if (len != 0) { # if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 31) || defined __NetBSD__ || defined __sun /* glibc < 2.31, NetBSD, Solaris */ @@ -1715,7 +1874,8 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) #elif USE_C_LOCALE && !HAVE_STRFTIME_L subfmt = L_("%I:%M:%S %p"); goto subformat; -#elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || (defined _WIN32 && !defined __CYGWIN__) +#elif ((defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ \ + || (defined _WIN32 && !defined __CYGWIN__)) /* macOS, FreeBSD, native Windows strftime() may produce empty output for "%r". */ subfmt = L_("%I:%M:%S %p"); @@ -1927,8 +2087,30 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) to_lowcase = true; } + { + char const *zone; +#ifdef _LIBC + zone = tp->tm_zone; + /* The tzset() call might have changed the value. */ + if (!(zone && *zone) && tp->tm_isdst >= 0) + { + /* POSIX.1 requires that local time zone information be used as + though strftime called tzset. */ + if (!*tzset_called) + { + tzset (); + *tzset_called = true; + } + zone = tp->tm_isdst <= 1 ? tzname[tp->tm_isdst] : "?"; + } + if (! zone) + zone = ""; +#else + char zonebuf[128]; /* Enough for any time zone abbreviation. */ + zone = get_tm_zone (tz, zonebuf, sizeof zonebuf, modifier, tp); +#endif + #ifdef COMPILE_WIDE - { /* The zone string is always given in multibyte form. We have to convert it to wide character. */ size_t w = pad == NO_PAD || width < 0 ? 0 : width; @@ -1956,10 +2138,10 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) p += incr; } i += incr; - } #else - cpy (strlen (zone), zone); + cpy (strlen (zone), zone); #endif + } break; case L_(':'): @@ -1984,7 +2166,7 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) int hour_diff; int min_diff; int sec_diff; -#if HAVE_TM_GMTOFF +#if HAVE_STRUCT_TM_TM_GMTOFF diff = tp->tm_gmtoff; #else if (!tz) @@ -1995,16 +2177,6 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) struct tm ltm; time_t lt; - /* POSIX.1 requires that local time zone information be used as - though strftime called tzset. */ -# ifndef my_strftime - if (!*tzset_called) - { - tzset (); - *tzset_called = true; - } -# endif - ltm = *tp; ltm.tm_wday = -1; lt = mktime_z (tz, <m); @@ -2014,7 +2186,14 @@ __strftime_internal (STREAM_OR_CHAR_T *s, STRFTIME_ARG (size_t maxsize) } #endif - negative_number = diff < 0 || (diff == 0 && *zone == '-'); + negative_number = diff < 0; + if (diff == 0) + { + char zonebuf[128]; /* Enough for any time zone abbreviation. */ + negative_number = (*get_tm_zone (tz, zonebuf, sizeof zonebuf, + 0, tp) + == '-'); + } hour_diff = diff / 60 / 60; min_diff = diff / 60 % 60; sec_diff = diff % 60; diff --git a/lib/strnlen.c b/lib/strnlen.c index 80857ec22b0..5231e4c595d 100644 --- a/lib/strnlen.c +++ b/lib/strnlen.c @@ -1,6 +1,5 @@ /* Find the length of STRING, but scan at most MAXLEN characters. Copyright (C) 2005-2007, 2009-2024 Free Software Foundation, Inc. - Written by Simon Josefsson. This file is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as @@ -19,12 +18,17 @@ #include <string.h> -/* Find the length of STRING, but scan at most MAXLEN characters. - If no '\0' terminator is found in that many characters, return MAXLEN. */ +/* Find the length of S, but scan at most MAXLEN bytes. + S must be a string if it starts with fewer than MAXLEN initialized bytes. + If no '\0' terminator is found in that many bytes, return MAXLEN. */ size_t -strnlen (const char *string, size_t maxlen) +strnlen (const char *s, size_t maxlen) { - const char *end = memchr (string, '\0', maxlen); - return end ? (size_t) (end - string) : maxlen; + /* Do not use memchr, because on some platforms memchr has + undefined behavior if MAXLEN exceeds the number of bytes in S. */ + size_t i; + for (i = 0; i < maxlen && s[i]; i++) + continue; + return i; } diff --git a/lib/time-internal.h b/lib/time-internal.h index 816684a1172..3d778ba50ec 100644 --- a/lib/time-internal.h +++ b/lib/time-internal.h @@ -17,6 +17,9 @@ /* Written by Paul Eggert. */ +/* This file is for Gnulib internal use only. + Applications should not use it. */ + /* A time zone rule. */ struct tm_zone { @@ -24,12 +27,6 @@ struct tm_zone members are zero. */ struct tm_zone *next; -#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE - /* Copies of recent strings taken from tzname[0] and tzname[1]. - The copies are in ABBRS, so that they survive tzset. Null if unknown. */ - char *tzname_copy[2]; -#endif - /* If nonzero, the rule represents the TZ environment variable set to the first "abbreviation" (this may be the empty string). Otherwise, it represents an unset TZ. */ @@ -41,9 +38,17 @@ struct tm_zone actually a TZ environment value) may be empty. Otherwise all strings must be nonempty. - Abbreviations are stored here because otherwise the values of - tm_zone and/or tzname would be dead after changing TZ and calling + Abbreviations are stored here even on platforms with tm_zone, because + otherwise tm_zone values would be dead after changing TZ and calling tzset. Abbreviations never move once allocated, and are live until tzfree is called. */ char abbrs[FLEXIBLE_ARRAY_MEMBER]; }; + +timezone_t set_tz (timezone_t); +bool revert_tz (timezone_t); + +/* Magic cookie timezone_t value, for local time. It differs from + NULL and from all other timezone_t values. Only the address + matters; the pointer is never dereferenced. */ +#define local_tz ((timezone_t) 1) diff --git a/lib/time.in.h b/lib/time.in.h index df99c8abca9..b91018937ad 100644 --- a/lib/time.in.h +++ b/lib/time.in.h @@ -122,6 +122,23 @@ struct __time_t_must_be_integral { # endif # endif +# if @GNULIB_TZNAME@ +/* tzname[0..1]: Abbreviated time zone names, set by the tzset() function. */ +# if NEED_DECL_TZNAME +extern +# ifdef __cplusplus + "C" +# endif + char *tzname[]; +# endif +# if defined _WIN32 && !defined __CYGWIN__ +/* On native Windows, map 'tzname' to '_tzname' etc., so that -loldnames is not + required. */ +# undef tzname +# define tzname _tzname +# endif +# endif + /* Set *TS to the current time, and return BASE. Upon failure, return 0. */ # if @GNULIB_TIMESPEC_GET@ diff --git a/lib/time_rz.c b/lib/time_rz.c index 468d7539ce1..a6523e1285b 100644 --- a/lib/time_rz.c +++ b/lib/time_rz.c @@ -44,11 +44,6 @@ enum { DEFAULT_MXFAST = 64 * sizeof (size_t) / 4 }; used. */ enum { ABBR_SIZE_MIN = DEFAULT_MXFAST - offsetof (struct tm_zone, abbrs) }; -/* Magic cookie timezone_t value, for local time. It differs from - NULL and from all other timezone_t values. Only the address - matters; the pointer is never dereferenced. */ -static timezone_t const local_tz = (timezone_t) 1; - /* Copy to ABBRS the abbreviation at ABBR with size ABBR_SIZE (this includes its trailing null byte). Append an extra null byte to mark the end of ABBRS. */ @@ -70,9 +65,6 @@ tzalloc (char const *name) if (tz) { tz->next = NULL; -#if HAVE_TZNAME && !HAVE_STRUCT_TM_TM_ZONE - tz->tzname_copy[0] = tz->tzname_copy[1] = NULL; -#endif tz->tz_is_set = !!name; tz->abbrs[0] = '\0'; if (name) @@ -81,33 +73,16 @@ tzalloc (char const *name) return tz; } -/* Save into TZ any nontrivial time zone abbreviation used by TM, and - update *TM (if HAVE_STRUCT_TM_TM_ZONE) or *TZ (if - !HAVE_STRUCT_TM_TM_ZONE && HAVE_TZNAME) if they use the abbreviation. +/* If HAVE_STRUCT_TM_TM_ZONE, save into TZ any nontrivial time zone + abbreviation used by TM, and update *TM to contain the saved abbreviation. Return true if successful, false (setting errno) otherwise. */ static bool save_abbr (timezone_t tz, struct tm *tm) { -#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME - char const *zone = NULL; +#if HAVE_STRUCT_TM_TM_ZONE + char const *zone = tm->tm_zone; char *zone_copy = (char *) ""; -# if HAVE_TZNAME - int tzname_index = -1; -# endif - -# if HAVE_STRUCT_TM_TM_ZONE - zone = tm->tm_zone; -# endif - -# if HAVE_TZNAME - if (! (zone && *zone) && 0 <= tm->tm_isdst) - { - tzname_index = tm->tm_isdst != 0; - zone = tzname[tzname_index]; - } -# endif - /* No need to replace null zones, or zones within the struct tm. */ if (!zone || ((char *) tm <= zone && zone < (char *) (tm + 1))) return true; @@ -144,12 +119,7 @@ save_abbr (timezone_t tz, struct tm *tm) } /* Replace the zone name so that its lifetime matches that of TZ. */ -# if HAVE_STRUCT_TM_TM_ZONE tm->tm_zone = zone_copy; -# else - if (0 <= tzname_index) - tz->tzname_copy[tzname_index] = zone_copy; -# endif #endif return true; @@ -202,7 +172,7 @@ change_env (timezone_t tz) Return LOCAL_TZ if the time zone setting is already correct. Otherwise return a newly allocated time zone representing the old setting, or NULL (setting errno) on failure. */ -static timezone_t +timezone_t set_tz (timezone_t tz) { char *env_tz = getenv_TZ (); @@ -229,7 +199,7 @@ set_tz (timezone_t tz) /* Restore an old setting returned by set_tz. It must not be null. Return true (preserving errno) if successful, false (setting errno) otherwise. */ -static bool +bool revert_tz (timezone_t tz) { if (tz == local_tz) @@ -302,9 +272,7 @@ mktime_z (timezone_t tz, struct tm *tm) tm_1.tm_isdst = tm->tm_isdst; time_t t = mktime (&tm_1); bool ok = 0 <= tm_1.tm_yday; -#if HAVE_STRUCT_TM_TM_ZONE || HAVE_TZNAME ok = ok && save_abbr (tz, &tm_1); -#endif if (revert_tz (old_tz) && ok) { *tm = tm_1; diff --git a/lib/timespec-add.c b/lib/timespec-add.c index e10c19842cd..50683187117 100644 --- a/lib/timespec-add.c +++ b/lib/timespec-add.c @@ -29,34 +29,22 @@ struct timespec timespec_add (struct timespec a, struct timespec b) { - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec + b.tv_nsec; - int nsd = ns - TIMESPEC_HZ; - int rns = ns; - - if (0 <= nsd) - { - rns = nsd; - time_t bs1; - if (!ckd_add (&bs1, bs, 1)) - bs = bs1; - else if (rs < 0) - rs++; - else - goto high_overflow; - } - - if (ckd_add (&rs, rs, bs)) + int nssum = a.tv_nsec + b.tv_nsec; + int carry = TIMESPEC_HZ <= nssum; + time_t rs; + int rns; + bool v = ckd_add (&rs, a.tv_sec, b.tv_sec); + if (v == ckd_add (&rs, rs, carry)) + rns = nssum - TIMESPEC_HZ * carry; + else { - if (bs < 0) + if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs) { rs = TYPE_MINIMUM (time_t); rns = 0; } else { - high_overflow: rs = TYPE_MAXIMUM (time_t); rns = TIMESPEC_HZ - 1; } diff --git a/lib/timespec-sub.c b/lib/timespec-sub.c index 315cc638369..f6d948780e4 100644 --- a/lib/timespec-sub.c +++ b/lib/timespec-sub.c @@ -30,28 +30,17 @@ struct timespec timespec_sub (struct timespec a, struct timespec b) { - time_t rs = a.tv_sec; - time_t bs = b.tv_sec; - int ns = a.tv_nsec - b.tv_nsec; - int rns = ns; - - if (ns < 0) - { - rns = ns + TIMESPEC_HZ; - time_t bs1; - if (!ckd_add (&bs1, bs, 1)) - bs = bs1; - else if (- TYPE_SIGNED (time_t) < rs) - rs--; - else - goto low_overflow; - } - - if (ckd_sub (&rs, rs, bs)) + int nsdiff = a.tv_nsec - b.tv_nsec; + bool borrow = nsdiff < 0; + time_t rs; + int rns; + bool v = ckd_sub (&rs, a.tv_sec, b.tv_sec); + if (v == ckd_sub (&rs, rs, borrow)) + rns = nsdiff + TIMESPEC_HZ * borrow; + else { - if (0 < bs) + if ((TYPE_MINIMUM (time_t) + TYPE_MAXIMUM (time_t)) / 2 < rs) { - low_overflow: rs = TYPE_MINIMUM (time_t); rns = 0; } diff --git a/lisp/autoinsert.el b/lisp/autoinsert.el index f2631422c62..6b7dcad3899 100644 --- a/lisp/autoinsert.el +++ b/lisp/autoinsert.el @@ -166,18 +166,18 @@ If this contains a %s, that will be replaced by the matching rule." (replace-match (capitalize (user-login-name)) t t)) '(end-of-line 1) " <" (progn user-mail-address) ">\n") - (".dir-locals.el" + ((,(rx ".dir-locals" (? "-2") ".el") . "Directory Local Variables") nil ";;; Directory Local Variables -*- no-byte-compile: t; -*-\n" ";;; For more information see (info \"(emacs) Directory Variables\")\n\n" "((" - '(setq v1 (let (modes) + '(setq v1 (let ((modes '("nil"))) (mapatoms (lambda (mode) (let ((name (symbol-name mode))) (when (string-match "-mode\\'" name) (push name modes))))) (sort modes 'string<))) - (completing-read "Local variables for mode: " v1 nil t) + (completing-read "Local variables for mode: " v1 nil 'confirm) " . ((" (let ((all-variables (apropos-internal ".*" diff --git a/lisp/completion-preview.el b/lisp/completion-preview.el index caebb9d01e3..0e32beef5d0 100644 --- a/lisp/completion-preview.el +++ b/lisp/completion-preview.el @@ -49,6 +49,29 @@ ;; prefix (so nothing is underlined in the preview), it displays a list ;; of all matching completion candidates. ;; +;; You can also insert only the first word of the completion candidate +;; with the command `completion-preview-insert-word'. With a numeric +;; prefix argument, it inserts that many words instead of just the one. +;; This command is not bound by default, but you may want to bind it to +;; M-f (or remap `forward-word') in `completion-preview-active-mode-map' +;; since it's very much like a `forward-word' that also moves "into" the +;; completion preview. To define your own command that inserts part of +;; a completion candidate by moving "into" the completion preview, use +;; the function `completion-preview-partial-insert'. For example, you +;; can define a command that completes exactly one symbol as follows: +;; +;; (defun my-completion-preview-insert-symbol () +;; (interactive) +;; (completion-preview-partial-insert #'forward-symbol 1)) +;; +;; Similarly to `completion-preview-insert-word', the command +;; `completion-preview-insert-sexp' lets you complete by one or more +;; balanced expressions. The definition of this command is very similar +;; to the simple example above, expect it uses `forward-sexp' rather +;; than `forward-symbol'. This command can be useful when you're using +;; Completion Preview mode with long, complex completion candidates, +;; such as entire shell commands from the shell history. +;; ;; If you set the user option `completion-preview-exact-match-only' to ;; non-nil, Completion Preview mode only suggests a completion ;; candidate when its the only possible completion for the (partial) @@ -90,7 +113,9 @@ first candidate, and you can cycle between the candidates with delete-backward-char backward-delete-char-untabify analyze-text-conversion - completion-preview-complete) + completion-preview-complete + completion-preview-insert-word + completion-preview-insert-sexp) "List of commands that should trigger completion preview." :type '(repeat (function :tag "Command" :value self-insert-command)) :version "30.1") @@ -163,6 +188,8 @@ If this is nil, display the completion preview without delay." "M-i" #'completion-preview-complete ;; "M-n" #'completion-preview-next-candidate ;; "M-p" #'completion-preview-prev-candidate + ;; "<remap> <forward-word>" #'completion-preview-insert-word + ;; "<remap> <forward-sexp>" #'completion-preview-insert-sexp ) (defun completion-preview--ignore () @@ -444,24 +471,102 @@ point, otherwise hide it." (completion-preview--show) (completion-preview-active-mode -1))))) +(defun completion-preview--barf-if-no-preview () + "Signal a `user-error' if completion preview is not active." + (unless completion-preview-active-mode + (user-error "No current completion preview"))) + (defun completion-preview-insert () "Insert the completion candidate that the preview is showing." (interactive) - (if completion-preview-active-mode + (completion-preview--barf-if-no-preview) + (let* ((pre (completion-preview--get 'completion-preview-base)) + (end (completion-preview--get 'completion-preview-end)) + (ind (completion-preview--get 'completion-preview-index)) + (all (completion-preview--get 'completion-preview-suffixes)) + (com (completion-preview--get 'completion-preview-common)) + (efn (plist-get (completion-preview--get 'completion-preview-props) + :exit-function)) + (aft (completion-preview--get 'after-string)) + (str (concat pre com (nth ind all)))) + (completion-preview-active-mode -1) + (goto-char end) + (insert-and-inherit (substring-no-properties aft)) + (when (functionp efn) (funcall efn str 'finished)))) + +(defun completion-preview-partial-insert (fun &rest args) + "Insert part of the current completion preview candidate. + +This function calls FUN with arguments ARGS, after temporarily inserting +the entire current completion preview candidate. FUN should move point: +if it moves point forward into the completion text, this function +inserts the prefix of the completion candidate up to that point. +Beyond moving point, FUN should not modify the current buffer." + (completion-preview--barf-if-no-preview) + (let* ((end (completion-preview--get 'completion-preview-end)) + (aft (completion-preview--get 'after-string)) + (eoc (+ end (length aft)))) + ;; Keep region active, if it is already. This lets commands that + ;; call this function interact correctly with `shift-select-mode'. + (let ((deactivate-mark nil)) + ;; Partially insert current completion candidate. + (catch 'abort-atomic-change + (atomic-change-group + (let ((change-group (prepare-change-group))) + (save-excursion + (goto-char end) + ;; Temporarily insert the full completion candidate. + (insert-and-inherit (substring-no-properties aft))) + ;; Set point to the end of the prefix that we want to keep. + (apply fun args) + (unless (< end (point)) + ;; Point didn't advance into the completion, so abort change + ;; to avoid littering `buffer-undo-list' with a nop entry. + (throw 'abort-atomic-change nil)) + ;; Delete the rest. + (delete-region (min (point) eoc) eoc) + ;; Combine into one change group. + (undo-amalgamate-change-group change-group))))) + ;; Cleanup. + (cond + ;; If we kept the entire completion candidate, call :exit-function. + ((<= eoc (point)) (let* ((pre (completion-preview--get 'completion-preview-base)) - (end (completion-preview--get 'completion-preview-end)) (ind (completion-preview--get 'completion-preview-index)) (all (completion-preview--get 'completion-preview-suffixes)) (com (completion-preview--get 'completion-preview-common)) - (efn (plist-get (completion-preview--get 'completion-preview-props) - :exit-function)) - (aft (completion-preview--get 'after-string)) - (str (concat pre com (nth ind all)))) + (efn (plist-get + (completion-preview--get 'completion-preview-props) + :exit-function))) (completion-preview-active-mode -1) - (goto-char end) - (insert (substring-no-properties aft)) - (when (functionp efn) (funcall efn str 'finished))) - (user-error "No current completion preview"))) + (when (functionp efn) (funcall efn (concat pre com (nth ind all)) + 'finished)))) + ;; If we kept anything, update preview overlay accordingly. + ((< end (point)) + (completion-preview--inhibit-update) + (overlay-put (completion-preview--make-overlay + (point) + (propertize + (substring aft (- (point) end)) + 'mouse-face 'completion-preview-highlight + 'keymap completion-preview--mouse-map)) + 'completion-preview-end (point))) + ;; If we kept nothing, do nothing. + ))) + +(defun completion-preview-insert-word (&optional n) + "Insert the first N words of the current completion preview candidate. + +Interactively, N is the numeric prefix argument, and it defaults to 1." + (interactive "^p") + (completion-preview-partial-insert #'forward-word n)) + +(defun completion-preview-insert-sexp (&optional n) + "Insert the first N s-expressions of the current completion preview candidate. + +Interactively, N is the numeric prefix argument, and it defaults to 1." + (interactive "^p") + (completion-preview-partial-insert #'forward-sexp n 'interactive)) (defun completion-preview-complete () "Complete up to the longest common prefix of all completion candidates. @@ -472,8 +577,7 @@ candidates unless `completion-auto-help' is nil. If you repeat this command again when the completions list is visible, it scrolls the completions list." (interactive) - (unless completion-preview-active-mode - (user-error "No current completion preview")) + (completion-preview--barf-if-no-preview) (let* ((beg (completion-preview--get 'completion-preview-beg)) (end (completion-preview--get 'completion-preview-end)) (com (completion-preview--get 'completion-preview-common)) @@ -512,7 +616,7 @@ completions list." (completion-preview--inhibit-update) (completion-at-point)) ;; Otherwise, insert the common prefix and update the preview. - (insert ins) + (insert-and-inherit ins) (let ((suf (nth cur all)) (pos (point))) (if (or (string-empty-p suf) (null suf)) @@ -578,15 +682,21 @@ prefix argument and defaults to 1." (message (format-spec completion-preview-message-format `((?i . ,(1+ new)) (?n . ,len)))))))) -(defun completion-preview--active-p (_symbol buffer) - "Check if the completion preview is currently shown in BUFFER." +(defun completion-preview-active-p (_symbol buffer) + "Check if the completion preview is currently shown in BUFFER. + +The first argument, SYMBOL, is ignored. You can use this function as +the `completion-predicate' property of commands that you define that +should only be available when the completion preview is active." (buffer-local-value 'completion-preview-active-mode buffer)) (dolist (cmd '(completion-preview-insert + completion-preview-insert-word + completion-preview-insert-sexp completion-preview-complete completion-preview-prev-candidate completion-preview-next-candidate)) - (put cmd 'completion-predicate #'completion-preview--active-p)) + (put cmd 'completion-predicate #'completion-preview-active-p)) ;;;###autoload (define-minor-mode completion-preview-mode diff --git a/lisp/cus-edit.el b/lisp/cus-edit.el index 469f4334b44..5fd3629e57d 100644 --- a/lisp/cus-edit.el +++ b/lisp/cus-edit.el @@ -1280,7 +1280,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 "29.4" +(defvar customize-changed-options-previous-release "30.1" "Version for `customize-changed' to refer back to by default.") ;; Packages will update this variable, so make it available. diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 4ae9a5e6629..f96b1bad886 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el @@ -1511,15 +1511,18 @@ to do that. To reset the slice use `doc-view-reset-slice'." ;; Redisplay (doc-view-goto-page (doc-view-current-page))) +(defvar touch-screen-simple-mouse-conversion) ; Defined in touch-screen.el. + (defun doc-view-set-slice-using-mouse () "Set the slice of the images that should be displayed. You set the slice by pressing mouse-1 at its top-left corner and dragging it to its bottom-right corner. See also `doc-view-set-slice' and `doc-view-reset-slice'." (interactive) - (let (x y w h done) + (let ((touch-screen-simple-mouse-conversion t) + x y w h done) (while (not done) - (let ((e (read-event + (let ((e (read-key (concat "Press mouse-1 at the top-left corner and " "drag it to the bottom-right corner!")))) (when (eq (car e) 'drag-mouse-1) diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index c22dfb2eb26..bda5150cf07 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -289,6 +289,7 @@ made in the style guide relating to order." Currently, all recognized keywords must be on `finder-known-keywords'." :version "25.1" :type 'boolean) +;;;###autoload(put 'checkdoc-package-keywords-flag 'safe-local-variable #'booleanp) (defvar checkdoc-style-functions nil "Hook run after the standard style check is completed. diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index b0be96d7b35..359f206f1ab 100644 --- a/lisp/erc/erc.el +++ b/lisp/erc/erc.el @@ -12,7 +12,7 @@ ;; David Edmondson (dme@dme.org) ;; Michael Olson (mwolson@gnu.org) ;; Kelvin White (kwhite@gnu.org) -;; Version: 5.6.0.30.1 +;; Version: 5.6.1-git ;; Package-Requires: ((emacs "27.1") (compat "29.1.4.5")) ;; Keywords: IRC, chat, client, Internet ;; URL: https://www.gnu.org/software/emacs/erc.html @@ -70,7 +70,7 @@ (require 'auth-source) (eval-when-compile (require 'subr-x)) -(defconst erc-version "5.6.0.30.1" +(defconst erc-version "5.6.1-git" "This version of ERC.") (defvar erc-official-location diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index 2ff41c3d409..a5e9de79907 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -530,30 +530,34 @@ PROC is the process that's exiting. STRING is the exit message." (not (process-live-p proc)))) (finish-io (lambda () - (with-current-buffer (process-buffer proc) - (if (or (process-get proc :eshell-busy) - (and wait-for-stderr (car stderr-live))) - (progn + (if (buffer-live-p (process-buffer proc)) + (with-current-buffer (process-buffer proc) + (if (or (process-get proc :eshell-busy) + (and wait-for-stderr (car stderr-live))) + (progn + (eshell-debug-command 'process + "i/o busy for process `%s'" proc) + (run-at-time 0 nil finish-io)) + (when data + (ignore-error eshell-pipe-broken + (eshell-output-object + data index handles))) + (eshell-close-handles + status + (when status (list 'quote (= status 0))) + handles) + ;; Clear the handles to mark that we're 100% + ;; finished with the I/O for this process. + (process-put proc :eshell-handles nil) (eshell-debug-command 'process - "i/o busy for process `%s'" proc) - (run-at-time 0 nil finish-io)) - (when data - (ignore-error eshell-pipe-broken - (eshell-output-object - data index handles))) - (eshell-close-handles - status - (when status (list 'quote (= status 0))) - handles) - ;; Clear the handles to mark that we're 100% - ;; finished with the I/O for this process. - (process-put proc :eshell-handles nil) - (eshell-debug-command 'process - "finished external process `%s'" proc) - (if primary - (run-hook-with-args 'eshell-kill-hook - proc string) - (setcar stderr-live nil))))))) + "finished external process `%s'" proc) + (if primary + (run-hook-with-args 'eshell-kill-hook + proc string) + (setcar stderr-live nil)))) + (eshell-debug-command 'process + "buffer for external process `%s' already killed" + proc))))) (funcall finish-io))) (when-let ((entry (assq proc eshell-process-list))) (eshell-remove-process-entry entry)))))) diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el index 18e05a371a4..568f6745067 100644 --- a/lisp/eshell/eshell.el +++ b/lisp/eshell/eshell.el @@ -216,6 +216,34 @@ named \"*eshell*<2>\"." :type 'string :group 'eshell) +(defcustom eshell-command-async-buffer 'confirm-new-buffer + "What to do when the output buffer is used by another shell command. +This option specifies how to resolve the conflict where a new command +wants to direct its output to the buffer whose name is stored +in `eshell-command-buffer-name-async', but that buffer is already +taken by another running shell command. + +The value `confirm-kill-process' is used to ask for confirmation before +killing the already running process and running a new process in the +same buffer, `confirm-new-buffer' for confirmation before running the +command in a new buffer with a name other than the default buffer name, +`new-buffer' for doing the same without confirmation, +`confirm-rename-buffer' for confirmation before renaming the existing +output buffer and running a new command in the default buffer, +`rename-buffer' for doing the same without confirmation." + :type '(choice (const :tag "Confirm killing of running command" + confirm-kill-process) + (const :tag "Confirm creation of a new buffer" + confirm-new-buffer) + (const :tag "Create a new buffer" + new-buffer) + (const :tag "Confirm renaming of existing buffer" + confirm-rename-buffer) + (const :tag "Rename the existing buffer" + rename-buffer)) + :group 'eshell + :version "31.1") + ;;;_* Running Eshell ;; ;; There are only three commands used to invoke Eshell. The first two @@ -283,11 +311,19 @@ information on Eshell, see Info node `(eshell)Top'." (eshell-command-mode +1)) (read-from-minibuffer prompt)))) +(defvar eshell-command-buffer-name-async "*Eshell Async Command Output*") +(defvar eshell-command-buffer-name-sync "*Eshell Command Output*") + ;;;###autoload (defun eshell-command (command &optional to-current-buffer) "Execute the Eshell command string COMMAND. If TO-CURRENT-BUFFER is non-nil (interactively, with the prefix -argument), then insert output into the current buffer at point." +argument), then insert output into the current buffer at point. + +When \"&\" is added at end of command, the command is async and its output +appears in a specific buffer. You can customize +`eshell-command-async-buffer' to specify what to do when this output +buffer is already taken by another running shell command." (interactive (list (eshell-read-command) current-prefix-arg)) (save-excursion @@ -301,18 +337,46 @@ argument), then insert output into the current buffer at point." (eshell-current-subjob-p)) ,(eshell-parse-command command)) command)) - intr - (bufname (if (eq (car-safe proc) :eshell-background) - "*Eshell Async Command Output*" - (setq intr t) - "*Eshell Command Output*"))) - (if (buffer-live-p (get-buffer bufname)) - (kill-buffer bufname)) - (rename-buffer bufname) + (async (eq (car-safe proc) :eshell-background)) + (bufname (cond + (to-current-buffer nil) + (async eshell-command-buffer-name-async) + (t eshell-command-buffer-name-sync))) + unique) + (when bufname + (when (buffer-live-p (get-buffer bufname)) + (cond + ((with-current-buffer bufname + (and (null eshell-foreground-command) + (null eshell-background-commands))) + ;; The old buffer is done executing; kill it so we can + ;; take its place. + (kill-buffer bufname)) + ((eq eshell-command-async-buffer 'confirm-kill-process) + (shell-command--same-buffer-confirm "Kill it") + (with-current-buffer bufname + ;; Stop all the processes in the old buffer (there may + ;; be several). + (eshell-process-interact #'interrupt-process t)) + (accept-process-output) + (kill-buffer bufname)) + ((eq eshell-command-async-buffer 'confirm-new-buffer) + (shell-command--same-buffer-confirm "Use a new buffer") + (setq unique t)) + ((eq eshell-command-async-buffer 'new-buffer) + (setq unique t)) + ((eq eshell-command-async-buffer 'confirm-rename-buffer) + (shell-command--same-buffer-confirm "Rename it") + (with-current-buffer bufname + (rename-uniquely))) + ((eq eshell-command-async-buffer 'rename-buffer) + (with-current-buffer bufname + (rename-uniquely))))) + (rename-buffer bufname unique)) ;; things get a little coarse here, since the desire is to ;; make the output as attractive as possible, with no ;; extraneous newlines - (when intr + (unless async (apply #'eshell-wait-for-process (cadr eshell-foreground-command)) (cl-assert (not eshell-foreground-command)) (goto-char (point-max)) @@ -320,7 +384,7 @@ argument), then insert output into the current buffer at point." (delete-char -1))) (cl-assert (and buf (buffer-live-p buf))) (unless to-current-buffer - (let ((len (if (not intr) 2 + (let ((len (if async 2 (count-lines (point-min) (point-max))))) (cond ((= len 0) @@ -336,7 +400,7 @@ argument), then insert output into the current buffer at point." ;; cause the output buffer to take up as little screen ;; real-estate as possible, if temp buffer resizing is ;; enabled - (and intr temp-buffer-resize-mode + (and (not async) temp-buffer-resize-mode (resize-temp-buffer-window))))))))))) ;;;###autoload diff --git a/lisp/gnus/canlock.el b/lisp/gnus/canlock.el index 02744a7f0a5..39ae6809a55 100644 --- a/lisp/gnus/canlock.el +++ b/lisp/gnus/canlock.el @@ -41,8 +41,6 @@ ;;; Code: -(require 'sha1) - (defvar mail-header-separator) (defgroup canlock nil diff --git a/lisp/international/quail.el b/lisp/international/quail.el index 48d2ccb8828..cb7aa89b252 100644 --- a/lisp/international/quail.el +++ b/lisp/international/quail.el @@ -1334,9 +1334,13 @@ If STR has `advice' text property, append the following special event: (quail-setup-overlays (quail-conversion-keymap)) (with-silent-modifications (unwind-protect - (let ((input-string (if (quail-conversion-keymap) + (let* (;; `with-silent-modifications' inhibits the modification + ;; hooks, but that's a part of `with-silent-modifications' + ;; we don't actually want here (bug#70541). + (inhibit-modification-hooks nil) + (input-string (if (quail-conversion-keymap) (quail-start-conversion key) - (quail-start-translation key)))) + (quail-start-translation key)))) (setq quail-guidance-str "") (when (and (stringp input-string) (> (length input-string) 0)) @@ -1871,10 +1875,9 @@ sequence counting from the head." (defsubst quail-point-in-conversion-region () "Return non-nil value if the point is in conversion region of Quail mode." - (let (start pos) - (and (setq start (overlay-start quail-conv-overlay)) - (>= (setq pos (point)) start) - (<= pos (overlay-end quail-conv-overlay))))) + (let ((start (overlay-start quail-conv-overlay))) + (and start + (<= start (point) (overlay-end quail-conv-overlay))))) (defun quail-conversion-backward-char () (interactive) diff --git a/lisp/international/utf7.el b/lisp/international/utf7.el index 63009b0744a..2b23bee1038 100644 --- a/lisp/international/utf7.el +++ b/lisp/international/utf7.el @@ -63,7 +63,6 @@ ;;; Code: -(require 'base64) (require 'mm-util) (defconst utf7-direct-encoding-chars " -%'-*,-[]-}" diff --git a/lisp/net/eww.el b/lisp/net/eww.el index 94bfd333fa9..907b35f8565 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -1370,8 +1370,13 @@ within text input fields." (save-excursion (goto-char (point-min)) (while-let ((match (text-property-search-forward - 'display nil (lambda (_ value) (imagep value))))) - (let* ((image (prop-match-value match)) + 'display nil + (lambda (_ value) + (and value (get-display-property + nil 'image nil value)))))) + (let* ((image (cons 'image + (get-display-property nil 'image nil + (prop-match-value match)))) (original-scale (or (image-property image :original-scale) (setf (image-property image :original-scale) (or (image-property image :scale) diff --git a/lisp/net/hmac-md5.el b/lisp/net/hmac-md5.el index 1c4ac24a9c4..af323b0d2b0 100644 --- a/lisp/net/hmac-md5.el +++ b/lisp/net/hmac-md5.el @@ -29,7 +29,6 @@ (eval-when-compile (require 'hmac-def)) (require 'hex-util) ; (decode-hex-string STRING) -(require 'md5) ; expects (md5 STRING) (defun md5-binary (string) "Return the MD5 of STRING in binary form." diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 3dadcb9a09b..ea3d8deeff8 100644 --- a/lisp/net/shr.el +++ b/lisp/net/shr.el @@ -58,6 +58,20 @@ fit these criteria." :version "24.1" :type 'float) +(defcustom shr-sliced-image-height 0.9 + "How tall images can be before slicing in relation to the window they're in. +A value of 0.7 means that images are allowed to take up 70% of the +height of the window before being sliced by `insert-sliced-image'. If +nil, never slice images. + +Sliced images allow for more intuitive scrolling up/down by letting you +scroll past each slice, instead of jumping past the entire image. +Alternately, you can use `pixel-scroll-precision-mode' to scroll +pixel-wise past images, in which case you can set this option to nil." + :version "31.1" + :type '(choice (const :tag "Never slice images") + float)) + (defcustom shr-allowed-images nil "If non-nil, only images that match this regexp are displayed. If nil, all URLs are allowed. Also see `shr-blocked-images'." @@ -205,6 +219,25 @@ interpreted as a multiple of the height of default font." :version "30.1" :type '(choice (const nil) (cons number number))) +(defcustom shr-image-zoom-levels '(fit original fill-height) + "A list of image zoom levels to cycle through with `shr-zoom-image'. +The first element in the list is the initial zoom level. Each element +can be one of the following symbols: + +* `fit': Display the image at its original size as requested by the + page, shrinking it to fit in the current window if necessary. +* `original': Display the image at its original size as requested by the + page. +* `image': Display the image at its full size (ignoring the width/height + specified by the HTML). +* `fill-height': Display the image zoomed to fill the height of the +current window." + :version "31.1" + :type '(set (choice (const :tag "Fit to window size" fit) + (const :tag "Original size" original) + (const :tag "Full image size" image) + (const :tag "Fill window height" fill-height)))) + (defvar shr-content-function nil "If bound, this should be a function that will return the content. This is used for cid: URLs, and the function is called with the @@ -607,35 +640,60 @@ the URL of the image to the kill buffer instead." (list (current-buffer) (1- (point)) (point-marker)) t)))) -(defun shr-zoom-image () - "Cycle the image size. +(defvar shr-image-zoom-level-alist + `((fit "Zoom to fit" shr-rescale-image) + (original "Zoom to original size" shr--image-zoom-original-size) + (image "Zoom to full image size" shr--image-zoom-image-size) + (fill-height "Zoom to fill window height" shr--image-zoom-fill-height)) + "An alist of possible image zoom levels. +Each element is of the form (SYMBOL DESC FUNCTION). SYMBOL is the +symbol identifying this level, as used by `shr-image-zoom-levels' (which +see). DESC is a string describing the level. + +FUNCTION is a function that returns a properly-zoomed image; it takes +the following arguments: + +* DATA: The image data in string form. +* CONTENT-TYPE: The content-type of the image, if any. +* WIDTH: The width as specified by the HTML \"width\" attribute, if any. +* HEIGHT: The height as specified by the HTML \"height\" attribute, if + any.") + +(defun shr-zoom-image (&optional position zoom-level) + "Change the zoom level of the image at POSITION. + The size will cycle through the default size, the original size, and full-buffer size." - (interactive) - (let ((url (get-text-property (point) 'image-url))) + (interactive "d") + (unless position (setq position (point))) + (let ((url (get-text-property position 'image-url))) (if (not url) (message "No image under point") - (let* ((end (or (next-single-property-change (point) 'image-url) + (unless zoom-level + (let ((last-zoom (get-text-property position 'image-zoom))) + (setq zoom-level (or (cadr (memq last-zoom shr-image-zoom-levels)) + (car shr-image-zoom-levels))))) + (let* ((end (or (next-single-property-change position 'image-url) (point-max))) (start (or (previous-single-property-change end 'image-url) (point-min))) - (size (get-text-property (point) 'image-size)) - (next-size (cond ((or (eq size 'default) - (null size)) - 'original) - ((eq size 'original) - 'full) - ((eq size 'full) - 'default))) + (dom-size (get-text-property position 'image-dom-size)) + (flags `( :zoom ,zoom-level + :width ,(car dom-size) + :height ,(cdr dom-size))) (buffer-read-only nil)) ;; Delete the old picture. (put-text-property start end 'display nil) - (message "Inserting %s..." url) - (url-retrieve url #'shr-image-fetched - `(,(current-buffer) ,start - ,(set-marker (make-marker) end) - ((size . ,next-size))) - t))))) + (message "%s" (cadr (assq zoom-level shr-image-zoom-level-alist))) + (if (and (not shr-ignore-cache) + (url-is-cached url)) + (shr-replace-image (shr-get-image-data url) start + (set-marker (make-marker) end) flags) + (url-retrieve url #'shr-image-fetched + `(,(current-buffer) ,start + ,(set-marker (make-marker) end) + ,flags) + t)))))) ;;; Utility functions. @@ -1056,6 +1114,25 @@ the mouse click event." (expand-file-name (file-name-nondirectory url) directory))))) +(defun shr-replace-image (data start end &optional flags) + (save-excursion + (save-restriction + (widen) + (let ((alt (buffer-substring start end)) + (properties (text-properties-at start)) + ;; We don't want to record these changes. + (buffer-undo-list t) + (inhibit-read-only t)) + (remove-overlays start end) + (delete-region start end) + (goto-char start) + (funcall shr-put-image-function data alt flags) + (while properties + (let ((type (pop properties)) + (value (pop properties))) + (unless (memq type '(display image-zoom)) + (put-text-property start (point) type value)))))))) + (defun shr-image-fetched (status buffer start end &optional flags) (let ((image-buffer (current-buffer))) (when (and (buffer-name buffer) @@ -1066,23 +1143,7 @@ the mouse click event." (search-forward "\r\n\r\n" nil t)) (let ((data (shr-parse-image-data))) (with-current-buffer buffer - (save-excursion - (save-restriction - (widen) - (let ((alt (buffer-substring start end)) - (properties (text-properties-at start)) - ;; We don't want to record these changes. - (buffer-undo-list t) - (inhibit-read-only t)) - (remove-overlays start end) - (delete-region start end) - (goto-char start) - (funcall shr-put-image-function data alt flags) - (while properties - (let ((type (pop properties)) - (value (pop properties))) - (unless (memq type '(display image-size)) - (put-text-property start (point) type value))))))))))) + (shr-replace-image data start end flags))))) (kill-buffer image-buffer))) (defun shr-image-from-data (data) @@ -1118,9 +1179,21 @@ the mouse click event." (defun shr-put-image (spec alt &optional flags) "Insert image SPEC with a string ALT. Return image. SPEC is either an image data blob, or a list where the first -element is the data blob and the second element is the content-type." +element is the data blob and the second element is the content-type. + +FLAGS is a property list specifying optional parameters for the image. +You can specify the following optional properties: + +* `:zoom': The zoom level for the image. One of `default', `original', + or `full'. +* `:width': The width of the image as specified by the HTML \"width\" + attribute. +* `:height': The height of the image as specified by the HTML + \"height\" attribute." (if (display-graphic-p) - (let* ((size (cdr (assq 'size flags))) + (let* ((zoom (or (plist-get flags :zoom) + (car shr-image-zoom-levels))) + (zoom-function (nth 2 (assq zoom shr-image-zoom-level-alist))) (data (if (consp spec) (car spec) spec)) @@ -1128,22 +1201,15 @@ element is the data blob and the second element is the content-type." (cadr spec))) (start (point)) (image (cond - ((eq size 'original) - (create-image data nil t :ascent shr-image-ascent - :format content-type)) ((eq content-type 'image/svg+xml) (when (image-type-available-p 'svg) (create-image data 'svg t :ascent shr-image-ascent))) - ((eq size 'full) - (ignore-errors - (shr-rescale-image data content-type - (plist-get flags :width) - (plist-get flags :height)))) - (t - (ignore-errors - (shr-rescale-image data content-type - (plist-get flags :width) - (plist-get flags :height))))))) + (zoom-function + (ignore-errors + (funcall zoom-function data content-type + (plist-get flags :width) + (plist-get flags :height)))) + (t (error "Unrecognized zoom level %s" zoom))))) (when image ;; The trailing space can confuse shr-insert into not ;; putting any space after inline images. @@ -1157,20 +1223,28 @@ element is the data blob and the second element is the content-type." (when (and (> (current-column) 0) (not inline)) (insert "\n")) - (let ((image-pos (point))) - (if (eq size 'original) + (let ((image-pos (point)) + image-height body-height) + (if (and shr-sliced-image-height + (setq image-height (cdr (image-size image t)) + body-height (window-body-height + (get-buffer-window (current-buffer)) + t)) + (> (/ image-height body-height 1.0) + shr-sliced-image-height)) ;; Normally, we try to keep the buffer text the same ;; by preserving ALT. With a sliced image, we have to ;; repeat the text for each line, so we can't do that. ;; Just use "*" for the string to insert instead. (progn - (insert-sliced-image image "*" nil 20 1) + (insert-sliced-image + image "*" nil (/ image-height (default-line-height)) 1) (let ((overlay (make-overlay start (point)))) ;; Avoid displaying unsightly decorations on the ;; image slices. (overlay-put overlay 'face 'shr-sliced-image))) (insert-image image alt)) - (put-text-property start (point) 'image-size size) + (put-text-property start (point) 'image-zoom zoom) (when (and (not inline) shr-max-inline-image-size) (insert "\n")) (when (and shr-image-animate @@ -1208,27 +1282,33 @@ width/height instead." (or max-height (- (nth 3 edges) (nth 1 edges)))))) (scaling (image-compute-scaling-factor image-scaling-factor))) - (when (or (and width - (> width max-width)) - (and height - (> height max-height))) - (setq width nil - height nil)) - (if (and width height - (< (* width scaling) max-width) - (< (* height scaling) max-height)) - (create-image - data (shr--image-type) t - :ascent shr-image-ascent - :width width - :height height - :format content-type) - (create-image - data (shr--image-type) t - :ascent shr-image-ascent - :max-width max-width - :max-height max-height - :format content-type))))) + (when (and width (> (* width scaling) max-width)) + (setq width nil)) + (when (and height (> (* height scaling) max-height)) + (setq height nil)) + (create-image + data (shr--image-type) t + :ascent shr-image-ascent + :width width + :height height + :max-width max-width + :max-height max-height + :format content-type)))) + +(defun shr--image-zoom-original-size (data content-type width height) + (create-image data (shr--image-type) t :ascent shr-image-ascent + :width width :height height :format content-type)) + +(defun shr--image-zoom-image-size (data content-type _width _height) + (create-image data nil t :ascent shr-image-ascent :format content-type)) + +(defun shr--image-zoom-fill-height (data content-type _width _height) + (let* ((edges (window-inside-pixel-edges + (get-buffer-window (current-buffer)))) + (height (truncate (* shr-max-image-proportion + (- (nth 3 edges) (nth 1 edges)))))) + (create-image data (shr--image-type) t :ascent shr-image-ascent + :height height :format content-type))) ;; url-cache-extract autoloads url-cache. (declare-function url-cache-create-filename "url-cache" (url)) @@ -1885,6 +1965,7 @@ The preference is a float determined from `shr-prefer-media-type'." (put-text-property start (point) 'keymap shr-image-map) (put-text-property start (point) 'shr-alt alt) (put-text-property start (point) 'image-url url) + (put-text-property start (point) 'image-dom-size (cons width height)) (put-text-property start (point) 'image-displayer (shr-image-displayer shr-content-function)) (put-text-property start (point) 'help-echo diff --git a/lisp/org/ob-processing.el b/lisp/org/ob-processing.el index 2733b1d1f6d..f7326f0eea7 100644 --- a/lisp/org/ob-processing.el +++ b/lisp/org/ob-processing.el @@ -56,7 +56,6 @@ (org-assert-version) (require 'ob) -(require 'sha1) (declare-function processing-sketch-run "ext:processing-mode" ()) diff --git a/lisp/org/org-feed.el b/lisp/org/org-feed.el index 4077afa0d3c..c90174f0fa7 100644 --- a/lisp/org/org-feed.el +++ b/lisp/org/org-feed.el @@ -92,7 +92,6 @@ (org-assert-version) (require 'org) -(require 'sha1) (declare-function url-retrieve-synchronously "url" (url &optional silent inhibit-cookies timeout)) diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index e8d1e692d0f..d2d0baa235c 100644 --- a/lisp/progmodes/grep.el +++ b/lisp/progmodes/grep.el @@ -827,15 +827,23 @@ The value depends on `grep-command', `grep-template', (unless grep-find-use-xargs (setq grep-find-use-xargs (cond - ((grep-probe find-program - `(nil nil nil ,(null-device) "-exec" "echo" - "{}" "+")) - 'exec-plus) + ;; For performance, we want: + ;; A. Run grep on batches of files (instead of one grep per file) + ;; B. If the directory is large and we need multiple batches, + ;; run find in parallel with a running grep. + ;; "find | xargs grep" gives both A and B ((and + (not (eq system-type 'windows-nt)) (grep-probe find-program `(nil nil nil ,(null-device) "-print0")) (grep-probe xargs-program '(nil nil nil "-0" "echo"))) 'gnu) + ;; "find -exec {} +" gives A but not B + ((grep-probe find-program + `(nil nil nil ,(null-device) "-exec" "echo" + "{}" "+")) + 'exec-plus) + ;; "find -exec {} ;" gives neither A nor B. (t 'exec)))) (unless grep-find-command diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 8d0f49c2d89..06daadbc1fd 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -722,10 +722,10 @@ Calls REPORT-FN directly." (defvar lua-ts-mode-map (let ((map (make-sparse-keymap "Lua"))) - (define-key map "\C-c\C-n" 'lua-ts-inferior-lua) - (define-key map "\C-c\C-c" 'lua-ts-send-buffer) - (define-key map "\C-c\C-l" 'lua-ts-send-file) - (define-key map "\C-c\C-r" 'lua-ts-send-region) + (keymap-set map "C-c C-n" 'lua-ts-inferior-lua) + (keymap-set map "C-c C-c" 'lua-ts-send-buffer) + (keymap-set map "C-c C-l" 'lua-ts-send-file) + (keymap-set map "C-c C-r" 'lua-ts-send-region) map) "Keymap for `lua-ts-mode' buffers.") diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el index 68685fb6625..ff71970d41b 100644 --- a/lisp/progmodes/perl-mode.el +++ b/lisp/progmodes/perl-mode.el @@ -1130,14 +1130,7 @@ Returns (parse-state) if line starts inside a string." ;; add the perl-brace-imaginary-offset. (progn (skip-chars-backward " \t") (if (bolp) 0 perl-brace-imaginary-offset)) - ;; If the openbrace is preceded by a parenthesized exp, - ;; move to the beginning of that; - ;; possibly a different line - (progn - (if (eq (preceding-char) ?\)) - (forward-sexp -1)) - ;; Get initial indentation of the line we are on. - (current-indentation))))))))) + (perl-indent-new-calculate 'virtual)))))))) (defun perl-backward-to-noncomment () "Move point backward to after the first non-white-space, skipping comments." diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index 89eefd1f08a..73d6bdd2d2d 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -7042,6 +7042,7 @@ Add import for undefined name `%s' (empty to skip): " (defvar electric-indent-inhibit) (defvar prettify-symbols-alist) +(defvar python--installed-grep-hook nil) ;;;###autoload (define-derived-mode python-base-mode prog-mode "Python" @@ -7126,6 +7127,15 @@ implementations: `python-mode' and `python-ts-mode'." "`outline-level' function for Python mode." (1+ (/ (current-indentation) python-indent-offset)))) + (unless python--installed-grep-hook + (setq python--installed-grep-hook t) + (with-eval-after-load 'grep + (defvar grep-files-aliases) + (defvar grep-find-ignored-directories) + (cl-pushnew '("py" . "*.py") grep-files-aliases :test #'equal) + (dolist (dir '(".tox" ".venv" ".mypy_cache" ".ruff_cache")) + (cl-pushnew dir grep-find-ignored-directories)))) + (setq-local prettify-symbols-alist python-prettify-symbols-alist) (make-local-variable 'python-shell-internal-buffer) diff --git a/lisp/subr.el b/lisp/subr.el index ab388630a91..36b5353b577 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3338,7 +3338,15 @@ only unbound fallback disabled is downcasing of the last event." ;; though read-key-sequence thinks we should wait ;; for more input to decide how to interpret the ;; current input. - (throw 'read-key keys))))))) + ;; + ;; As this treatment will completely defeat the + ;; purpose of touch screen event conversion, + ;; dispense with this timeout when the first + ;; event in this vector is a touch-screen event. + (unless (memq (car-safe (aref keys 0)) '(touchscreen-begin + touchscreen-update + touchscreen-end)) + (throw 'read-key keys)))))))) (unwind-protect (progn (use-global-map diff --git a/lisp/textmodes/reftex-global.el b/lisp/textmodes/reftex-global.el index 0eaffec3b54..7b4407ec336 100644 --- a/lisp/textmodes/reftex-global.el +++ b/lisp/textmodes/reftex-global.el @@ -152,7 +152,7 @@ No active TAGS table is required." (setq dlist (reftex-uniquify-by-car dlist)) (if (null dlist) (error "No duplicate labels in document")) (switch-to-buffer-other-window "*Duplicate Labels*") - (set (make-local-variable 'TeX-master) master) + (setq-local TeX-master master) (erase-buffer) (insert " MULTIPLE LABELS IN CURRENT DOCUMENT:\n") (insert @@ -492,17 +492,16 @@ With no argument, this command toggles (with-current-buffer crt-buf (when reftex-mode (if (boundp 'multi-isearch-next-buffer-function) - (set (make-local-variable - 'multi-isearch-next-buffer-function) - #'reftex-isearch-switch-to-next-file) - (set (make-local-variable 'isearch-wrap-function) - #'reftex-isearch-wrap-function) - (set (make-local-variable 'isearch-search-fun-function) - (lambda () #'reftex-isearch-isearch-search)) - (set (make-local-variable 'isearch-push-state-function) - #'reftex-isearch-push-state-function) - (set (make-local-variable 'isearch-next-buffer-function) - #'reftex-isearch-switch-to-next-file)) + (setq-local multi-isearch-next-buffer-function + #'reftex-isearch-switch-to-next-file) + (setq-local isearch-wrap-function + #'reftex-isearch-wrap-function) + (setq-local isearch-search-fun-function + (lambda () #'reftex-isearch-isearch-search)) + (setq-local isearch-push-state-function + #'reftex-isearch-push-state-function) + (setq-local isearch-next-buffer-function + #'reftex-isearch-switch-to-next-file)) (setq reftex-isearch-minor-mode t)))) (add-hook 'reftex-mode-hook #'reftex-isearch-minor-mode)) (dolist (crt-buf (buffer-list)) diff --git a/lisp/textmodes/reftex-index.el b/lisp/textmodes/reftex-index.el index a93afd63855..db476ff5c0b 100644 --- a/lisp/textmodes/reftex-index.el +++ b/lisp/textmodes/reftex-index.el @@ -387,9 +387,9 @@ Press `?' for a summary of important key bindings, or check the menu. Here are all local bindings. \\{reftex-index-mode-map}" - (set (make-local-variable 'revert-buffer-function) #'reftex-index-revert) - (set (make-local-variable 'reftex-index-restriction-data) nil) - (set (make-local-variable 'reftex-index-restriction-indicator) nil) + (setq-local revert-buffer-function #'reftex-index-revert) + (setq-local reftex-index-restriction-data nil) + (setq-local reftex-index-restriction-indicator nil) (setq mode-line-format (list "---- " 'mode-line-buffer-identification " " 'global-mode-string @@ -511,9 +511,9 @@ With prefix 3, restrict index to region." ;; If the buffer is currently restricted, empty it to force update. (when reftex-index-restriction-data (reftex-erase-buffer)) - (set (make-local-variable 'reftex-last-index-file) calling-file) - (set (make-local-variable 'reftex-index-tag) index-tag) - (set (make-local-variable 'reftex-docstruct-symbol) docstruct-symbol) + (setq-local reftex-last-index-file calling-file) + (setq-local reftex-index-tag index-tag) + (setq-local reftex-docstruct-symbol docstruct-symbol) (if restriction (setq reftex-index-restriction-indicator (car restriction) reftex-index-restriction-data (cdr restriction)) @@ -1303,8 +1303,7 @@ If the buffer is non-empty, delete the old header first." (lambda (a _b) (equal (car a) default-macro)))) macro entry key repeat) - (if master (set (make-local-variable 'TeX-master) - (file-name-nondirectory master))) + (when master (setq-local TeX-master (file-name-nondirectory master))) (when (> (buffer-size) 0) (goto-char 1) @@ -1387,9 +1386,9 @@ Here are all local bindings. \\{reftex-index-phrases-mode-map}" :syntax-table reftex-index-phrases-syntax-table - (set (make-local-variable 'font-lock-defaults) - reftex-index-phrases-font-lock-defaults) - (set (make-local-variable 'reftex-index-phrases-marker) (make-marker))) + (setq-local font-lock-defaults + reftex-index-phrases-font-lock-defaults) + (setq-local reftex-index-phrases-marker (make-marker))) ;; (add-hook 'reftex-index-phrases-mode-hook #'turn-on-font-lock) (defun reftex-index-next-phrase (&optional arg) diff --git a/lisp/textmodes/reftex-sel.el b/lisp/textmodes/reftex-sel.el index fa36543daf4..aec89448481 100644 --- a/lisp/textmodes/reftex-sel.el +++ b/lisp/textmodes/reftex-sel.el @@ -97,7 +97,7 @@ Press `?' for a summary of important key bindings. During a selection process, these are the local bindings. \\{reftex-select-label-mode-map}" - (set (make-local-variable 'reftex-select-marked) nil) + (setq-local reftex-select-marked nil) (when (syntax-table-p reftex-latex-syntax-table) (set-syntax-table reftex-latex-syntax-table)) ;; We do not set a local map - reftex-select-item does this. @@ -136,7 +136,7 @@ Press `?' for a summary of important key bindings. During a selection process, these are the local bindings. \\{reftex-select-label-mode-map}" - (set (make-local-variable 'reftex-select-marked) nil) + (setq-local reftex-select-marked nil) ;; We do not set a local map - reftex-select-item does this. ) @@ -236,9 +236,9 @@ During a selection process, these are the local bindings. (concat "\\`" (regexp-quote (file-name-directory (reftex-TeX-master-file)))))) - (set (make-local-variable 'reftex-docstruct-symbol) docstruct-symbol) - (set (make-local-variable 'reftex-prefix) - (cdr (assoc labels reftex-typekey-to-prefix-alist))) + (setq-local reftex-docstruct-symbol docstruct-symbol) + (setq-local reftex-prefix + (cdr (assoc labels reftex-typekey-to-prefix-alist))) (if (equal reftex-prefix " ") (setq reftex-prefix nil)) ;; Walk the docstruct and insert the appropriate stuff @@ -459,7 +459,7 @@ During a selection process, these are the local bindings. (reftex-find-start-point (point-min) offset reftex-last-data reftex-last-line) (beginning-of-line 1) - (set (make-local-variable 'reftex-last-follow-point) (point)) + (setq-local reftex-last-follow-point (point)) (unwind-protect (progn @@ -480,9 +480,9 @@ During a selection process, these are the local bindings. (mapc (lambda (c) (delete-overlay (nth 1 c))) reftex-select-marked))))) - (set (make-local-variable 'reftex-last-line) - (+ (count-lines (point-min) (point)) (if (bolp) 1 0))) - (set (make-local-variable 'reftex-last-data) reftex--last-data) + (setq-local reftex-last-line + (+ (count-lines (point-min) (point)) (if (bolp) 1 0))) + (setq-local reftex-last-data reftex--last-data) (reftex-kill-buffer "*RefTeX Help*") (setq reftex-callback-fwd (not reftex-callback-fwd)) ;; ;-))) (message "") diff --git a/lisp/textmodes/reftex-toc.el b/lisp/textmodes/reftex-toc.el index 1cc6e27e780..fe5a32f15f0 100644 --- a/lisp/textmodes/reftex-toc.el +++ b/lisp/textmodes/reftex-toc.el @@ -1,6 +1,6 @@ ;;; reftex-toc.el --- RefTeX's table of contents mode -*- lexical-binding: t; -*- -;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc. +;; Copyright (C) 1997-2024 Free Software Foundation, Inc. ;; Author: Carsten Dominik <dominik@science.uva.nl> ;; Maintainer: auctex-devel@gnu.org @@ -125,13 +125,13 @@ Press `?' for a summary of important key bindings. Here are all local bindings. \\{reftex-toc-mode-map}" - (set (make-local-variable 'transient-mark-mode) t) - (set (make-local-variable 'revert-buffer-function) #'reftex-toc-revert) - (set (make-local-variable 'reftex-toc-include-labels-indicator) "") - (set (make-local-variable 'reftex-toc-max-level-indicator) - (if (= reftex-toc-max-level 100) - "ALL" - (int-to-string reftex-toc-max-level))) + (setq-local transient-mark-mode t) + (setq-local revert-buffer-function #'reftex-toc-revert) + (setq-local reftex-toc-include-labels-indicator "") + (setq-local reftex-toc-max-level-indicator + (if (= reftex-toc-max-level 100) + "ALL" + (int-to-string reftex-toc-max-level))) (setq mode-line-format (list "---- " 'mode-line-buffer-identification " " 'global-mode-string " (" mode-name ")" @@ -241,7 +241,7 @@ When called with a raw \\[universal-argument] prefix, rescan the document first. (switch-to-buffer "*toc*")) (or (eq major-mode 'reftex-toc-mode) (reftex-toc-mode)) - (set (make-local-variable 'reftex-docstruct-symbol) docstruct-symbol) + (setq-local reftex-docstruct-symbol docstruct-symbol) (setq reftex-toc-include-labels-indicator (if (eq reftex-toc-include-labels t) "ALL" diff --git a/lisp/textmodes/reftex.el b/lisp/textmodes/reftex.el index 6974a4be4a7..efe38337001 100644 --- a/lisp/textmodes/reftex.el +++ b/lisp/textmodes/reftex.el @@ -1,6 +1,6 @@ ;;; reftex.el --- minor mode for doing \label, \ref, \cite, \index in LaTeX -*- lexical-binding: t; -*- -;; Copyright (C) 1997-2000, 2003-2024 Free Software Foundation, Inc. +;; Copyright (C) 1997-2024 Free Software Foundation, Inc. ;; Author: Carsten Dominik <dominik@science.uva.nl> ;; Maintainer: auctex-devel@gnu.org @@ -2036,8 +2036,8 @@ IGNORE-WORDS List of words which should be removed from the string." ;; of font-lock) (rename-buffer newname t) ;; Good: we have the indirection functions - (set (make-local-variable 'font-lock-fontify-region-function) - #'reftex-select-font-lock-fontify-region) + (setq-local font-lock-fontify-region-function + #'reftex-select-font-lock-fontify-region) (let ((major-mode 'latex-mode)) (font-lock-mode 1))) (rename-buffer oldname)))) diff --git a/lisp/textmodes/rst.el b/lisp/textmodes/rst.el index 5fbff4ba888..1e09d3a6eb6 100644 --- a/lisp/textmodes/rst.el +++ b/lisp/textmodes/rst.el @@ -102,7 +102,6 @@ ;; FIXME: Embed complicated `defconst's in `eval-when-compile'. -;; Common Lisp stuff (require 'cl-lib) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index c5918efb800..57eff075e73 100644 --- a/lisp/touch-screen.el +++ b/lisp/touch-screen.el @@ -157,13 +157,22 @@ dragging.") ;; Should this variable be documented? (defvar-local touch-screen-keyboard-function nil "Function that decides whether to display the on screen keyboard. -If set, this function is called with point set to the position of the -tap involved when a command listed in `touch-screen-set-point-commands' -is about to be invoked in response to a tap, the current buffer, or the -text beneath point (in the case of an `inhibit-read-only' text -property), is not read only, and `touch-screen-display-keyboard' is nil, -and should return non-nil if it is appropriate to display the on-screen -keyboard afterwards.") +If set, this function is called with point set to the position +of the tap involved when a command listed in +`touch-screen-set-point-commands' is about to be invoked in +response to a tap, the current buffer, or the text beneath +point (in the case of an `inhibit-read-only' text property), is +not read only, and `touch-screen-display-keyboard' is nil, and +should return non-nil if it is appropriate to display the +on-screen keyboard afterwards.") + +(defvar touch-screen-simple-mouse-conversion nil + "Whether to unconditionally enable simple mouse event translation. +If non-nil, touch screen event conversion will always proceed as +though a command was bound to `down-mouse-1' at the position of +the initial tap. That is to say, taps, mouse motion, and +touchpoint removals will be unconditionally converted into +mouse-down, mouse motion, mouse drag, and mouse button events.") @@ -1418,36 +1427,27 @@ is not read-only." (new-point (posn-point posn)) (old-posn (nth 4 touch-screen-current-tool)) (old-window (posn-window posn)) - (old-point (posn-point posn))) + (old-point (posn-point posn)) + (new-relative-xy (touch-screen-relative-xy + posn new-window)) + (old-relative-xy (touch-screen-relative-xy + old-posn new-window))) (throw 'input-event - ;; If the position of the touch point hasn't - ;; changed, or it doesn't start or end on a - ;; window... - (if (and (not old-point) (not new-point)) - ;; Should old-point and new-point both equal - ;; nil, compare the posn areas and nominal - ;; column position. If either are - ;; different, generate a drag event. - (let ((new-col-row (posn-col-row posn)) - (new-area (posn-area posn)) - (old-col-row (posn-col-row old-posn)) - (old-area (posn-area old-posn))) - (if (and (equal new-col-row old-col-row) - (eq new-area old-area)) - ;; ... generate a mouse-1 event... - (list 'mouse-1 posn) - ;; ... otherwise, generate a - ;; drag-mouse-1 event. - (list 'drag-mouse-1 old-posn posn))) - (if (and (eq new-window old-window) - (eq new-point old-point) - (windowp new-window) - (windowp old-window)) - ;; ... generate a mouse-1 event... - (list 'mouse-1 posn) - ;; ... otherwise, generate a drag-mouse-1 - ;; event. - (list 'drag-mouse-1 old-posn posn))))))) + ;; If the position of the touch point has + ;; changed, or it has moved significantly, as + ;; measured by reference to double-click-fuzz... + (if (or (let ((xdiff (- (car new-relative-xy) + (car old-relative-xy))) + (ydiff (- (cdr new-relative-xy) + (cdr old-relative-xy)))) + (and (>= (abs xdiff) double-click-fuzz) + (>= (abs ydiff) double-click-fuzz))) + (not (eq old-window new-window)) + (not (eq old-point new-point))) + ;; ... generate a drag-mouse-1 event... + (list 'drag-mouse-1 old-posn posn) + ;; ... otherwise, generate a mouse-1 event. + (list 'mouse-1 posn)))))) ((eq what 'mouse-1-menu) ;; Generate a `down-mouse-1' event at the position the tap ;; took place, unless the touch sequence was canceled. @@ -1633,29 +1633,35 @@ functions undertaking event management themselves to call ;; Generate the `restart-drag' event. (throw 'input-event (list 'touchscreen-restart-drag position)))) - ;; Determine if there is a command bound to `down-mouse-1' - ;; at the position of the tap and that command is not a - ;; command whose functionality is replaced by the - ;; long-press mechanism. If so, set the fourth element of - ;; `touch-screen-current-tool' to `mouse-drag' and - ;; generate an emulated `mouse-1' event. + ;; Determine whether there is a command bound to + ;; `down-mouse-1' at the position of the tap and that + ;; command is not a command whose functionality is replaced + ;; by the long-press mechanism. If so, set the fourth + ;; element of `touch-screen-current-tool' to `mouse-drag' + ;; and generate an emulated `mouse-1' event. Likewise if + ;; touch event translation is being invoked by a caller of + ;; `read-key' that expects unprocessed mouse input, ;; - ;; If the command in question is a keymap, set that - ;; element to `mouse-1-menu' instead of `mouse-drag', and - ;; don't generate a `down-mouse-1' event immediately. - ;; Instead, wait for the touch point to be released. + ;; If the command in question is a keymap, set that element + ;; to `mouse-1-menu' instead of `mouse-drag', and don't + ;; generate a `down-mouse-1' event immediately, but wait for + ;; the touch point to be released, so that the menu bar may + ;; not be displayed before the user has released the touch + ;; point and the window system is ready to display a menu. (if (and tool-list - (and (setq binding - (key-binding (if prefix - (vector prefix - 'down-mouse-1) - [down-mouse-1]) - t nil position)) - (not (and (symbolp binding) - (get binding 'ignored-mouse-command))))) - (if (or (keymapp binding) - (and (symbolp binding) - (get binding 'mouse-1-menu-command))) + (or (and (setq binding + (key-binding (if prefix + (vector prefix + 'down-mouse-1) + [down-mouse-1]) + t nil position)) + (not (and (symbolp binding) + (get binding 'ignored-mouse-command)))) + touch-screen-simple-mouse-conversion)) + (if (and (not touch-screen-simple-mouse-conversion) + (or (keymapp binding) + (and (symbolp binding) + (get binding 'mouse-1-menu-command)))) ;; binding is a keymap, or a command that does ;; almost the same thing. If a `mouse-1' event is ;; generated after the keyboard command loop diff --git a/lisp/version.el b/lisp/version.el index a84f7f161f0..db2afd55694 100644 --- a/lisp/version.el +++ b/lisp/version.el @@ -28,26 +28,31 @@ +;; If either of the files examined by the following two functions does +;; not exist, Emacs was configured `--disable-build-details'. + (defun android-read-build-system () "Obtain the host name of the system on which Emacs was built. Use the data stored in the special file `/assets/build_info'. Value is the string ``Unknown'' upon failure, else the hostname of the build system." - (with-temp-buffer - (insert-file-contents "/assets/build_info") - (let ((string (buffer-substring 1 (line-end-position)))) - (and (not (equal string "Unknown")) string)))) + (when (file-exists-p "/assets/build_info") + (with-temp-buffer + (insert-file-contents "/assets/build_info") + (let ((string (buffer-substring 1 (line-end-position)))) + (and (not (equal string "Unknown")) string))))) (defun android-read-build-time () "Obtain the time at which Emacs was built. Use the data stored in the special file `/assets/build_info'. Value is nil upon failure, else the time in the same format as returned by `current-time'." - (with-temp-buffer - (insert-file-contents "/assets/build_info") - (end-of-line) - (let ((number (read (current-buffer)))) - (time-convert number 'list)))) + (when (file-exists-p "/assets/build_info") + (with-temp-buffer + (insert-file-contents "/assets/build_info") + (end-of-line) + (let ((number (read (current-buffer)))) + (time-convert number 'list))))) diff --git a/lisp/whitespace.el b/lisp/whitespace.el index bc23a8794eb..28d131b054c 100644 --- a/lisp/whitespace.el +++ b/lisp/whitespace.el @@ -1465,6 +1465,11 @@ The problems cleaned up are: If `whitespace-style' includes the value `space-after-tab::space', replace TABs by SPACEs. +5. missing newline at end of file. + If `whitespace-style' includes the value `missing-newline-at-eof', + and the cleanup region includes the end of file, add a final newline + if it is not there already. + See `whitespace-style', `indent-tabs-mode' and `tab-width' for documentation." (interactive "@r") @@ -1545,7 +1550,16 @@ documentation." ((memq 'space-before-tab::space whitespace-style) (whitespace-replace-action 'untabify rstart rend - whitespace-space-before-tab-regexp 2)))) + whitespace-space-before-tab-regexp 2))) + ;; PROBLEM 5: missing newline at end of file + (and (memq 'missing-newline-at-eof whitespace-style) + (> (point-max) (point-min)) + (= (point-max) (without-restriction (point-max))) + (/= (char-before (point-max)) ?\n) + (not (and (eq selective-display t) + (= (char-before (point-max)) ?\r))) + (goto-char (point-max)) + (ignore-errors (insert "\n")))) (set-marker rend nil)))) ; point marker to nowhere diff --git a/m4/canonicalize.m4 b/m4/canonicalize.m4 index b63391a6ad7..ec7aac47089 100644 --- a/m4/canonicalize.m4 +++ b/m4/canonicalize.m4 @@ -1,5 +1,5 @@ # canonicalize.m4 -# serial 39 +# serial 40 dnl Copyright (C) 2003-2007, 2009-2024 Free Software Foundation, Inc. @@ -113,7 +113,7 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS], result |= 2; free (name); } - /* This test fails on Cygwin 2.9. */ + /* This test fails on macOS 14, Cygwin 2.9. */ #if HAVE_LSTAT { char *name = realpath ("conftest.l/../conftest.a", NULL); @@ -122,7 +122,7 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS], free (name); } #endif - /* This test fails on Mac OS X 10.13, OpenBSD 6.0. */ + /* This test fails on macOS 14, OpenBSD 6.0. */ { char *name = realpath ("conftest.a/", NULL); if (name != NULL) @@ -163,6 +163,8 @@ AC_DEFUN([gl_FUNC_REALPATH_WORKS], *-gnu* | gnu*) gl_cv_func_realpath_works="guessing yes" ;; # Guess 'nearly' on musl systems. *-musl*) gl_cv_func_realpath_works="guessing nearly" ;; + # Guess no on macOS. + darwin*) gl_cv_func_realpath_works="guessing no" ;; # Guess no on Cygwin. cygwin*) gl_cv_func_realpath_works="guessing no" ;; # Guess no on native Windows. diff --git a/m4/gnulib-comp.m4 b/m4/gnulib-comp.m4 index 9af4b3a9fc8..6c49edac932 100644 --- a/m4/gnulib-comp.m4 +++ b/m4/gnulib-comp.m4 @@ -1646,7 +1646,6 @@ AC_DEFUN([gl_FILE_LIST], [ m4/vararrays.m4 m4/warn-on-use.m4 m4/warnings.m4 - m4/wchar_t.m4 m4/wint_t.m4 m4/xattr.m4 m4/zzgnulib.m4 diff --git a/m4/largefile.m4 b/m4/largefile.m4 index 2f824089b0a..28813483594 100644 --- a/m4/largefile.m4 +++ b/m4/largefile.m4 @@ -1,5 +1,5 @@ # largefile.m4 -# serial 1 +# serial 2 dnl Copyright 1992-1996, 1998-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -88,7 +88,7 @@ m4_define([_AC_SYS_YEAR2038_OPTIONS], m4_normalize( # If you change this macro you may also need to change # _AC_SYS_YEAR2038_OPTIONS. AC_DEFUN([_AC_SYS_YEAR2038_PROBE], -[AC_CACHE_CHECK([for $CPPFLAGS option for timestamps after 2038], +[AC_CACHE_CHECK([for $CC option to support timestamps after 2038], [ac_cv_sys_year2038_opts], [ac_save_CPPFLAGS="$CPPFLAGS" ac_opt_found=no @@ -234,7 +234,7 @@ m4_define([_AC_SYS_LARGEFILE_OPTIONS], m4_normalize( # If you change this macro you may also need to change # _AC_SYS_LARGEFILE_OPTIONS. AC_DEFUN([_AC_SYS_LARGEFILE_PROBE], -[AC_CACHE_CHECK([for $CPPFLAGS option for large files], +[AC_CACHE_CHECK([for $CC option to support large files], [ac_cv_sys_largefile_opts], [ac_save_CPPFLAGS=$CPPFLAGS ac_opt_found=no diff --git a/m4/ndk-build.m4 b/m4/ndk-build.m4 index f86d4e4fc1e..a561c7c849d 100644 --- a/m4/ndk-build.m4 +++ b/m4/ndk-build.m4 @@ -143,22 +143,35 @@ ndk_resolve_import_module () { ndk_module=[$]1 AC_MSG_CHECKING([for imported $ndk_module]) + AC_CACHE_VAL([AS_TR_SH([ndk_cv_commands_$ndk_module])], + [for ndk_android_mk in $ndk_module_files; do + # Read this Android.mk file. Set NDK_ROOT to /tmp: the Android in + # tree build system sets it to a meaningful value, but build files + # just use it to test whether or not the NDK is being used. + ndk_commands=`ndk_run_test` + eval "$ndk_commands" + + if test -n "$module_name"; then + # Guarantee that evaluation of the cached value will also set + # `ndk_android_mk'. + ndk_commands="$ndk_commands ndk_android_mk=$ndk_android_mk" + break; + fi + done + AS_IF([test -z "$module_name"], + [AS_VAR_SET([AS_TR_SH([ndk_cv_commands_$ndk_module])], + [""])], + [AS_VAR_SET([AS_TR_SH([ndk_cv_commands_$ndk_module])], + [$ndk_commands])])]) + + # Copy the computed value into ndk_commands. + AS_VAR_COPY([ndk_commands], [AS_TR_SH([ndk_cv_commands_$ndk_module])]) + eval "$ndk_commands" - for ndk_android_mk in $ndk_module_files; do - # Read this Android.mk file. Set NDK_ROOT to /tmp: the Android in - # tree build system sets it to a meaningful value, but build files - # just use it to test whether or not the NDK is being used. - ndk_commands=`ndk_run_test` - eval "$ndk_commands" - - if test -n "$module_name"; then - break; - fi - done - - AS_IF([test -z "$module_name"], + # Print the outcome of the test. + AS_IF([test -n "$module_name"], [AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no]) - AC_MSG_ERROR([The module currently being built depends on [$]1, but \ + AC_MSG_ERROR([The module currently being built has imported [$]1, but \ that could not be found in the list of directories specified in \ `--with-ndk-path'.])]) @@ -175,8 +188,6 @@ but none were found.])]) [AC_MSG_ERROR([The module [$]1 requires the C++ standard library, but a working C++ compiler was not found.])]) - AC_MSG_RESULT([yes]) - # Make sure the module is prepended. ndk_MODULES="$ndk_MODULES $module_target" ndk_MAKEFILES="$ndk_android_mk $ndk_MAKEFILES" @@ -552,19 +563,28 @@ AC_DEFUN([ndk_SEARCH_MODULE], module_name= ndk_module=$1 ndk_replace_pkg_config_package -AC_MSG_CHECKING([for Android.mk that builds $ndk_module]) - -for ndk_android_mk in $ndk_module_files; do - # Read this Android.mk file. Set NDK_ROOT to /tmp: the Android in - # tree build system sets it to a meaning value, but build files just - # use it to test whether or not the NDK is being used. - ndk_commands=`ndk_run_test` - - eval "$ndk_commands" - if test -n "$module_name"; then - break; - fi -done +AC_MSG_CHECKING([for Android.mk providing $ndk_module]) +AC_CACHE_VAL([AS_TR_SH([ndk_cv_commands_$ndk_module])], + [for ndk_android_mk in $ndk_module_files; do + # Read this Android.mk file. Set NDK_ROOT to /tmp: the Android in + # tree build system sets it to a meaningful value, but build files + # just use it to test whether or not the NDK is being used. + ndk_commands=`ndk_run_test` + eval "$ndk_commands" + + if test -n "$module_name"; then + # Guarantee that evaluation of the cached value will also set + # `ndk_android_mk'. + ndk_commands="$ndk_commands ndk_android_mk=$ndk_android_mk" + break; + fi + done + AS_IF([test -n "$module_name"], + [AS_VAR_SET([AS_TR_SH([ndk_cv_commands_$ndk_module])], + [$ndk_commands])], + [AS_VAR_SET([AS_TR_SH([ndk_cv_commands_$ndk_module])], [])])]) +AS_VAR_COPY([ndk_commands], [AS_TR_SH([ndk_cv_commands_$ndk_module])]) +eval "$ndk_commands" if test -z "$module_name"; then AC_MSG_RESULT([no]) diff --git a/m4/nstrftime.m4 b/m4/nstrftime.m4 index f73bca40ec1..534507d300b 100644 --- a/m4/nstrftime.m4 +++ b/m4/nstrftime.m4 @@ -1,5 +1,5 @@ # nstrftime.m4 -# serial 38 +# serial 40 dnl Copyright (C) 1996-1997, 1999-2007, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -11,8 +11,6 @@ AC_DEFUN([gl_FUNC_GNU_STRFTIME], [ AC_REQUIRE([AC_C_RESTRICT]) - # This defines (or not) HAVE_TZNAME and HAVE_STRUCT_TM_TM_ZONE. - AC_REQUIRE([AC_STRUCT_TIMEZONE]) - AC_REQUIRE([gl_TM_GMTOFF]) + AC_CHECK_FUNCS_ONCE([strftime_z]) ]) diff --git a/m4/printf-posix-rpl.m4 b/m4/printf-posix-rpl.m4 deleted file mode 100644 index 0f741192499..00000000000 --- a/m4/printf-posix-rpl.m4 +++ /dev/null @@ -1,26 +0,0 @@ -# printf-posix-rpl.m4 serial 4 -dnl Copyright (C) 2007-2024 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_PRINTF_POSIX], -[ - AC_REQUIRE([gl_FUNC_VFPRINTF_POSIX]) - if test $gl_cv_func_vfprintf_posix = no; then - gl_REPLACE_PRINTF - fi -]) - -AC_DEFUN([gl_REPLACE_PRINTF], -[ - AC_REQUIRE([gl_STDIO_H_DEFAULTS]) - AC_REQUIRE([gl_ASM_SYMBOL_PREFIX]) - AC_LIBOBJ([printf]) - REPLACE_PRINTF=1 - AC_DEFINE([REPLACE_PRINTF_POSIX], [1], - [Define if printf is overridden by a POSIX compliant gnulib implementation.]) - gl_PREREQ_PRINTF -]) - -AC_DEFUN([gl_PREREQ_PRINTF], [:]) diff --git a/m4/readlinkat.m4 b/m4/readlinkat.m4 index 1f091e8b636..4c4e3588e0a 100644 --- a/m4/readlinkat.m4 +++ b/m4/readlinkat.m4 @@ -1,5 +1,5 @@ # readlinkat.m4 -# serial 9 +# serial 10 dnl Copyright (C) 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -34,7 +34,7 @@ AC_DEFUN([gl_FUNC_READLINKAT], [gl_cv_decl_readlinkat_works=no]) ]) # Assume readlinkat has the same bugs as readlink, - # as is the case on OS X 10.10 with trailing slashes. + # as is the case on macOS 14 with trailing slashes. case $gl_cv_decl_readlinkat_works,$gl_cv_func_readlink_trailing_slash,$gl_cv_func_readlink_truncate in *yes,*yes,*yes) ;; diff --git a/m4/stddef_h.m4 b/m4/stddef_h.m4 index 998fe12fa83..c7f75b37fa0 100644 --- a/m4/stddef_h.m4 +++ b/m4/stddef_h.m4 @@ -1,5 +1,5 @@ # stddef_h.m4 -# serial 16 +# serial 17 dnl Copyright (C) 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -10,7 +10,6 @@ dnl A placeholder for <stddef.h>, for platforms that have issues. AC_DEFUN_ONCE([gl_STDDEF_H], [ AC_REQUIRE([gl_STDDEF_H_DEFAULTS]) - AC_REQUIRE([gt_TYPE_WCHAR_T]) dnl Persuade OpenBSD <stddef.h> to declare max_align_t. AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) @@ -52,11 +51,6 @@ AC_DEFUN_ONCE([gl_STDDEF_H], GL_GENERATE_STDDEF_H=true fi - if test $gt_cv_c_wchar_t = no; then - HAVE_WCHAR_T=0 - GL_GENERATE_STDDEF_H=true - fi - AC_CACHE_CHECK([whether NULL can be used in arbitrary expressions], [gl_cv_decl_null_works], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <stddef.h> @@ -148,5 +142,4 @@ AC_DEFUN([gl_STDDEF_H_DEFAULTS], STDDEF_NOT_IDEMPOTENT=0; AC_SUBST([STDDEF_NOT_IDEMPOTENT]) REPLACE_NULL=0; AC_SUBST([REPLACE_NULL]) HAVE_MAX_ALIGN_T=1; AC_SUBST([HAVE_MAX_ALIGN_T]) - HAVE_WCHAR_T=1; AC_SUBST([HAVE_WCHAR_T]) ]) diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4 index 8eb5816ad7e..10e1fbb8aa9 100644 --- a/m4/stdio_h.m4 +++ b/m4/stdio_h.m4 @@ -1,5 +1,5 @@ # stdio_h.m4 -# serial 63 +# serial 69 dnl Copyright (C) 2007-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -159,6 +159,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_GETLINE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_PRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_PRINTF_POSIX]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_OBSTACK_ZPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PCLOSE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_PERROR]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_POPEN]) @@ -177,6 +178,7 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STDIO_H_SIGPIPE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TMPFILE]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VASPRINTF]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VAZSPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VFSCANF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSCANF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VDPRINTF]) @@ -186,6 +188,10 @@ AC_DEFUN([gl_STDIO_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VPRINTF_POSIX]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSNPRINTF]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VSPRINTF_POSIX]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VZSNPRINTF]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_VZSPRINTF]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ZSNPRINTF]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_ZSPRINTF]) dnl Support Microsoft deprecated alias function names by default. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_FCLOSEALL], [1]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_FDOPEN], [1]) diff --git a/m4/time_h.m4 b/m4/time_h.m4 index d2f3c9701cb..4ca7305792c 100644 --- a/m4/time_h.m4 +++ b/m4/time_h.m4 @@ -1,5 +1,5 @@ # time_h.m4 -# serial 25 +# serial 26 dnl Copyright (C) 2000-2001, 2003-2007, 2009-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -145,6 +145,7 @@ AC_DEFUN([gl_TIME_H_REQUIRE_DEFAULTS], gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIMESPEC_GETRES]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_R]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TIME_RZ]) + gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZNAME]) gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_TZSET]) dnl Support Microsoft deprecated alias function names by default. gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MDA_TZSET], [1]) diff --git a/m4/time_rz.m4 b/m4/time_rz.m4 index 8f45f2b1d3d..9613597aca0 100644 --- a/m4/time_rz.m4 +++ b/m4/time_rz.m4 @@ -1,5 +1,5 @@ # time_rz.m4 -# serial 1 +# serial 2 dnl Copyright (C) 2015-2024 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -13,7 +13,6 @@ AC_DEFUN([gl_TIME_RZ], [ AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS]) AC_REQUIRE([gl_TIME_H_DEFAULTS]) - AC_REQUIRE([AC_STRUCT_TIMEZONE]) # On Mac OS X 10.6, localtime loops forever with some time_t values. # See Bug#27706, Bug#27736, and diff --git a/m4/tm_gmtoff.m4 b/m4/tm_gmtoff.m4 index 0c7dcb2a09a..3d97edb7a7f 100644 --- a/m4/tm_gmtoff.m4 +++ b/m4/tm_gmtoff.m4 @@ -1,15 +1,29 @@ # tm_gmtoff.m4 -# serial 3 +# serial 5 dnl Copyright (C) 2002, 2009-2024 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. +dnl Check for tm_gmtoff and tm_zone in struct tm, and #define +dnl HAVE_STRUCT_TM_TM_GMTOFF and HAVE_STRUCT_TM_TM_ZONE accordingly. +dnl Most code that needs one needs the other, so there seemed little +dnl point to having two macros to check them individually. +dnl Although all platforms that we know of have either both members or +dnl neither member, check for the two members separately just in case. +dnl +dnl These days this macro is more useful than AC_STRUCT_TIMEZONE, which also +dnl checks for the obsolescent tzname and does not check for tm_gmtoff. AC_DEFUN([gl_TM_GMTOFF], [ - AC_CHECK_MEMBER([struct tm.tm_gmtoff], - [AC_DEFINE([HAVE_TM_GMTOFF], [1], - [Define if struct tm has the tm_gmtoff member.])], - , - [#include <time.h>]) + AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [], + [[#include <time.h> + ]]) + + dnl Backward compatibility with 2024-and-earlier versions of this macro. + AS_IF([test "$ac_cv_member_struct_tm_tm_gmtoff" = yes], + [AC_DEFINE([HAVE_TM_GMTOFF], [1], + [Define if struct tm has the tm_gmtoff member. + This macro is obsolete. + New code should use HAVE_STRUCT_TM_TM_GMTOFF.])]) ]) diff --git a/m4/wchar_t.m4 b/m4/wchar_t.m4 deleted file mode 100644 index 968832cb296..00000000000 --- a/m4/wchar_t.m4 +++ /dev/null @@ -1,25 +0,0 @@ -# wchar_t.m4 -# serial 4 (gettext-0.18.2) -dnl Copyright (C) 2002-2003, 2008-2024 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. - -dnl From Bruno Haible. -dnl Test whether <stddef.h> has the 'wchar_t' type. -dnl Prerequisite: AC_PROG_CC - -AC_DEFUN([gt_TYPE_WCHAR_T], -[ - AC_CACHE_CHECK([for wchar_t], [gt_cv_c_wchar_t], - [AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include <stddef.h> - wchar_t foo = (wchar_t)'\0';]], - [[]])], - [gt_cv_c_wchar_t=yes], - [gt_cv_c_wchar_t=no])]) - if test $gt_cv_c_wchar_t = yes; then - AC_DEFINE([HAVE_WCHAR_T], [1], [Define if you have the 'wchar_t' type.]) - fi -]) diff --git a/msdos/sed2v2.inp b/msdos/sed2v2.inp index 3c719e3f9ac..1285afeddf1 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 "30.0.60"/ +/^#undef PACKAGE_VERSION/s/^.*$/#define PACKAGE_VERSION "31.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/msdos/sedlibmk.inp b/msdos/sedlibmk.inp index 5680126ad7a..624983798c4 100644 --- a/msdos/sedlibmk.inp +++ b/msdos/sedlibmk.inp @@ -269,7 +269,6 @@ s/@PACKAGE@/emacs/ /^HAVE_UNSIGNED_LONG_LONG_INT *=/s/@HAVE_UNSIGNED_LONG_LONG_INT@/1/ /^HAVE_USLEEP *=/s/@HAVE_USLEEP@/1/ /^HAVE_WCHAR_H *=/s/@HAVE_WCHAR_H@/1/ -/^HAVE_WCHAR_T *=/s/@HAVE_WCHAR_T@/1/ /^HAVE_LIBGMP *=/s/@HAVE_LIBGMP@/0/ /^HAVE__BOOL *=/s/@HAVE__BOOL@/1/ /^HAVE__EXIT *=/s/@HAVE__EXIT@/1/ diff --git a/nt/README.W32 b/nt/README.W32 index 33e252f7e01..5f33898c215 100644 --- a/nt/README.W32 +++ b/nt/README.W32 @@ -1,7 +1,7 @@ Copyright (C) 2001-2024 Free Software Foundation, Inc. See the end of the file for license conditions. - Emacs version 30.0.60 for MS-Windows + Emacs version 31.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/emacs-module.h.in b/src/emacs-module.h.in index 690254bd28c..21e4ca7cfa1 100644 --- a/src/emacs-module.h.in +++ b/src/emacs-module.h.in @@ -198,6 +198,23 @@ struct emacs_env_30 @module_env_snippet_30@ }; +struct emacs_env_31 +{ +@module_env_snippet_25@ + +@module_env_snippet_26@ + +@module_env_snippet_27@ + +@module_env_snippet_28@ + +@module_env_snippet_29@ + +@module_env_snippet_30@ + +@module_env_snippet_31@ +}; + /* Every module should define a function as follows. */ extern int emacs_module_init (struct emacs_runtime *runtime) EMACS_NOEXCEPT diff --git a/src/emacs.c b/src/emacs.c index 7b315310873..c85beede992 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -23,6 +23,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <errno.h> #include <fcntl.h> +#include <locale.h> #include <stdlib.h> #include <sys/file.h> @@ -132,10 +133,6 @@ extern char etext; # endif #endif -#ifdef HAVE_SETLOCALE -#include <locale.h> -#endif - #if HAVE_WCHAR_H # include <wchar.h> #endif @@ -402,14 +399,6 @@ section of the Emacs manual or the file BUGS.\n" /* True if handling a fatal error already. */ bool fatal_error_in_progress; -#if !HAVE_SETLOCALE -static char * -setlocale (int cat, char const *locale) -{ - return 0; -} -#endif - /* True if the current system locale uses UTF-8 encoding. */ static bool using_utf8 (void) @@ -3277,7 +3266,6 @@ You must run Emacs in batch mode in order to dump it. */) #endif -#if HAVE_SETLOCALE /* Recover from setlocale (LC_ALL, ""). */ void fixup_locale (void) @@ -3297,7 +3285,7 @@ synchronize_locale (int category, Lisp_Object *plocale, Lisp_Object desired_loca *plocale = desired_locale; char const *locale_string = STRINGP (desired_locale) ? SSDATA (desired_locale) : ""; -# ifdef WINDOWSNT +#ifdef WINDOWSNT /* Changing categories like LC_TIME usually requires specifying an encoding suitable for the new locale, but MS-Windows's 'setlocale' will only switch the encoding when LC_ALL is @@ -3306,9 +3294,9 @@ synchronize_locale (int category, Lisp_Object *plocale, Lisp_Object desired_loca numbers is unaffected. */ setlocale (LC_ALL, locale_string); fixup_locale (); -# else /* !WINDOWSNT */ +#else setlocale (category, locale_string); -# endif /* !WINDOWSNT */ +#endif } } @@ -3322,21 +3310,20 @@ synchronize_system_time_locale (void) Vsystem_time_locale); } -# ifdef LC_MESSAGES +#ifdef LC_MESSAGES static Lisp_Object Vprevious_system_messages_locale; -# endif +#endif /* Set system messages locale to match Vsystem_messages_locale, if possible. */ void synchronize_system_messages_locale (void) { -# ifdef LC_MESSAGES +#ifdef LC_MESSAGES synchronize_locale (LC_MESSAGES, &Vprevious_system_messages_locale, Vsystem_messages_locale); -# endif +#endif } -#endif /* HAVE_SETLOCALE */ /* Return a diagnostic string for ERROR_NUMBER, in the wording and encoding appropriate for the current locale. */ diff --git a/src/fns.c b/src/fns.c index cb3e25811ea..6ccdfbcd070 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3012,6 +3012,25 @@ bool_vector_cmp (Lisp_Object a, Lisp_Object b) return (d & aw) ? 1 : -1; } +/* Return -1 if a<b, 1 if a>b, 0 if a=b or if b is NaN (a must be a fixnum). */ +static inline int +fixnum_float_cmp (EMACS_INT a, double b) +{ + double fa = (double)a; + if (fa == b) + { + /* This doesn't mean that a=b because the conversion may have rounded. + However, b must be an integer that fits in an EMACS_INT, + because |b| ≤ 2|a| and EMACS_INT has at least one bit more than + needed to represent any fixnum. + Thus we can compare in the integer domain instead. */ + EMACS_INT ib = b; /* lossless conversion */ + return a < ib ? -1 : a > ib; + } + else + return fa < b ? -1 : fa > b; /* return 0 if b is NaN */ +} + /* Return -1, 0 or 1 to indicate whether a<b, a=b or a>b in the sense of value<. In particular 0 does not mean equality in the sense of Fequal, only that the arguments cannot be ordered yet they can be compared (same @@ -3035,7 +3054,7 @@ value_cmp (Lisp_Object a, Lisp_Object b, int maxdepth) if (FIXNUMP (b)) return ia < XFIXNUM (b) ? -1 : 1; /* we know that a != b */ if (FLOATP (b)) - return ia < XFLOAT_DATA (b) ? -1 : ia > XFLOAT_DATA (b); + return fixnum_float_cmp (ia, XFLOAT_DATA (b)); if (BIGNUMP (b)) return -mpz_sgn (*xbignum_val (b)); } @@ -3176,7 +3195,7 @@ value_cmp (Lisp_Object a, Lisp_Object b, int maxdepth) if (FLOATP (b)) return fa < XFLOAT_DATA (b) ? -1 : fa > XFLOAT_DATA (b); if (FIXNUMP (b)) - return fa < XFIXNUM (b) ? -1 : fa > XFIXNUM (b); + return -fixnum_float_cmp (XFIXNUM (b), fa); if (BIGNUMP (b)) { if (isnan (fa)) diff --git a/src/lisp.h b/src/lisp.h index 59d8e497f13..68b77a88aa7 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -5190,15 +5190,9 @@ extern AVOID terminate_due_to_signal (int, int); #ifdef WINDOWSNT extern Lisp_Object Vlibrary_cache; #endif -#if HAVE_SETLOCALE void fixup_locale (void); void synchronize_system_messages_locale (void); void synchronize_system_time_locale (void); -#else -INLINE void fixup_locale (void) {} -INLINE void synchronize_system_messages_locale (void) {} -INLINE void synchronize_system_time_locale (void) {} -#endif extern char *emacs_strerror (int) ATTRIBUTE_RETURNS_NONNULL; extern void shut_down_emacs (int, Lisp_Object); diff --git a/src/lread.c b/src/lread.c index 3feb27eda46..c3b0e8a3ef5 100644 --- a/src/lread.c +++ b/src/lread.c @@ -28,6 +28,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #include <sys/stat.h> #include <sys/file.h> #include <errno.h> +#include <locale.h> #include <math.h> #include <stat-time.h> #include "lisp.h" @@ -55,11 +56,6 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ #endif #include <unistd.h> - -#ifdef HAVE_SETLOCALE -#include <locale.h> -#endif /* HAVE_SETLOCALE */ - #include <fcntl.h> #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \ diff --git a/src/marker.c b/src/marker.c index f016bf9c088..16fa3bcef3e 100644 --- a/src/marker.c +++ b/src/marker.c @@ -202,19 +202,15 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos) if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) CONSIDER (cached_charpos, cached_bytepos); - for (tail = BUF_MARKERS (b); tail; tail = tail->next) - { - CONSIDER (tail->charpos, tail->bytepos); - - /* If we are down to a range of 50 chars, - don't bother checking any other markers; - scan the intervening chars directly now. */ - if (best_above - charpos < distance - || charpos - best_below < distance) - break; - else - distance += BYTECHAR_DISTANCE_INCREMENT; - } + for (tail = BUF_MARKERS (b); + /* If we are down to a range of DISTANCE chars, + don't bother checking any other markers; + scan the intervening chars directly now. */ + tail && !(best_above - charpos < distance + || charpos - best_below < distance); + tail = tail->next, + distance += BYTECHAR_DISTANCE_INCREMENT) + CONSIDER (tail->charpos, tail->bytepos); /* We get here if we did not exactly hit one of the known places. We have one known above and one known below. @@ -354,19 +350,15 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t bytepos) if (b == cached_buffer && BUF_MODIFF (b) == cached_modiff) CONSIDER (cached_bytepos, cached_charpos); - for (tail = BUF_MARKERS (b); tail; tail = tail->next) - { - CONSIDER (tail->bytepos, tail->charpos); - - /* If we are down to a range of 50 chars, - don't bother checking any other markers; - scan the intervening chars directly now. */ - if (best_above - bytepos < distance - || bytepos - best_below < distance) - break; - else - distance += BYTECHAR_DISTANCE_INCREMENT; - } + for (tail = BUF_MARKERS (b); + /* If we are down to a range of DISTANCE bytes, + don't bother checking any other markers; + scan the intervening chars directly now. */ + tail && !(best_above_byte - bytepos < distance + || bytepos - best_below_byte < distance); + tail = tail->next, + distance += BYTECHAR_DISTANCE_INCREMENT) + CONSIDER (tail->bytepos, tail->charpos); /* We get here if we did not exactly hit one of the known places. We have one known above and one known below. diff --git a/src/module-env-30.h b/src/module-env-30.h index e75210c7f8e..e69de29bb2d 100644 --- a/src/module-env-30.h +++ b/src/module-env-30.h @@ -1,3 +0,0 @@ - /* Add module environment functions newly added in Emacs 30 here. - Before Emacs 30 is released, remove this comment and start - module-env-31.h on the master branch. */ diff --git a/src/module-env-31.h b/src/module-env-31.h new file mode 100644 index 00000000000..e9827b18382 --- /dev/null +++ b/src/module-env-31.h @@ -0,0 +1,3 @@ + /* Add module environment functions newly added in Emacs 31 here. + Before Emacs 31 is released, remove this comment and start + module-env-32.h on the master branch. */ diff --git a/src/pdumper.c b/src/pdumper.c index 8946c317bf9..bc5748c8c47 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2125,8 +2125,7 @@ dump_marker (struct dump_context *ctx, const struct Lisp_Marker *marker) } static dump_off -dump_interval_node (struct dump_context *ctx, struct itree_node *node, - dump_off parent_offset) +dump_interval_node (struct dump_context *ctx, struct itree_node *node) { #if CHECK_STRUCTS && !defined (HASH_itree_node_50DE304F13) # error "itree_node changed. See CHECK_STRUCTS comment in config.h." @@ -2153,17 +2152,17 @@ dump_interval_node (struct dump_context *ctx, struct itree_node *node, dump_remember_fixup_ptr_raw (ctx, offset + dump_offsetof (struct itree_node, parent), - dump_interval_node (ctx, node->parent, offset)); + dump_interval_node (ctx, node->parent)); if (node->left) dump_remember_fixup_ptr_raw (ctx, offset + dump_offsetof (struct itree_node, left), - dump_interval_node (ctx, node->left, offset)); + dump_interval_node (ctx, node->left)); if (node->right) dump_remember_fixup_ptr_raw (ctx, offset + dump_offsetof (struct itree_node, right), - dump_interval_node (ctx, node->right, offset)); + dump_interval_node (ctx, node->right)); return offset; } @@ -2180,7 +2179,7 @@ dump_overlay (struct dump_context *ctx, const struct Lisp_Overlay *overlay) dump_remember_fixup_ptr_raw (ctx, offset + dump_offsetof (struct Lisp_Overlay, interval), - dump_interval_node (ctx, overlay->interval, offset)); + dump_interval_node (ctx, overlay->interval)); return offset; } @@ -2209,9 +2208,9 @@ dump_finalizer (struct dump_context *ctx, /* Do _not_ call dump_pseudovector_lisp_fields here: we dump the only Lisp field, finalizer->function, manually, so we can give it a low weight. */ - dump_field_lv (ctx, &out, finalizer, &finalizer->function, WEIGHT_NONE); - dump_field_finalizer_ref (ctx, &out, finalizer, &finalizer->prev); - dump_field_finalizer_ref (ctx, &out, finalizer, &finalizer->next); + dump_field_lv (ctx, out, finalizer, &finalizer->function, WEIGHT_NONE); + dump_field_finalizer_ref (ctx, out, finalizer, &finalizer->prev); + dump_field_finalizer_ref (ctx, out, finalizer, &finalizer->next); return finish_dump_pvec (ctx, &out->header); } diff --git a/src/puresize.h b/src/puresize.h index 2a716872832..d7d8f0b4eec 100644 --- a/src/puresize.h +++ b/src/puresize.h @@ -47,7 +47,7 @@ INLINE_HEADER_BEGIN #endif #ifndef BASE_PURESIZE -#define BASE_PURESIZE (3000000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) +#define BASE_PURESIZE (3100000 + SYSTEM_PURESIZE_EXTRA + SITELOAD_PURESIZE_EXTRA) #endif /* Increase BASE_PURESIZE by a ratio depending on the machine's word size. */ diff --git a/src/sysdep.c b/src/sysdep.c index 07237885cb9..d916a695155 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -4551,18 +4551,10 @@ does the same thing as `current-time'. */) # include <wchar.h> # include <wctype.h> -# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE -# include <locale.h> -# endif -# ifndef LC_COLLATE -# define LC_COLLATE 0 -# endif +# include <locale.h> # ifndef LC_COLLATE_MASK # define LC_COLLATE_MASK 0 # endif -# ifndef LC_CTYPE -# define LC_CTYPE 0 -# endif # ifndef LC_CTYPE_MASK # define LC_CTYPE_MASK 0 # endif @@ -4595,15 +4587,11 @@ freelocale (locale_t loc) static char * emacs_setlocale (int category, char const *locale) { -# ifdef HAVE_SETLOCALE errno = 0; char *loc = setlocale (category, locale); if (loc || errno) return loc; errno = EINVAL; -# else - errno = ENOTSUP; -# endif return 0; } diff --git a/src/xdisp.c b/src/xdisp.c index 7d31813a57e..8c7e8e5cb43 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5549,6 +5549,7 @@ setup_for_ellipsis (struct it *it, int len) static Lisp_Object find_display_property (Lisp_Object disp, Lisp_Object prop) { + Lisp_Object elem; if (NILP (disp)) return Qnil; /* We have a vector of display specs. */ @@ -5556,11 +5557,11 @@ find_display_property (Lisp_Object disp, Lisp_Object prop) { for (ptrdiff_t i = 0; i < ASIZE (disp); i++) { - Lisp_Object elem = AREF (disp, i); + elem = AREF (disp, i); if (CONSP (elem) && CONSP (XCDR (elem)) && EQ (XCAR (elem), prop)) - return XCAR (XCDR (elem)); + goto found; } return Qnil; } @@ -5570,11 +5571,11 @@ find_display_property (Lisp_Object disp, Lisp_Object prop) { while (!NILP (disp)) { - Lisp_Object elem = XCAR (disp); + elem = XCAR (disp); if (CONSP (elem) && CONSP (XCDR (elem)) && EQ (XCAR (elem), prop)) - return XCAR (XCDR (elem)); + goto found; /* Check that we have a proper list before going to the next element. */ @@ -5589,9 +5590,20 @@ find_display_property (Lisp_Object disp, Lisp_Object prop) else if (CONSP (disp) && CONSP (XCDR (disp)) && EQ (XCAR (disp), prop)) - return XCAR (XCDR (disp)); + { + elem = disp; + goto found; + } + + return Qnil; + + found: + /* If the property value is a list of one element, just return the + CAR. */ + if (NILP (XCDR (XCDR (elem)))) + return XCAR (XCDR (elem)); else - return Qnil; + return XCDR (elem); } static Lisp_Object @@ -28053,18 +28065,7 @@ store_mode_line_string (const char *string, Lisp_Object lisp_string, if (string != NULL) { -#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY \ - && __ANDROID_API__ < 22 - /* Circumvent a bug in memchr preventing strnlen from returning - valid values when a large limit is specified. - - https://issuetracker.google.com/issues/37020957 */ - if (precision <= 0 || ((uintptr_t) string - > (UINTPTR_MAX - precision))) - len = strlen (string); - else -#endif /* HAVE_ANDROID && !ANDROID_STUBIFY && __ANDROID_API__ < 22 */ - len = strnlen (string, precision <= 0 ? SIZE_MAX : precision); + len = strnlen (string, precision <= 0 ? SIZE_MAX : precision); lisp_string = make_string (string, len); if (NILP (props)) props = mode_line_string_face_prop; diff --git a/test/infra/Dockerfile.emba b/test/infra/Dockerfile.emba index de32906212b..088df86ad70 100644 --- a/test/infra/Dockerfile.emba +++ b/test/infra/Dockerfile.emba @@ -145,7 +145,6 @@ RUN src/emacs -Q --batch \ treesit-language-source-alist \ (quote ((bash "https://github.com/tree-sitter/tree-sitter-bash") \ (c "https://github.com/tree-sitter/tree-sitter-c") \ - (c-sharp "https://github.com/tree-sitter/tree-sitter-c-sharp") \ (cpp "https://github.com/tree-sitter/tree-sitter-cpp") \ (css "https://github.com/tree-sitter/tree-sitter-css") \ (elixir "https://github.com/elixir-lang/tree-sitter-elixir") \ diff --git a/test/infra/Makefile.in b/test/infra/Makefile.in index 0144ad1cbd9..9c32fd6a192 100644 --- a/test/infra/Makefile.in +++ b/test/infra/Makefile.in @@ -117,25 +117,22 @@ endef $(foreach subdir, $(SUBDIRS), $(eval $(call subdir_template,$(subdir)))) -# csharp-mode-tests.el, js-tests.el and python-tests.el don't follow -# test file name convention. +# js-tests.el and python-tests.el don't follow test file name convention. TREE-SITTER-FILES ?= $(shell cd .. ; \ find lisp src \( -name "*-ts-mode-tests.el" -o -name "treesit-tests.el" \ - -o -name "csharp-mode-tests.el" -o -name "js-tests.el" \ - -o -name "python-tests.el" \) | \ + -o -name "js-tests.el" -o -name "python-tests.el" \) | \ sort | sed s/\\.el/.log/) all: generate-test-jobs -.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS) tree-sitter-files +.PHONY: generate-test-jobs $(FILE) $(SUBDIR_TARGETS) tree-sitter-files-template -generate-test-jobs: $(FILE) $(SUBDIR_TARGETS) tree-sitter-files +generate-test-jobs: $(FILE) $(SUBDIR_TARGETS) tree-sitter-files-template -tree-sitter-files: +tree-sitter-files-template: @echo >>$(FILE) - @echo "# csharp-mode-tests.el, js-tests.el and python-tests.el don't follow" >>$(FILE) - @echo "# test file name convention." >>$(FILE) - @echo '.tree-sitter-files:' >>$(FILE) + @echo "# js-tests.el and python-tests.el don't follow test file name convention." >>$(FILE) + @echo '.tree-sitter-files-template:' >>$(FILE) @echo ' variables:' >>$(FILE) @echo ' tree_sitter_files: >-' >>$(FILE) @for name in $(TREE-SITTER-FILES) ; do echo " $${name}" >>$(FILE) ; done diff --git a/test/infra/gitlab-ci.yml b/test/infra/gitlab-ci.yml index e5e48b76ec2..11ff0d1c738 100644 --- a/test/infra/gitlab-ci.yml +++ b/test/infra/gitlab-ci.yml @@ -294,7 +294,7 @@ build-image-tree-sitter: test-tree-sitter: stage: platforms - extends: [.job-template, .test-template, .tree-sitter-template, .tree-sitter-files] + extends: [.job-template, .test-template, .tree-sitter-template, .tree-sitter-files-template] needs: - job: build-image-tree-sitter optional: true diff --git a/test/infra/test-jobs.yml b/test/infra/test-jobs.yml index 13b184b1277..0d9cbb029e5 100644 --- a/test/infra/test-jobs.yml +++ b/test/infra/test-jobs.yml @@ -577,12 +577,10 @@ test-src-inotify: target: emacs-inotify make_params: -C test check-src -# csharp-mode-tests.el, js-tests.el and python-tests.el don't follow -# test file name convention. -.tree-sitter-files: +# js-tests.el and python-tests.el don't follow test file name convention. +.tree-sitter-files-template: variables: tree_sitter_files: >- - lisp/progmodes/csharp-mode-tests.log lisp/progmodes/c-ts-mode-tests.log lisp/progmodes/elixir-ts-mode-tests.log lisp/progmodes/go-ts-mode-tests.log diff --git a/test/lisp/completion-preview-tests.el b/test/lisp/completion-preview-tests.el index 3f64fe02e18..b190ecb7020 100644 --- a/test/lisp/completion-preview-tests.el +++ b/test/lisp/completion-preview-tests.el @@ -291,7 +291,7 @@ instead." (setq-local completion-at-point-functions (list (completion-preview-tests--capf - '("foobar" "foobaz") + '("foobar-1 2" "foobarverylong") :exit-function (lambda (&rest args) (setq exit-fn-called t @@ -299,11 +299,150 @@ instead." (insert "foo") (let ((this-command 'self-insert-command)) (completion-preview--post-command)) - (completion-preview-tests--check-preview "bar" 'completion-preview-common) + (completion-preview-tests--check-preview "bar-1 2" + 'completion-preview-common) (completion-preview-insert) + (should (string= (buffer-string) "foobar-1 2")) + (should-not completion-preview--overlay) + (should exit-fn-called) + (should (equal exit-fn-args '("foobar-1 2" finished)))))) + +(ert-deftest completion-preview-insert-word () + "Test that `completion-preview-insert-word' properly inserts just a word." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobar-1 2" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "bar-1 2" + 'completion-preview-common) + (completion-preview-insert-word) (should (string= (buffer-string) "foobar")) + (completion-preview-tests--check-preview "-1 2" 'completion-preview) + (should-not exit-fn-called) + (should-not exit-fn-args)))) + +(ert-deftest completion-preview-insert-nonsubword () + "Test that `completion-preview-insert-word' with `subword-mode' off." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobarBar" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "barBar" + 'completion-preview-common) + (completion-preview-insert-word) + (should (string= (buffer-string) "foobarBar")) (should-not completion-preview--overlay) (should exit-fn-called) - (should (equal exit-fn-args '("foobar" finished)))))) + (should (equal exit-fn-args '("foobarBar" finished)))))) + +(ert-deftest completion-preview-insert-subword () + "Test that `completion-preview-insert-word' with `subword-mode' on." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (subword-mode) + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobarBar" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "barBar" + 'completion-preview-common) + (completion-preview-insert-word) + (should (string= (buffer-string) "foobar")) + (completion-preview-tests--check-preview "Bar" 'completion-preview) + (should-not exit-fn-called) + (should-not exit-fn-args)))) + +(ert-deftest completion-preview-insert-mid-symbol () + "Test `completion-preview-insert-word' when point is in a mulit-word symbol." + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foo-bar-baz-spam")))) + (insert "foo-bar-baz-") + (goto-char 4) + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "spam" + 'completion-preview-exact + 'completion-preview-exact) + (completion-preview-insert-word 2) + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + ;; Moving two words forward should land at the end of baz, without + ;; inserting anything from the completion candidate. + (completion-preview-tests--check-preview "spam" + 'completion-preview-exact + 'completion-preview-exact) + (should (= (point) 12)) + (completion-preview-insert-word -2) + ;; Moving backward shouldn't change anything, either. + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "spam" + 'completion-preview-exact + 'completion-preview-exact) + (should (= (point) 5)))) + +(ert-deftest completion-preview-insert-sexp () + "Test that `completion-preview-insert-sexp' properly inserts just a sexp." + (let ((exit-fn-called nil) (exit-fn-args nil)) + (with-temp-buffer + (setq-local completion-at-point-functions + (list + (completion-preview-tests--capf + '("foobar-1 2" "foobarverylong") + :exit-function + (lambda (&rest args) + (setq exit-fn-called t + exit-fn-args args))))) + (insert "foo") + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "bar-1 2" + 'completion-preview-common) + (completion-preview-insert-sexp) + (should (string= (buffer-string) "foobar-1")) + (completion-preview-tests--check-preview " 2" 'completion-preview) + (should-not exit-fn-called) + (should-not exit-fn-args)))) + +(ert-deftest completion-preview-insert-inherits-text-properties () + "Test that `completion-preview-insert' inherits text properties." + (with-temp-buffer + (setq-local completion-at-point-functions + (list (completion-preview-tests--capf '("foobar" "foobaz")))) + (insert (propertize "foo" 'prop 'val)) + (let ((this-command 'self-insert-command)) + (completion-preview--post-command)) + (completion-preview-tests--check-preview "bar" 'completion-preview-common) + (completion-preview-insert) + (should (string= (buffer-string) "foobar")) + (should (eq (get-text-property 6 'prop) 'val)))) ;;; completion-preview-tests.el ends here diff --git a/test/lisp/eshell/eshell-tests.el b/test/lisp/eshell/eshell-tests.el index e58b5a14ed9..f16c28cd1ae 100644 --- a/test/lisp/eshell/eshell-tests.el +++ b/test/lisp/eshell/eshell-tests.el @@ -117,6 +117,27 @@ This test uses a pipeline for the command." (forward-line) (should (looking-at "hi\n")))))) +(ert-deftest eshell-test/eshell-command/output-buffer/async-kill () + "Test that the `eshell-command' function kills the old process when told to." + (skip-unless (executable-find "echo")) + (ert-with-temp-directory eshell-directory-name + (let ((orig-processes (process-list)) + (eshell-history-file-name nil) + (eshell-command-async-buffer 'confirm-kill-process)) + (eshell-command "sleep 5 | *echo hi &") + (cl-letf* ((result t) + ;; Say "yes" only once: for the `confirm-kill-process' + ;; prompt. If there are any other prompts (e.g. from + ;; `kill-buffer'), say "no" to make the test fail. + ((symbol-function 'yes-or-no-p) + (lambda (_prompt) (prog1 result (setq result nil))))) + (eshell-command "*echo bye &")) + (eshell-wait-for (lambda () (equal (process-list) orig-processes))) + (with-current-buffer "*Eshell Async Command Output*" + (goto-char (point-min)) + (forward-line) + (should (looking-at "bye\n")))))) + (ert-deftest eshell-test/command-running-p () "Modeline should show no command running" (with-temp-eshell diff --git a/test/lisp/net/rfc2104-tests.el b/test/lisp/net/rfc2104-tests.el index be5da619eaa..40e593ad56b 100644 --- a/test/lisp/net/rfc2104-tests.el +++ b/test/lisp/net/rfc2104-tests.el @@ -23,8 +23,6 @@ (require 'ert) (require 'rfc2104) -(require 'sha1) -(require 'md5) (ert-deftest dbus-test-sha1 () (should diff --git a/test/lisp/net/shr-tests.el b/test/lisp/net/shr-tests.el index 54d85ee95f9..f8559df5272 100644 --- a/test/lisp/net/shr-tests.el +++ b/test/lisp/net/shr-tests.el @@ -158,6 +158,7 @@ settings, then once more for each (OPTION . VALUE) pair.") (shr-width 80) (shr-use-fonts nil) (shr-image-animate nil) + (shr-sliced-image-height nil) (inhibit-message t) (dom (libxml-parse-html-region (point-min) (point-max)))) ;; Render the document. @@ -170,19 +171,15 @@ settings, then once more for each (OPTION . VALUE) pair.") (shr-zoom-image) (shr-test-wait-for (lambda () (= put-image-calls 2)) "Timed out waiting to zoom image") - ;; Check that we got a sliced image. - (let ((slice-count 0)) + ;; Check that we have a single image at original size. + (let (image-zooms) (goto-char (point-min)) (while (< (point) (point-max)) - (when-let ((display (get-text-property (point) 'display))) - ;; If this is nil, we found a non-sliced image, but we - ;; should have replaced that! - (should (assq 'slice display)) - (cl-incf slice-count)) + (when (get-text-property (point) 'display) + (push (get-text-property (point) 'image-zoom) image-zooms)) (goto-char (or (next-single-property-change (point) 'display) (point-max)))) - ;; Make sure we actually saw a slice. - (should (> slice-count 1))))))))) + (should (equal image-zooms '(original)))))))))) (require 'shr) diff --git a/test/lisp/whitespace-tests.el b/test/lisp/whitespace-tests.el index 73c7e742ec5..bd35b3ac9f3 100644 --- a/test/lisp/whitespace-tests.el +++ b/test/lisp/whitespace-tests.el @@ -8,7 +8,6 @@ ;; 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 @@ -94,6 +93,20 @@ buffer's content." (should (equal (whitespace-tests--cleanup-string "a \n\t \n\n") "a \n")))) +(ert-deftest whitespace-cleanup-missing-newline-at-eof () + (let ((whitespace-style '(empty missing-newline-at-eof))) + (should (equal (whitespace-tests--cleanup-string "") + "")) + (should (equal (whitespace-tests--cleanup-string "a") + "a\n")) + (should (equal (whitespace-tests--cleanup-string "a\n\t") + "a\n")) + (should (equal (whitespace-tests--cleanup-string "a\n\t ") + "a\n")) + (should (equal (whitespace-tests--cleanup-string "a\n\t ") + "a\n")) + (should (equal (whitespace-tests--cleanup-string "\n\t") + "")))) ;; We cannot call whitespace-mode because it will do nothing in batch ;; mode. So we call its innards instead. diff --git a/test/manual/indent/perl.perl b/test/manual/indent/perl.perl index b44593da028..de76fffa262 100755 --- a/test/manual/indent/perl.perl +++ b/test/manual/indent/perl.perl @@ -5,6 +5,10 @@ sub add_funds($) { return 0; } +find ({ wanted => sub { + return; + }, follow => 1 }, '/tmp'); + # qw(...) is a quoted list of words, so we can and should indent its content! my @tutu = qw[ tata diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index ca5b10db705..decbdb6ac52 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el @@ -1606,6 +1606,13 @@ (1.5 . 1.6) (-1.3 . -1.2) (-13.0 . 12.0) ;; floats/fixnums (1 . 1.1) (1.9 . 2) (-2.0 . 1) (-2 . 1.0) + ;; fixnums that can't be represented as floats + (72057594037927935 . 72057594037927936.0) + (72057594037927936.0 . 72057594037927937) + (-72057594037927936.0 . -72057594037927935) + (-72057594037927937 . -72057594037927936.0) + (2305843009213693951 . 2305843009213693952.0) + ;; floats/bignums (,big . ,(float (* 2 big))) (,(float big) . ,(* 2 big)) ;; symbols @@ -1665,7 +1672,11 @@ (should (value< x y)) (should-not (value< y x)) (should-not (value< x x)) - (should-not (value< y y)))) + (should-not (value< y y)) + (should (value< (vector x 2) (vector y 1))) + (should-not (value< (vector y 1) (vector x 2))) + (should (value< (vector x 1) (vector x 2))) + (should (value< (vector y 1) (vector y 2))))) (delete-process proc2) (delete-process proc1) @@ -1683,6 +1694,9 @@ ;; numbers (0 . 0.0) (0 . -0.0) (0.0 . -0.0) + (72057594037927936 . 72057594037927936.0) + (1 . 0.0e+NaN) + ;; symbols (a . #:a) @@ -1697,7 +1711,9 @@ (let ((x (car c)) (y (cdr c))) (should-not (value< x y)) - (should-not (value< y x)))))) + (should-not (value< y x)) + (should (value< (cons x 1) (cons y 2))) + (should-not (value< (cons x 2) (cons y 1))))))) (ert-deftest fns-value<-type-mismatch () ;; values of disjoint (incomparable) types |