diff --git a/.gitignore b/.gitignore index 143ee31a7a5..eb51921aa38 100644 --- a/.gitignore +++ b/.gitignore @@ -18,14 +18,15 @@ # along with GNU Emacs. If not, see . -# 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 diff --git a/ChangeLog.3 b/ChangeLog.3 index 1398b9bcf53..80ea900477e 100644 --- a/ChangeLog.3 +++ b/ChangeLog.3 @@ -17355,7 +17355,7 @@ ([EmacsView viewDidResize:]):Don't explicitly release surfaces. ([EmacsView initFrameFromEmacs:]): Move the layer code to after the NSWindow has been created as creating the layer now relies on some of - it's properties. + its properties. ([EmacsView makeBackingLayer]): New function. ([EmacsView lockFocus]): ([EmacsView focusOnDrawingBuffer]): Rename to lockFocus. @@ -128823,7 +128823,7 @@ (setq message-send-mail-function 'message-send-mail-with-sendmail) (setq sendmail-program "msmtp") - the message seding is handled by an external program, so no Unicode + the message sending is handled by an external program, so no Unicode encoding is performed in Emacs. Thus Emacs must not assert that the Unicode encoding was performed. @@ -128870,7 +128870,7 @@ Change default offset of CC Mode syntactic symbol inlambda to 0 - It's previous default was c-lineup-inexpr-block. This change is mainly to + Its previous default was c-lineup-inexpr-block. This change is mainly to prevent excessive indentation of the innards of C++ lambda functions. * lisp/progmodes/cc-vars.el (c-offsets-alist): Amend the offset for inlambda @@ -129602,7 +129602,7 @@ 2019-05-27 Glenn Morris - * test/lisp/autorevert-tests.el: Give on on remote hydra.nixos tests. + * test/lisp/autorevert-tests.el: Give up on remote hydra.nixos tests. (auto-revert--test-enabled-remote): Disable on hydra.nixos. @@ -135286,7 +135286,7 @@ 92ce2dd Improve documentation of window parameters 6dc42c5 Improve commentary in frame.el a8cffcf Fix typo in a doc string - 9e79f19 (emacs-26) ; * src/fontset.c (set-fontset-font): Use uppercas... + 9e79f19 (emacs-26) ; * src/fontset.c (set-fontset-font): Use uppercase... # Conflicts: # lisp/vc/vc.el @@ -155238,7 +155238,7 @@ d6aa55e Avoid segfaults in replace-buffer-contents with large buffers d22b8d1 Adjust for scaling for mode-line popup menus (Bug#31880) 3d2e3dc Change name of `seqp' argument (Bug#26411) - 40e1db8 Change index of ";" to better reflect it's usage (Bug#31623) + 40e1db8 Change index of ";" to better reflect its usage (Bug#31623) d289e7e Fix bug of 'mouse-drag-and-drop-region' to detect edges of re... e292c09 Fix #'fun handling inside `labels' (Bug#31792) @@ -176477,7 +176477,7 @@ 2018-06-20 Noam Postavsky - Change index of ";" to better reflect it's usage (Bug#31623) + Change index of ";" to better reflect its usage (Bug#31623) * doc/lispref/objects.texi (Comments): "; for commenting" fits better with the following text about how a semicolon begins a comment. Also @@ -217678,7 +217678,7 @@ Add seq-random-elt to seq.el * lisp/emacs-lisp/seq.el (seq-random-elt): Add function to return a - random element from it's sequence parameter. + random element from its sequence parameter. * test/lisp/emacs-lisp/seq-tests.el (test-seq-random-elt-take-all test-seq-random-elt-return-nil): Test the new function @@ -223245,7 +223245,7 @@ Make ‘delete-trailing-whitespace’ delete spaces after form feed * lisp/simple.el (delete-trailing-whitespace): Treat form fead as - a non-whitespace character (regradless of whether it’s character syntax + a non-whitespace character (regardless of whether its character syntax is whitespace) and delete any whitespace following it instead of leaving lines with form feeds completely unchanged. I.e. a line like "\f " will now became "\f". diff --git a/ChangeLog.4 b/ChangeLog.4 index 364fa212709..be1eb2f80b4 100644 --- a/ChangeLog.4 +++ b/ChangeLog.4 @@ -309,7 +309,7 @@ 2024-03-31 Michael Albinus - Adapt Tramp versio (don't merge) + Adapt Tramp version (don't merge) * doc/misc/trampver.texi: * lisp/net/trampver.el: Change version to "2.6.3". @@ -8476,8 +8476,8 @@ changes, make hint overlays span one character (instead of being length 0). Give the overlays an "evaporate" property. - Given an inlay hints at position POS, its attached to [POS, POS+1] if - it's kind=1 (usually type hints) and [POS-1, POS] otherwise. For + Given an inlay hints at position POS, it's attached to [POS, POS+1] if + its kind=1 (usually type hints) and [POS-1, POS] otherwise. For kind=1 hints, the 'cursor position of the first such overlay is also tweaked, so that's it's less awkward to edit around it. @@ -9313,7 +9313,7 @@ Not the subject of it, but mentioned in bug#61893. * lisp/progmodes/c-ts-mode.el (c-ts-mode--anchor-prev-sibling): Skip - the sibling if it doesn't start on it's own line. + the sibling if it doesn't start on its own line. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New test. 2023-03-05 Kyle Meyer @@ -24470,7 +24470,7 @@ (treesit-major-mode-setup): Instead of binding font-lock-fontify-region-function, now bind to font-lock-fontify-syntactically-function. And we can let font-lock do - it's thing. + its thing. 2022-10-31 Yuan Fu @@ -28715,7 +28715,7 @@ Fix Tramp completion on MS Windows * lisp/net/tramp.el (tramp-build-remote-file-name-spec-regexp): - Revert previous change, it's too complicate. + Revert previous change, it's too complicated. (tramp-build-completion-file-name-regexp): Use `tramp-prefix-format' instead of `tramp-prefix-regexp'. (Bug#558133) @@ -37079,7 +37079,7 @@ * src/xselect.c (lisp_data_to_selection_data): Assume an empty vector represents INTEGER data, instead of blindly trying to - aref it's first element. + aref its first element. 2022-09-04 Jim Porter @@ -40542,7 +40542,7 @@ * doc/misc/gnus.texi (The problem of spam): Don't explain what spam is; there is no need for that in 2022. Don't explain - limitations of obsolete software TMDA; it's website has stopped + limitations of obsolete software TMDA; its website has stopped working but seems to have been updated last in 2007. (Thwarting Email Spam, Anti-Spam Basics) (Spam Package Configuration Examples): Prefer "spam" to "UCE". @@ -63333,7 +63333,7 @@ Correct indentation of opening brace in xdisp.c, which isn't at start of defun * xdisp.c (calc_pixel_width_or_height): indent the opening brace of a - substatement correctly. It's previous position, in column 0, caused + substatement correctly. Its previous position, in column 0, caused indentation errors in C Mode. 2022-05-17 Po Lu diff --git a/ChangeLog.android b/ChangeLog.android index e86ef7a2a77..1acf157dfbf 100644 --- a/ChangeLog.android +++ b/ChangeLog.android @@ -5406,7 +5406,7 @@ (syms_of_androidselect): Define it. * src/emacs.c (load_pdump): Eschew excessively elaborate dump file - location code on on Android. + location code on Android. * src/pdumper.c (Fdump_emacs_portable): Allow dumping while interactive on Android. 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/admin/codespell/codespell.exclude b/admin/codespell/codespell.exclude index f01302b7931..733e548a598 100644 --- a/admin/codespell/codespell.exclude +++ b/admin/codespell/codespell.exclude @@ -87,7 +87,7 @@ be shown. On positions 3,4, and 7, the @samp{alog} function will be As is my wont, I started hacking on it almost immediately. I first The latter criterion is the "je ne sais quoi" of the artistic aspect of order but are now listed consecutively en bloc. - "mot de passe" "Mot de passe") + "mot de passe" "Mot de passe") Reported by Mor Zahavi . (Bug#51271) * etc/refcards/fr-refcard.tex (section{Formater}): Remove mention Reported by Ture Pålsson. diff --git a/admin/codespell/codespell.ignore b/admin/codespell/codespell.ignore index 02bd6d05838..ebb85e510bb 100644 --- a/admin/codespell/codespell.ignore +++ b/admin/codespell/codespell.ignore @@ -32,6 +32,7 @@ msdos ot parm parms +proced reenable reenabled requestor diff --git a/admin/release-branch.txt b/admin/release-branch.txt index 0c393a9eccb..b59bc12dfb9 100644 --- a/admin/release-branch.txt +++ b/admin/release-branch.txt @@ -42,7 +42,8 @@ Instructions for cutting the Emacs release branch M-x set-version RET XY+1.0.50 RET - This creates a new file etc/NEWS.XY. "git add" it. + This creates a new file etc/NEWS. "git add" it. + (The original NEWS gets renamed into NEWS.XY.) Change the value of 'customize-changed-options-previous-release' in cus-edit.el to reference emacs-XY.1, the next version to be @@ -60,7 +61,7 @@ Instructions for cutting the Emacs release branch module_env_snippet_XY+1="$srcdir/src/module-env-XY+1.h" . adding a new 'struct emacs_env_XY+1' to src/emacs-module.h.in, - with the contents identical to'struct emacs_env_XY', with one + with the contents identical to 'struct emacs_env_XY', with one line added: @module_env_snippet_XY+1@ 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 93265594275..fb71a86a43e 100644 --- a/configure.ac +++ b/configure.ac @@ -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 @@ -1276,6 +1282,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]) @@ -1613,6 +1624,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 5.0 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 @@ -3146,7 +3181,7 @@ if test "${HAVE_W32}" = "yes"; then NATIVE_IMAGE_API="yes (w32)" W32_OBJ="$W32_OBJ w32image.o" fi - W32_LIBS="$W32_LIBS -lwinmm -lusp10 -lgdi32 -lcomdlg32" + W32_LIBS="$W32_LIBS -lwinmm -lgdi32 -lcomdlg32" W32_LIBS="$W32_LIBS -lmpr -lwinspool -lole32 -lcomctl32" W32_RES_LINK="\$(EMACSRES)" CLIENTRES="emacsclient.res" @@ -3921,6 +3956,8 @@ if test "${with_dbus}" = "yes"; then dnl dbus_watch_get_unix_fd has been introduced in D-Bus 1.1.1. dnl dbus_type_is_valid and dbus_validate_* have been introduced in dnl D-Bus 1.5.12. + dnl dbus_message_set_allow_interactive_authorization was introduced + dnl in D-Bus 1.8.10. OLD_LIBS=$LIBS LIBS="$LIBS $DBUS_LIBS" AC_CHECK_FUNCS([dbus_watch_get_unix_fd \ @@ -3928,7 +3965,8 @@ if test "${with_dbus}" = "yes"; then dbus_validate_bus_name \ dbus_validate_path \ dbus_validate_interface \ - dbus_validate_member]) + dbus_validate_member \ + dbus_message_set_allow_interactive_authorization]) LIBS=$OLD_LIBS DBUS_OBJ=dbusbind.o fi @@ -5963,7 +6001,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/emacs/anti.texi b/doc/emacs/anti.texi index 7abb504632b..42c656ac852 100644 --- a/doc/emacs/anti.texi +++ b/doc/emacs/anti.texi @@ -4,155 +4,133 @@ @c See file emacs.texi for copying conditions. @node Antinews -@appendix Emacs 28 Antinews +@appendix Emacs 29 Antinews @c Update the emacs.texi Antinews menu entry with the above version number. For those users who live backwards in time, here is information -about downgrading to Emacs version 28.2. We hope you will enjoy the +about downgrading to Emacs version 29.4. We hope you will enjoy the greater simplicity that results from the absence of many @w{Emacs @value{EMACSVER}} features. @itemize @bullet @item -Like its newer releases, Emacs 28 can still be built with support of +Emacs can no longer be built for Android mobile devices. We have +removed the Android support because it was deemed unnecessary, what with +the screens of the mobile devices becoming smaller and smaller as you +move back in time. We expect Android users to enjoy the much simpler +text editors available on their devices. As a nice bonus, removing +Android support allowed us to get rid of gobs of related files, thus +making the release tarballs much leaner. + +@item +We have deleted much of the enhanced support for touchscreen devices, +for the same reason we dropped Android: there will be no need for that +as you move back in time. + +@item +We also dropped support for sophisticated input methods that include +text conversions, again because those are mostly needed on mobile and +hand-held devices, which we gradually remove from Emacs in each past +version. + +@item +Like its newer releases, Emacs 29 can still be built with support of native compilation of Lisp programs. However, in preparation for -removal of this feature in some previous version, we've deleted the -capability of ahead-of-time native compilation of all the Lisp files -that come with Emacs. This makes the Emacs build process much faster. +removal of this feature in some previous version, we've made the native +compiler support off by default; you will now have to request it +explicitly at configure time. This makes the default Emacs build +process much faster. @item -Emacs can no longer be built with the tree-sitter library, so you no -longer will need to look for and install the grammar libraries for -the languages in which you want to program. Similarly, all the modes -that are based on the tree-sitter library were deleted, leaving you -with just one major mode for every supported programming language: no -more need to decide whether to turn the tree-sitter supported modes on -and try using their parser-based fontification, indentation, and other -features. For some languages and file types, this means no major mode -at all, leaving you with the venerable Fundamental mode as the -natural, high-performance choice. For example, Go, Rust, and CMake -files no longer have any major modes for editing their files --- -another milestone towards a simpler, leaner Emacs. +JSON interfaces are slowly move into oblivion as past years come closer, +so we have removed our internal implementation of JSON; you will now +need to build Emacs with the libjansson library, if you need JSON. +Eventually, we plan on removing JSON support from Emacs altogether; this +move will make the removal much simpler. @item -Built-in support for accessing SQLite databases was removed. You can -now again edit SQLite files as simple binary files, which Emacs is -quite capable to support, as it always did. +Tree-sitter based modes are now completely independent of their +non-Tree-Sitter counterparts. We decided that keeping the settings +separate and independent goes a long way toward simplicity, which is one +of our main motivation for removing stuff from Emacs. @item -As a gesture to users of the Haiku operating system, we've dropped the -code which allowed Emacs to be built on that OS@. We expect Haiku -users to enjoy the much simpler editors they have for editing their -files. +Various Help commands no longer turn on Outline minor mode. With less +material to display in the *Help* buffers, due to removing of excess +documentation from Emacs, we think using outlining is an unnecessary +complication, as scrolling through plain text is so much simpler. + +For the same reasons, Emacs no longer shows Unicode names of characters +in *Help* buffers shown by @code{describe-bindings}. @item -Support for XInput2 input events on X is gone. We think the -traditional X input events are more than enough, certainly so as you -move back in time, where XInput2 will eventually be removed from X as -well, once the maintainers of the X Windows system realize the utter -futility of supporting fancy input mechanisms. +To make Emacs configuration simpler and easier to control, the tool bar +can now be displayed only in its natural and logical position: on the +top of the frame; no more of that @code{tool-bar-position} nonsense with +tool bars on the bottom. For the same reasons @code{modifier-bar-mode} +is now gone. @item -The ``pure GTK'' (a.k.a.@: @acronym{PGTK}) configuration of Emacs is -no longer supported. This is in anticipation of the complete removal -of the GTK toolkit support from Emacs, and in accordance with our -expectation that GTK will cease to exist as you move back in time. We -plan on removing support for all the other toolkits as well, leaving -only the pure X build with our own widgets as the single supported GUI -configuration on X. +The command @code{recover-file} no longer allows to display the diffs +between a file and its auto-save file. You either want to recover a +file or you don't; confusing users with a third alternative when they +are anxious already by the possibility of losing precious edits is +considered a bad idea, certainly so as we move further towards smaller, +simpler Emacs. @item -The @option{--init-directory} command-line option was removed, as -initializing Emacs with init files of another user is a preposterous -idea anyway. +Several languages and input methods, which will fall in disuse as you +move back in time, were removed. This includes Urdu, Pashto, and Sindhi +languages, and the input method for the Colemak keyboard layout. Many +@kbd{C-x 8} key sequences, including those which insert various +quotation characters and guillemets, were deleted for the same reason. @item -In line with simplifying and eventually removing the -native-compilation option, we've deleted the -@option{--with-native-compilation=aot} configure-time option. This -greatly simplifies how native compilation works and makes your -configure-time decision regarding native compilation in Emacs -clear-cut: either Emacs compiles non-preloaded Lisp packages to native -code only before using it, or it never uses native compilation at all; -no more half measures and special exceptions. For similar reasons, -@code{native-compile-prune-cache} and -@code{startup-redirect-eln-cache} features are no longer part of -Emacs. +The support for @code{lzip}-compressed Info manuals was removed from the +Info mode. We anticipate that @command{lzip} will disappear from the +face of the Earth in the near past, and are preparing Emacs for that in +advance. @item -We've deleted the special code and features which allowed Emacs to -present decent performance and responsiveness when editing files with -very long lines. Such files become more and more rare as time goes -back, and so having all this tricky code in Emacs for their benefit -was deemed an unnecessary complication. +Support for LLDB in Grand Unified Debugger mode was dropped. We decided +that given LLDB's diminishing popularity, its support is just code +bloat. @item -Emacs dropped support for Eglot and the LSP servers. We decided that -the built-in ways of analyzing source code are more than enough as you -move back in time. +Several fancy Project and VC commands were deleted, as part of our +consistent effort of making Emacs simpler to use. @item -Commands to scale and rotate images are once again bound to single -keys like @kbd{+}, @kbd{-}, and @kbd{r}, which makes them much easier -to type. As for the risk of typing these by mistake, we don't believe -Emacs users make typing mistakes, especially as they move back in -time and become younger and younger. +The user option @code{shell-command-guess-functions} and the context +menu @samp{Open With} in Dired are gone. We trust Emacs users to always +know themselves which shell command is the appropriate one for a given +file, so no guessing by Dired is needed, or welcome. The +@code{dired-do-open} command was deleted for the same reasons. @item -To simplify typing popular commands, we've rebound the @w{@kbd{C-x 8 . .}} -back to @w{@kbd{C-x 8 .}} and @w{@kbd{C-x 8 = =}} back to @w{@kbd{C-x 8 =}}. -There's no need for fancier, longer key sequences, as moving back in -time means we will have fewer and fewer commands to bind to them in -the first place. +We went back to the original lean-and-mean interface for specifying +registers for register-related commands. The fancy preview and the +options to go with it were deemed gratuitous and were removed. @item -If you inadvertently kill the @file{*scratch*} buffer, Emacs will -recreate it in Fundamental mode, not in Lisp Interaction mode. You -get to turn on the mode you like yourself. Our long-term plans for -past Emacs releases is to remove the recreation of @file{*scratch*} -altogether, and this is the first step in that direction. +Eshell is now much smaller and easier to use, due to dropping quite a +few of the new commands and fancy new options. @item -Support for @code{rlogin} and @code{rsh} protocols are back, since we -expect them to become more and more important and popular as you move -back in time. +The command @code{customize-dirlocals} was removed. Editing the +@file{.dir-locals.el} files as plain text is so much simpler, and quite +enough. @item -In preparation for eventual removal of Unicode support from Emacs, -we've downgraded our Unicode support to version 14.0. +We have removed several packages that we consider unnecessary for the +past of Emacs. This includes EditorConfig support, @samp{which-key}, +PEG, and Window-Tool-Bar. @item -You can no longer change the size of the font globally. Since Emacs -will at some past date remove all support for variable-size fonts, -having such commands is a luxury we are better without. - -@item -On our permanent quest for simplifying Emacs, we've removed the -commands @code{duplicate-line} and @code{duplicate-dwim}; the old-time -friends @kbd{M-w} and @kbd{C-y} (typed one or more times) should -suffice. The command @code{rename-visited-file} is gone for the same -reason. - -@item -We've deleted many commands related to Emoji, which were bound in the -@kbd{C-x 8 e} prefix keymap. We decided that the ability to type -Emoji sequences using @kbd{C-x 8 @key{RET}} is enough, and actually -serves our users better by requiring them to know the codepoints of -the sequences they want to type. - -@item -We dropped support for many scripts and input methods, especially old -scripts that no one uses anyway. For similar reasons, Greek and -Ukrainian translations of the Emacs tutorial are not available -anymore. - -@item -@file{package.el} can no longer fetch source code of packages from -their VCS repositories. We think command-line tools like Git should -be enough to allow you to clone their repositories. So we deleted -the @code{package-vc-install} command and other similar commands. +The @code{etags-regen-mode} was deleted. Regeneration of @file{TAGS} +tables manually is all Emacs users will need in the past. @item To keep up with decreasing computer memory capacity and disk space, many -other functions and files have been eliminated in Emacs 28.2. +other functions and files have been eliminated in Emacs 29.4. @end itemize diff --git a/doc/emacs/basic.texi b/doc/emacs/basic.texi index a2a934ff243..42f5c971e2f 100644 --- a/doc/emacs/basic.texi +++ b/doc/emacs/basic.texi @@ -643,14 +643,11 @@ long, by using Auto Fill mode. @xref{Filling}. Normally, the first character of each continuation line is positioned at the beginning of the screen line where it is displayed. The minor mode @code{visual-wrap-prefix-mode} and its global -(@pxref{Minor Modes}) counterpart -@code{global-visual-wrap-prefix-mode} arranges that continuation lines -be prefixed by slightly adjusted versions of the fill prefixes -(@pxref{Fill Prefix}) of their respective logical lines, so that -indentation characters or the prefixes of source code comments are -replicated across every continuation line, and the appearance of such -comments or indentation is not broken. These prefixes are only shown -on display, and does not change the buffer text in any way. +counterpart (@pxref{Minor Modes}) @code{global-visual-wrap-prefix-mode} +arranges for continuation lines to be indented on display using a fill +prefix (@pxref{Fill Prefix}) automatically computed from each line's +surrounding context. These prefixes are display-only feature, and do +not change the buffer text in any way. Sometimes, you may need to edit files containing many long logical lines, and it may not be practical to break them all up by adding diff --git a/doc/emacs/buffers.texi b/doc/emacs/buffers.texi index 2786ff6ad65..eba593f0ec9 100644 --- a/doc/emacs/buffers.texi +++ b/doc/emacs/buffers.texi @@ -313,6 +313,8 @@ Kill buffer @var{buffer} (@code{kill-buffer}). Offer to kill each buffer, one by one. @item M-x kill-matching-buffers Offer to kill all buffers matching a regular expression. +@item M-x kill-matching-buffers-no-ask +Like @code{kill-matching-buffers}, but don't ask for confirmation. @end table @findex kill-buffer @@ -334,13 +336,16 @@ by one. An answer of @kbd{yes} means to kill the buffer, just like with a space, which are used internally by Emacs. @findex kill-matching-buffers +@findex kill-matching-buffers-no-ask The command @kbd{M-x kill-matching-buffers} prompts for a regular expression and kills all buffers whose names match that expression. -@xref{Regexps}. Like @code{kill-some-buffers}, it asks for -confirmation before each kill. This command normally ignores buffers -whose names begin with a space, which are used internally by Emacs. -To kill internal buffers as well, call @code{kill-matching-buffers} -with a prefix argument. +@xref{Regexps}. Like @code{kill-some-buffers}, it asks for confirmation +before each kill. This command normally ignores buffers whose names +begin with a space, which are used internally by Emacs. To kill +internal buffers as well, call @code{kill-matching-buffers} with a +prefix argument. The command @w{@kbd{M-x kill-matching-buffers-no-ask}} +works like @code{kill-matching-buffers}, but doesn't ask for +confirmation before killing each matching buffer. The Buffer Menu feature is also convenient for killing various buffers. @xref{Several Buffers}. diff --git a/doc/emacs/building.texi b/doc/emacs/building.texi index 38cc0bb67af..1b079c2cef9 100644 --- a/doc/emacs/building.texi +++ b/doc/emacs/building.texi @@ -477,6 +477,14 @@ non-@code{nil} if the buffer is to be saved). Any other non-@code{nil} value means that all buffers should be saved without asking. The default is @code{ask}. +@vindex grep-use-headings +@vindex grep-heading@r{ face} + By default, grep matches are shown with the file names prefixed to +each line. But if the variable @code{grep-use-headings} is customized +to a non-@code{nil} value, the matches are split into sections, one +section for each file with matches, and the file names are shown in the +section headings using a special face @code{grep-heading}. + @findex grep-find @findex find-grep The command @kbd{M-x grep-find} (also available as @kbd{M-x @@ -1313,6 +1321,10 @@ of output to its standard output, you may wish to separate its I/O from interaction with GDB. Use the command @w{@kbd{M-x gdb-display-io-buffer}} to show a window with a buffer to which Emacs redirects the input and output from the program you are debugging. +However, if the variable @code{gdb-display-io-buffer} is @code{nil}, +Emacs will not create nor display a separate I/O buffer, but will +instead redirect the program's interaction to the GUD interaction +buffer. @findex gdb-display-registers-buffer @item Registers Buffer diff --git a/doc/emacs/dired.texi b/doc/emacs/dired.texi index c251a6dc2be..cf57350743f 100644 --- a/doc/emacs/dired.texi +++ b/doc/emacs/dired.texi @@ -803,9 +803,9 @@ The @code{dired-keep-marker-copy} user option controls how this command handles file marking. The default is to mark all new copies of files with a @samp{C} mark. -@item D @findex dired-do-delete @kindex D @r{(Dired)} +@item D Delete the specified files (@code{dired-do-delete}). This is like the shell command @code{rm}. @@ -813,6 +813,13 @@ Like the other commands in this section, this command operates on the @emph{marked} files, or the next @var{n} files. By contrast, @kbd{x} (@code{dired-do-flagged-delete}) deletes all @dfn{flagged} files. +@findex dired-do-open +@kindex E @r{(Dired)} +@item E +``Open'' the specified files using an external program. The program is +selected according to the system conventions, as determined by the +variable @code{shell-command-guess-open}. + @findex dired-do-rename @kindex R @r{(Dired)} @cindex renaming files (in Dired) diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index cdc92679fcb..8776d358373 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -220,7 +220,7 @@ Appendices * GNU Free Documentation License:: The license for this documentation. * Emacs Invocation:: Hairy startup options. * X Resources:: X resources for customizing Emacs. -* Antinews:: Information about Emacs version 28. +* Antinews:: Information about Emacs version 29. * Mac OS / GNUstep:: Using Emacs under macOS and GNUstep. * Haiku:: Using Emacs on Haiku. * Android:: Using Emacs on Android. diff --git a/doc/emacs/files.texi b/doc/emacs/files.texi index dfacf501650..709cb0910e6 100644 --- a/doc/emacs/files.texi +++ b/doc/emacs/files.texi @@ -1633,8 +1633,8 @@ commands to visit the corresponding source locations. manipulate and apply parts of patches: @table @kbd -@item M-n @findex diff-hunk-next +@item M-n Move to the next hunk-start (@code{diff-hunk-next}). With prefix argument @var{n}, move forward to the @var{n}th next hunk. @@ -1645,45 +1645,50 @@ you set @code{diff-refine} to the symbol @code{navigation}, Diff mode only refines the hunk you move to with this command or with @code{diff-hunk-prev}. -@item M-p @findex diff-hunk-prev +@item M-p Move to the previous hunk-start (@code{diff-hunk-prev}). With prefix argument @var{n}, move back to the @var{n}th previous hunk. Like @kbd{M-n}, this command refines the hunk you move to if you set @code{diff-refine} to the symbol @code{navigation}. -@item M-@} @findex diff-file-next +@item M-@} Move to the next file-start, in a multi-file patch (@code{diff-file-next}). With prefix argument @var{n}, move forward to the start of the @var{n}th next file. -@item M-@{ @findex diff-file-prev +@item M-@{ Move to the previous file-start, in a multi-file patch (@code{diff-file-prev}). With prefix argument @var{n}, move back to the start of the @var{n}th previous file. -@item M-k @findex diff-hunk-kill +@item M-k Kill the hunk at point (@code{diff-hunk-kill}). -@item M-K @findex diff-file-kill +@item M-K In a multi-file patch, kill the current file part. (@code{diff-file-kill}). -@item C-c C-a @findex diff-apply-hunk @cindex patches, applying +@item C-c C-a Apply this hunk to its target file (@code{diff-apply-hunk}). With a prefix argument of @kbd{C-u}, revert this hunk, i.e.@: apply the reverse of the hunk, which changes the ``new'' version into the ``old'' version. If @code{diff-jump-to-old-file} is non-@code{nil}, apply the hunk to the ``old'' version of the file instead. -@item C-c C-b +@findex diff-apply-buffer +@item C-c @key{RET} a +Apply all the hunks in the buffer (@code{diff-apply-buffer}). If the +diffs were applied successfully, save the changed buffers. + @findex diff-refine-hunk +@item C-c C-b Highlight the changes of the hunk at point with a finer granularity (@code{diff-refine-hunk}). This allows you to see exactly which parts of each changed line were actually changed. @@ -1693,9 +1698,9 @@ By default, Diff mode refines hunks as Emacs displays them, so you may find this command useful if you customize @code{diff-refine} to a non-default value. -@item C-c C-c @findex diff-goto-source @vindex diff-jump-to-old-file +@item C-c C-c Go to the source file and line corresponding to this hunk (@code{diff-goto-source}). By default, this jumps to the ``new'' version of the file, the one shown first on the file header. @@ -1710,20 +1715,20 @@ this jumps to the work file by default. With a prefix argument, jump to the ``old'' revision of the file (@pxref{Old Revisions}), when point is on the old line, or otherwise jump to the ``new'' revision. -@item C-c C-e @findex diff-ediff-patch +@item C-c C-e Start an Ediff session with the patch (@code{diff-ediff-patch}). @xref{Top, Ediff, Ediff, ediff, The Ediff Manual}. -@item C-c C-n @findex diff-restrict-view +@item C-c C-n Restrict the view to the current hunk (@code{diff-restrict-view}). @xref{Narrowing}. With a prefix argument, restrict the view to the current file of a multiple-file patch. To widen again, use @kbd{C-x n w} (@code{widen}). -@item C-c C-r @findex diff-reverse-direction +@item C-c C-r Reverse the direction of comparison for the entire buffer (@code{diff-reverse-direction}). With a prefix argument, reverse the direction only inside the current region (@pxref{Mark}). Reversing @@ -1731,8 +1736,8 @@ the direction means changing the hunks and the file-start headers to produce a patch that would change the ``new'' version into the ``old'' one. -@item C-c C-s @findex diff-split-hunk +@item C-c C-s Split the hunk at point (@code{diff-split-hunk}) into two separate hunks. This inserts a hunk header and modifies the header of the current hunk. This command is useful for manually editing patches, @@ -1743,35 +1748,35 @@ produced by the @option{-c} or @option{--context} options to @command{diff}, first convert the buffer to the unified diff format with @kbd{C-c C-u}. -@item C-c C-d @findex diff-unified->context +@item C-c C-d Convert the entire buffer to the @dfn{context diff format} (@code{diff-unified->context}). With a prefix argument, convert only the hunks within the region. -@item C-c C-u @findex diff-context->unified +@item C-c C-u Convert the entire buffer to unified diff format (@code{diff-context->unified}). With a prefix argument, convert unified format to context format. When the mark is active, convert only the hunks within the region. -@item C-c C-l @findex diff-refresh-hunk +@item C-c C-l Re-generate the current hunk (@code{diff-refresh-hunk}). -@item C-c C-w @vindex diff-ignore-whitespace-switches @findex diff-ignore-whitespace-hunk +@item C-c C-w Re-generate the current hunk, disregarding changes in whitespace. With a non-@code{nil} prefix arg, re-generate all the hunks (@code{diff-ignore-whitespace-hunk}). This calls @code{diff-command} with @code{diff-ignore-whitespace-switches}, which defaults to @samp{-b}, meaning ignore changes in whitespace only. -@item C-x 4 A @findex diff-add-change-log-entries-other-window @findex add-change-log-entry-other-window@r{, in Diff mode} +@item C-x 4 A Generate a ChangeLog entry, like @kbd{C-x 4 a} does (@pxref{Change Log}), for each one of the hunks (@code{diff-add-change-log-entries-other-window}). This creates a diff --git a/doc/emacs/fixit.texi b/doc/emacs/fixit.texi index f3c876cf3f7..af9ca5fcdf6 100644 --- a/doc/emacs/fixit.texi +++ b/doc/emacs/fixit.texi @@ -473,6 +473,13 @@ it will slow down cursor motion and scrolling commands. It also doesn't automatically check the text you didn't type or move across; use @code{flyspell-region} or @code{flyspell-buffer} for that. +@vindex flyspell-check-changes + Normally, Flyspell mode highlights misspelled words that you typed or +modified, but also words you move across without changing them. But if +you customize the variable @code{flyspell-check-changes} to a +non-@code{nil} value, Flyspell mode will check only the words you typed +or edited in some way. + @findex flyspell-correct-word @findex flyspell-auto-correct-word @findex flyspell-correct-word-before-point diff --git a/doc/emacs/killing.texi b/doc/emacs/killing.texi index 57adc037cb7..62f72763ac6 100644 --- a/doc/emacs/killing.texi +++ b/doc/emacs/killing.texi @@ -302,6 +302,13 @@ a pure white space string to the kill ring, you can say: non-@code{nil} value, identical subsequent kills yield a single kill-ring entry, without duplication. +@findex kill-ring-deindent-mode + If you enable the minor mode @code{kill-ring-deindent-mode}, text +saved to the kill-ring will have its indentation decreased by the amount +of indentation of the first saved line. That is, if the first line of +the saved text was indented @var{n} columns, this mode will remove that +number of columns from the indentation of each saved line. + @node Yanking @section Yanking @cindex moving text diff --git a/doc/emacs/maintaining.texi b/doc/emacs/maintaining.texi index 3a9bef9884a..f4752fa2b29 100644 --- a/doc/emacs/maintaining.texi +++ b/doc/emacs/maintaining.texi @@ -1850,6 +1850,9 @@ Run shell command in the current project's root directory @item C-x p & Run shell command asynchronously in the current project's root directory (@code{project-async-shell-command}). +@item C-x p o +Run the next command in the current project +(@code{project-any-command}). @end table Emacs provides commands for handling project files conveniently. @@ -1946,6 +1949,11 @@ directory. @xref{Top,Eshell,Eshell, eshell, Eshell: The Emacs Shell}. The command @kbd{C-x p &} (@code{project-async-shell-command}) runs @code{async-shell-command} in the current project's root directory. +@findex project-any-command + Finally, the command @kbd{C-x p o} (@code{project-any-command}) will +run the next command you type, whether related to files or not, in the +current project. + @node Project Buffer Commands @subsection Project Commands That Operate on Buffers @@ -1958,6 +1966,9 @@ List the project buffers (@code{project-list-buffers}). @item C-x p k Kill all live buffers that belong to the current project (@code{project-kill-buffers}). +@item C-x p o +Run the next command in the current project +(@code{project-any-command}). @end table @findex project-switch-to-buffer @@ -1986,6 +1997,10 @@ project that satisfy any of @code{project-kill-buffer-conditions}. If @code{project-kill-buffers-display-buffer-list} is non-@code{nil}, the buffers to be killed will be displayed first. + Finally, the command @kbd{C-x p o} (@code{project-any-command}) will +run the next command you type, whether related to buffers or not, in the +current project. + @node Switching Projects @subsection Switching Projects @@ -2466,10 +2481,10 @@ the match with @var{replacement}. This command can only be used in @file{*xref*} buffers that show all the matches for an identifier in all the relevant files. @xref{Identifier Search}. +@cindex revert-buffer, in @file{*xref*} buffers @item g -@findex xref-revert-buffer -Refresh the contents of the @file{*xref*} buffer -(@code{xref-revert-buffer}). +Refresh the contents of the @file{*xref*} buffer (@code{revert-buffer}). +@xref{Reverting}. @item M-, @findex xref-quit-and-pop-marker-stack diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi index 4557f41c3f7..79744967455 100644 --- a/doc/emacs/mini.texi +++ b/doc/emacs/mini.texi @@ -452,6 +452,15 @@ While in the completion list buffer, kill it and delete the window showing it (@code{kill-current-buffer}). @end table +@vindex minibuffer-visible-completions + If the variable @code{minibuffer-visible-completions} is customized to +a non-@code{nil} value, it changes the commands bound to the arrow keys: +instead of moving in the minibuffer, they move between completion +candidates, like meta-arrow keys do by default. Similarly, +@kbd{@key{RET}} selects the current candidate, like @kbd{M-@key{RET}} +does normally. @code{C-g} hides the completion window, but leaves the +minibuffer active, so you can continue typing at the prompt. + @node Completion Exit @subsection Completion Exit @@ -685,6 +694,17 @@ then move to a candidate by cursor motion commands and select it with @code{second-tab}, then the first @kbd{@key{TAB}} will pop up the completions list buffer, and the second one will switch to it. +@findex previous-line-completion +@findex next-line-completion +@vindex completion-auto-wrap + When the window showing the completions is selected, either because +you customized @code{completion-auto-select} or because you switched to +it by typing @kbd{C-x o}, the @kbd{@key{UP}} and @kbd{@key{DOWN}} arrow +keys move by lines between completion candidates; with a prefix numeric +argument, they move that many lines. If @code{completion-auto-wrap} is +non-@code{nil}, these commands will wrap at bottom and top of the +candidate list. + @vindex completion-cycle-threshold If @code{completion-cycle-threshold} is non-@code{nil}, completion commands can cycle through completion alternatives. Normally, if diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index 13d86a32e79..d1e8217f579 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -2849,13 +2849,14 @@ frame parameters you don't want to be restored; they will then be set according to your customizations in the init file. @vindex desktop-files-not-to-save -@vindex remote-file-name-access-timeout +@vindex remote-file-name-access-timeout@r{, and desktop restoring} Information about buffers visiting remote files is not saved by default. Customize the variable @code{desktop-files-not-to-save} to change this. In this case, you might also consider customizing @code{remote-file-name-access-timeout}, which is the number of seconds after which buffer restoration of a remote file is -stopped. This prevents Emacs being blocked. +stopped. This prevents Emacs from being blocked when restoring sessions +that visited remote files. @vindex desktop-restore-eager By default, all the buffers in the desktop are restored in one go. diff --git a/doc/emacs/text.texi b/doc/emacs/text.texi index 1d1065c45c2..8abaeafcf33 100644 --- a/doc/emacs/text.texi +++ b/doc/emacs/text.texi @@ -1208,6 +1208,12 @@ Hide everything except the top @var{n} levels of heading lines Hide everything except for the heading or body that point is in, plus the headings leading up from there to the top level of the outline (@code{outline-hide-other}). +@item C-c / h @var{regexp} @key{RET} +Hide bodies of headings that match @var{regexp} +(@code{outline-hide-by-heading-regexp}). +@item C-c / s @var{regexp} @key{RET} +Show bodies of headings that match @var{regexp} +(@code{outline-show-by-heading-regexp}). @end table @findex outline-hide-entry @@ -1253,6 +1259,16 @@ headers leading up from there to top level in the outline) and the top level headings. It also reveals body lines preceding the first heading in the buffer. +@findex outline-hide-by-heading-regexp +@findex outline-show-by-heading-regexp +@kindex C-c / h @r{(Outline mode)} +@kindex C-c / s @r{(Outline mode)} + The command @kbd{C-c / h} (@code{outline-hide-by-heading-regexp}) +prompts for a regular expression, and hides all the body lines of +headings which match the regular expression. The command @kbd{C-c / s} +likewise prompts for a regular expression, and reveals the bodies of +matching headings. + @findex outline-hide-body @findex outline-show-all @kindex C-c C-t @r{(Outline mode)} diff --git a/doc/emacs/windows.texi b/doc/emacs/windows.texi index 5ad6850fed9..60599d42020 100644 --- a/doc/emacs/windows.texi +++ b/doc/emacs/windows.texi @@ -300,7 +300,8 @@ Make selected window narrower (@code{shrink-window-horizontally}). Shrink this window if its buffer doesn't need so many lines (@code{shrink-window-if-larger-than-buffer}). @item C-x + -Make all windows the same height (@code{balance-windows}). +Balance the sizes of all the windows of the selected frame +(@code{balance-windows}). @end table @kindex C-x 0 @@ -373,8 +374,11 @@ lines to other windows in the frame. @kindex C-x + @findex balance-windows - You can also use @kbd{C-x +} (@code{balance-windows}) to even out the -heights of all the windows in the selected frame. + You can also use @kbd{C-x +} (@code{balance-windows}) to balance the +sizes of all the windows of the selected frame (with the exception of +the minibuffer window, @pxref{Minibuffer}). This command makes each +horizontal pair of adjacent windows the same height, and each vertical +pair of adjacent windows the same width. @node Displaying Buffers @section Displaying a Buffer in a Window diff --git a/doc/lispref/ChangeLog.1 b/doc/lispref/ChangeLog.1 index ee8f418414c..e2d4c019b4a 100644 --- a/doc/lispref/ChangeLog.1 +++ b/doc/lispref/ChangeLog.1 @@ -4890,7 +4890,7 @@ 2011-05-10 Jim Meyering - * minibuf.texi: Fix typo "in in -> in". + * minibuf.texi: Fix typo. 2011-05-06 Paul Eggert diff --git a/doc/lispref/anti.texi b/doc/lispref/anti.texi index 0cb956eea98..8dba137ca31 100644 --- a/doc/lispref/anti.texi +++ b/doc/lispref/anti.texi @@ -6,178 +6,113 @@ @c This node must have no pointers. @node Antinews -@appendix Emacs 28 Antinews +@appendix Emacs 29 Antinews @c Update the elisp.texi Antinews menu entry with the above version number. For those users who live backwards in time, here is information about -downgrading to Emacs version 28.2. We hope you will enjoy the greater +downgrading to Emacs version 29.4. We hope you will enjoy the greater simplicity that results from the absence of many @w{Emacs @value{EMACSVER}} features. @itemize @bullet @item -The implementation of overlays is back to its simple, time-proven -storage in a pair of linear linked lists centered around some buffer -position. No more fancy interval trees and suchlikes. Lisp programs -that use overlays once again need to recenter overlays around the -buffer position of interest, and display-related features should again -make sure they don't use too many overlays in a buffer, lest redisplay -will be too slow. +Mouse wheel events once again follow the platform and window-system +conventions: sometimes they are @code{wheel-up/down} and sometimes +@code{mouse-4/5/6/7}. Lisp programs which use these should once again +be aware of the conventions in effect and behave accordingly. @item -Several functions stopped the annoying conversion of quotes and key -sequences by no longer calling @code{substitute-command-keys}. One -prominent example is @code{format-prompt} and all its many callers. -This makes the strings they produce much more predictable, returning -to you, the Lisp programmer, control on which punctuation characters -will appear in the text presented to the users. For similar reasons, -the @code{substitute-quotes} function was deleted. +The command @code{describe-function} no longer distracts you by showing +unnecessary details like the type of the function's object. Emacs +hackers always know whether a function is a primitive, a native-compiled +Lisp function, or any other kind. Stating the obvious simply wastes the +precious screen estate; as you move into the past, and the typical +dimensions of the screen become smaller, that waste is less and less +justified. So we made the waste smaller. @item -The venerable @code{buffer-modified-p} function again reliably returns -either @code{nil} or @code{t}, not any other confusing values. +The support for styled underline in face attribute was dropped. The +simple underline should be enough; anything else is just code bloat and +creeping featurism. Colorful underlines on TTY frames are no longer +supported for the same reason. @item -The support for @samp{medium} weight of fonts was dropped. Emacs now -considers @samp{medium} and @samp{regular} weights to be the same. We -believe this will simplify your font setup, since there's no longer a -need to worry about fonts that support @samp{regular} weight, but not -the @samp{medium} one, or vice versa: either one will do! +IELM stopped recording its input history. You will no longer be annoyed +by inputs from your past sessions; each session starts with a clean +slate. What can be simpler and easier to remember? @item -To reduce the amount of code in Emacs related to unimportant features, -we've removed the function @code{compiled-function-p}. Lisp programs -are expected to test explicitly for the relevant types of function -objects: built-in, byte-compiled, and natively-compiled. For the same -reasons we deleted the functions @code{pos-bol}, @code{pos-eol}, -@code{file-attribute-file-identifier}, and quite a few others. We -don't expect anyone to miss those fancy functions. +You can no longer disable JavaScript in xwidget Webkit sessions. Since +xwidgets are going away in one of the previous Emacs versions, we +decided to make this one step in that direction and get rid of this +complication. @item -The timeout used by @code{x-show-tip} can no longer be specified by -Lisp programs; it is hard-coded in the function. This will lead to a -simpler, easier maintained code, and no one should want to control the -timeout after which the tip pops down. +The @code{minibuffer-regexp-mode} was removed. Regular expressions are +just strings, so no fancy mode should be needed for editing them. @item -The macro @code{setopt} was deleted; use @code{customize-variable} -instead, or invoke the @code{:set} function from Lisp. +We removed the Compat package. Forward compatibility for ELPA packages +becomes less and less important as you move back through time, and soon +enough ELPA will disappear entirely. We decided it was prudent to start +preparing for that now. @item -We removed the @code{lisp-directory} variable, as the value can be -easily deduced from other similar variables, like -@code{installation-directory} and @code{source-directory}, each one -when it's relevant. +We are back to interpreting @code{\x} without any following hex digits +as character code zero (@acronym{NUL}), as it always was in Emacs. The +savings in typing due to this alone are enough to justify this +simplification. @item -To simplify code and reduce complexity, we deleted the functions -@code{get-display-property} and @code{add-display-text-property}; use -the generic @code{get-text-property} and @code{put-text-property} -instead. +To keep Emacs clean and elegant, we've removed the ability to show +tooltips for fringe bitmaps. What important information cam be shown on +the fringes, and why would it require tooltips to explain its purpose? +We decided it isn't justified to keep this in past versions of Emacs. @item -Support for pinch input events and for modern drag-and-drop -functionality on X was dropped. As you move back in time, these -facilities will become less and less important, and will soon enough -disappear, so there's no reason to keep them in Emacs. +Fancy sorting-related facilities, like the @code{value<} function and +keyword arguments for @code{sort}, were deleted as too complex. The +basic @code{sort} function should all that's needed in the years to go. @item -To keep Emacs clean and elegant, we've removed the @file{textsec.el} -library, with its facilities for checking whether some text is -``suspicious''. We consider our users smart enough to detect -maliciously modified text by just looking at it or by moving the -cursor across it, and the whole idea that someone would wish to -deliberately deceive Emacs users ridiculous and unworthy of -complicating our elegant text-processing and display capabilities. +Features related to the inheritance graph of major modes were deemed +unnecessary and thus were dropped. This includes +@code{provided-mode-derived-p}, @code{derived-mode-add-parents}, and +others. We decided that untangling the mode inheritance relationships +by hand facilitates more clear code and makes the intent evident. @item -The functions @code{keymap-set}, @code{keymap-global-set}, -@code{keymap-local-set}, @code{keymap-substitute}, -@code{keymap-lookup}, and some others were deleted. We have found the -traditional @code{define-key}, @code{global-set-key}, -@code{local-set-key}, @code{substitute-key-definition}, and -@code{key-binding} more than enough, and their minor inconsistencies -in the syntax of keys they accept a source of endless fun in Emacs -Lisp programming. Why make Emacs programming a dull place? For the -same reasons we deleted @code{key-valid-p}, since we consider the -permissive nature of @code{kbd} more in the spirit of Emacs Lisp. +We removed unnecessary functionality for handling touch screen events, +as touch screens gradually disappear from view as you move back in time. +There's no need to keep obsolete these new inventions in the past. @item -Yanking of anything but plain text from other applications becomes -more and more an unnecessary feature as you move back in time, so we -dropped support for pasting media like HTML and images via the -clipboard. If you @i{really} need to yank those into an Emacs buffer, -you can go via a disk file. +Various new functions and variables for moving and transposing sexps and +for moving by program statements were dropped as unnecessary. The +original commands that move by balanced expressions are more than +enough. @item -We removed unnecessary functions @code{string-pixel-width} and -@code{string-glyph-split}, as we consider it inappropriate for Lisp -programs to do display layout calculations, where these functions come -in handy. Display is for the display engine, written in C, and should -stay there! +We deleted some fancy @code{declare} forms for functions, such as +@code{ftype}. Emacs Lisp is not a string-typed language, which makes +these declarations anathema. The types @code{closure} and +@code{interpreted-function} are gone for the same reason: no need to +distinguish types of Lisp functions. @item -Various new Xwidget functions, such as -@code{xwidget-perform-lispy-event}, @code{xwidget-webkit-load-html}, -and @code{xwidget-webkit-back-forward-list}, were deleted as part of -our continuing effort to gradually delete the entire Xwidget -functionality in some previous release of Emacs. +The byte compiler stopped issuing warnings about practices some purists +consider questionable. This includes warnings about missing +@code{lexical-binding} cookies, empty bodies of special forms and +macros, comparison with literals, @code{condition-case} without +handlers, mutation of constants, and some others. As time moves into +the past, the typical Emacs hacker knows best what's correct code and +what isn't, and thus these warnings become useless annoyances. Good +riddance! @item -Setting the @code{:stderr} property of a process in a -@code{make-process} call once again forces the process's connection to -use pipes, not ptys, for all the standard streams --- a considerable -simplification of this complex interface. - -@item -To keep the amount of Lisp functions from growing out of control, we -deleted @code{string-equal-ignore-case}. Use @code{compare-strings} -instead. - -Several features that complicated the byte compiler have been removed: - -@itemize @minus -@item -The warnings about quoting mistakes in documentation strings. You are -expected to find such mistakes yourself, by eyeballing the resulting -@file{*Help*} buffer display. - -@item -The warnings about malformed @code{defcustom} types, like -double-quoting symbols in @code{choice} lists. -@end itemize - -@item -The macro @code{with-buffer-unmodified-if-unchanged} was deleted. -Lisp programs that need to leave the buffer unmodified in these cases -can always compare the text before and after the modifications. - -@item -The functions @code{string-edit} and @code{read-string-from-buffer} -were removed, as we consider the fun of programming them anew every -time an important part of the education of each Emacs Lisp developer. - -@item -We deleted the function @code{readablep} and the related variable -@code{print-unreadable-function}, since no one is supposed to want to -print unreadable Lisp objects. - -@item -The facility for storing multisession variables was deleted as an -unnecessary complication. With it are gone @code{multisession-value}, -@code{define-multisession-variable}, and -@code{list-multisession-values}. - -@item -The support for the @code{cursor-face} text property was dropped. We -consider the rest of the faces adequate for supporting this -functionality. - -@item -The function @code{tooltip-show} dropped support for optional face -arguments @code{text-face} and @code{default-face} that allow fancy -control of the face of the tip text and top frame colors. We decided -that tooltips should all look the same, to prevent user confusion. +The @code{obarray} type is gone. Obarrays are back to their original +representation as vectors. Each removed Lisp data type makes Emacs +simpler and easier to use, so this is a welcome deletion. @item As part of the ongoing quest for simplicity, many other functions and 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/compile.texi b/doc/lispref/compile.texi index 9f93fb4a981..65442dd8d19 100644 --- a/doc/lispref/compile.texi +++ b/doc/lispref/compile.texi @@ -1024,6 +1024,9 @@ Like 1, and in addition dump pseudo-C code. Like 2, and in addition dump the GCC intermediate passes and @file{libgccjit} log file. @end table + +When generated, the pseudo-C code is deposited in the same directory +as the corresponding @file{.eln} file. @end defopt @defopt native-comp-verbose diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 34096196df4..6e4b727a2bd 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -1659,15 +1659,47 @@ overlay. @end defun @defun remove-overlays &optional start end name value -This function removes all the overlays between @var{start} and -@var{end} whose property @var{name} has the specified @var{value}. It -can move the endpoints of the overlays in the region, or split them. +This function clears the text in the region between @var{start} and +@var{end} of any overlays whose property named @var{name} has the +specified @var{value}, such that no such overlay will affect the text in +the region. To do this, the function can remove overlays in the region, +or move their endpoints, or split them, or do some combination of these. +Specifically: -If @var{name} is omitted or @code{nil}, it means to delete all overlays in -the specified region. If @var{start} and/or @var{end} are omitted or -@code{nil}, that means the beginning and end of the buffer respectively. -Therefore, @code{(remove-overlays)} removes all the overlays in the -current buffer. +@itemize @bullet +@item +Overlays that start at or after @var{start} and end before @var{end} +will be removed completely. + +@item +Overlays that start before @var{start} and end after @var{start}, but +before @var{end}, will be altered so that they end at @var{start}. + +@item +Overlays that start at or after @var{start} and end after @var{end} will +be altered so that they start at @var{end}. + +@item +Overlays that start before @var{start} and end after @var{end} will be +split into two overlays: one that ends at @var{start} and the other that +begins at @var{end}. +@end itemize + +If @var{name} is omitted or @code{nil}, it means to delete/modify all +overlays that affect text in the specified region. If @var{start} +and/or @var{end} are omitted or @code{nil}, they default to the +beginning and end of the buffer, respectively. Therefore, +@code{(remove-overlays)} removes all the overlays in the current buffer. + +Values of the named overlay property are compared using @code{eq}, which +is important if the values are anything but symbols or fixnums +(@pxref{Equality Predicates}). It means the values passed to the +function must be the same values used to set the overlay property, not +their copies; objects which are different will not compare equal even if +they have identical contents. + +The optional arguments @var{name} and @var{value} should either both be +passed and non-@code{nil}, or both omitted or @code{nil}. @end defun @defun copy-overlay overlay @@ -5182,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/lispref/elisp.texi b/doc/lispref/elisp.texi index 1059d0dcf61..f464bcfe94f 100644 --- a/doc/lispref/elisp.texi +++ b/doc/lispref/elisp.texi @@ -236,7 +236,7 @@ To view this manual in other formats, click Appendices -* Antinews:: Info for users downgrading to Emacs 28. +* Antinews:: Info for users downgrading to Emacs 29. * GNU Free Documentation License:: The license for this documentation. * GPL:: Conditions for copying and changing GNU Emacs. * Tips:: Advice and coding conventions for Emacs Lisp. diff --git a/doc/lispref/functions.texi b/doc/lispref/functions.texi index dcce4043064..695e1c3efb5 100644 --- a/doc/lispref/functions.texi +++ b/doc/lispref/functions.texi @@ -186,8 +186,8 @@ their code. @end defun @noindent -Unlike @code{functionp}, the next three functions do @emph{not} treat -a symbol as its function definition. +Unlike @code{functionp}, the next functions do @emph{not} treat a symbol +as its function definition. @defun subrp object This function returns @code{t} if @var{object} is a built-in function @@ -243,6 +243,20 @@ without symbol indirection. It signals an error for non-built-in functions. We recommend to use @code{func-arity} instead. @end defun +@defun cl-functionp object +This function is like @code{functionp}, except it returns @code{nil} for +lists and symbols. +@end defun + +@findex subr-primitive-p +@defun primitive-function-p object +This function returns @code{t} if @var{object} is a built-in primitive +written in C (@pxref{Primitive Function Type}). Note that special forms +are explicitly excluded, as they are not functions. Use +@code{subr-primitive-p} if you need to recognize special forms as well. +@end defun + + @node Lambda Expressions @section Lambda Expressions @cindex lambda expression diff --git a/doc/lispref/package.texi b/doc/lispref/package.texi index 421e64dd5d1..40c550b56b4 100644 --- a/doc/lispref/package.texi +++ b/doc/lispref/package.texi @@ -192,10 +192,11 @@ used as the long description. (When displaying the description, Emacs omits the @samp{;;; Commentary:} line, as well as the leading comment characters in the commentary itself.) - If the file has a @samp{Package-Requires} header, that is used as -the package dependencies. In the above example, the package depends -on the @samp{flange} package, version 1.0 or higher. @xref{Library -Headers}, for a description of the @samp{Package-Requires} header. If + If the file has a @samp{Package-Requires} header, that is used as the +package dependencies. In the above example, the package depends on the +@samp{flange} package, version 1.0 or higher. @xref{Library Headers}, +for a description of the @samp{Package-Requires} header. To depend on a +specific version of Emacs, specify @samp{emacs} as the package name. If the header is omitted, the package has no dependencies. The @samp{Keywords} and @samp{URL} headers are optional, but recommended. @@ -247,9 +248,10 @@ is the brief description. @var{requirements} is a list of required packages and their versions. Each element in this list should have the form @code{(@var{dep-name} -@var{dep-version})}, where @var{dep-name} is a symbol whose name is -the dependency's package name, and @var{dep-version} is the -dependency's version (a string). +@var{dep-version})}, where @var{dep-name} is a symbol whose name is the +dependency's package name, and @var{dep-version} is the dependency's +version (a string). The spacial value @samp{emacs} means that the +package depends on the given version of Emacs. @end defun If the content directory contains a file named @file{README}, this diff --git a/doc/lispref/peg.texi b/doc/lispref/peg.texi index e496e1cf817..01666456c9c 100644 --- a/doc/lispref/peg.texi +++ b/doc/lispref/peg.texi @@ -29,7 +29,7 @@ current buffer, using a given set of rules. @cindex root, of parsing expression grammar @cindex entry-point, of parsing expression grammar Each rule in a @acronym{PEG} is referred to as a @dfn{parsing -expression} (@acronym{PEX}), and can be specified a a literal string, a +expression} (@acronym{PEX}), and can be specified a literal string, a regexp-like character range or set, a peg-specific construct resembling an Emacs Lisp function call, a reference to another rule, or a combination of any of these. A grammar is expressed as a tree of rules diff --git a/doc/lispref/positions.texi b/doc/lispref/positions.texi index 9193c1063d1..ead7833af61 100644 --- a/doc/lispref/positions.texi +++ b/doc/lispref/positions.texi @@ -875,14 +875,21 @@ nested defuns. @findex treesit-forward-sentence @findex forward-sentence @findex backward-sentence -If Emacs is compiled with tree-sitter, it can use the tree-sitter -parser information to move across syntax constructs. Since what -exactly is considered a sentence varies between languages, a major -mode should set @code{treesit-thing-settings} to determine that. -Then the mode can get navigation-by-sentence functionality for free, -by using @code{forward-sentence} and -@code{backward-sentence}(@pxref{Moving by Sentences,,, emacs, The -extensible self-documenting text editor}). +@vindex forward-sentence-function +@cindex sentence, in program source files +The function that is the value of the variable +@code{forward-sentence-function} determines how to move across syntax +constructs known as @dfn{sentences}. Major modes can assign their own +functions to this variable to customize the behavior of +@code{forward-sentence} command. If Emacs is compiled with tree-sitter, +it can use the tree-sitter parser information to move across syntax +constructs. Since what exactly is considered a sentence varies between +languages, a major mode should set @code{treesit-thing-settings} to +determine that. Then @code{forward-sentence-function} will be set to +@code{treesit-forward-sentence}, and the mode will get +navigation-by-sentence functionality for free, by using +@code{forward-sentence} and @code{backward-sentence}(@pxref{Moving by +Sentences,,, emacs, The extensible self-documenting text editor}). @findex treesit-forward-sexp @findex forward-sexp@r{, and tree-sitter} diff --git a/doc/lispref/strings.texi b/doc/lispref/strings.texi index 6e5c3521135..e290e2e7a6b 100644 --- a/doc/lispref/strings.texi +++ b/doc/lispref/strings.texi @@ -406,11 +406,12 @@ that matches @var{trim-right} from @var{string}. Both regexps default to @samp{[ \t\n\r]+}. @end defun -@defun string-fill string length -Attempt to Word-wrap @var{string} so that no lines are longer than -@var{length}. Filling is done on whitespace boundaries only. If -there are individual words that are longer than @var{length}, these -will not be shortened. +@defun string-fill string width +Attempt to Word-wrap @var{string} so that it displays with lines no +wider than @var{width}. Filling is done on whitespace boundaries only. +If there are individual words that are longer than @var{width}, these +will not be shortened, and therefore @var{string} might be shown with +lines wider than @var{width} in that case. @end defun @defun string-limit string length &optional end coding-system diff --git a/doc/lispref/tips.texi b/doc/lispref/tips.texi index 1e35b82e413..802fa0febed 100644 --- a/doc/lispref/tips.texi +++ b/doc/lispref/tips.texi @@ -611,7 +611,7 @@ little space in a running Emacs. @item Format the documentation string so that it fits in an Emacs window on an 80-column screen. It is a good idea for most lines to be no wider than -60 characters. The first line should not be wider than 67 characters +60 characters. The first line should not be wider than 74 characters, or it will look bad in the output of @code{apropos}. @vindex emacs-lisp-docstring-fill-column diff --git a/doc/misc/calc.texi b/doc/misc/calc.texi index 381da21cebe..54909c130c3 100644 --- a/doc/misc/calc.texi +++ b/doc/misc/calc.texi @@ -28482,7 +28482,7 @@ logarithmic scales, Calc uses the @kbd{l} prefix for functions operating on notes. Scientific pitch notation refers to a note by giving a letter -A through G, possibly followed by a flat or sharp) with a subscript +A through G, possibly followed by a flat or sharp, with a subscript indicating an octave number. Each octave starts with C and ends with B and @c increasing each note by a semitone will result diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index 7f299180fc6..bcbd9faf0c9 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -835,12 +835,14 @@ Emacs Manual}, for fuller details. @code{comment-region} isn't actually part of @ccmode{}; it is given a @ccmode{} binding for convenience. -@item @kbd{M-;} (@code{comment-dwim} or @code{indent-for-comment} @footnote{The name of this command varies between (X)Emacs versions.}) +@item @kbd{M-;} (@code{comment-dwim} or @code{indent-for-comment}) @kindex M-; @findex comment-dwim @findex indent-for-comment Insert a comment at the end of the current line, if none is there -already. Then reindent the comment according to @code{comment-column} +already@footnote{The name of this command varies between (X)Emacs +versions.}. Then reindent the comment according to +@code{comment-column} @ifclear XEMACS (@pxref{Options for Comments,,, emacs, GNU Emacs Manual}) @end ifclear @@ -1221,15 +1223,17 @@ also suppresses auto-newline mode. Toggle auto-newline minor mode. When the command turns the mode on, it also enables electric minor mode. -@item @kbd{M-x c-toggle-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-d}.} +@item @kbd{M-x c-toggle-hungry-state} @findex c-toggle-hungry-state @findex toggle-hungry-state @r{(c-)} -Toggle hungry-delete minor mode. +Toggle hungry-delete minor mode@footnote{Prior to @ccmode{} 5.31, this +command was bound to @kbd{C-c C-d}.}. -@item @kbd{M-x c-toggle-auto-hungry-state}@footnote{Prior to @ccmode{} 5.31, this command was bound to @kbd{C-c C-t}.} +@item @kbd{M-x c-toggle-auto-hungry-state} @findex c-toggle-auto-hungry-state @findex toggle-auto-hungry-state @r{(c-)} -Toggle both auto-newline and hungry delete minor modes. +Toggle both auto-newline and hungry delete minor modes@footnote{Prior to +@ccmode{} 5.31, this command was bound to @kbd{C-c C-t}.}. @item @kbd{C-c C-w} (@code{M-x subword-mode}) @kindex C-c C-w @@ -1569,7 +1573,7 @@ perform @code{c-hungry-delete-backwards} and rather than using the minor mode toggling. @table @asis -@item @kbd{C-c C-@key{DEL}}, or @kbd{C-c @key{DEL}} (@code{c-hungry-delete-backwards})@footnote{This command was formerly known as @code{c-hungry-backspace}.} +@item @kbd{C-c C-@key{DEL}}, or @kbd{C-c @key{DEL}} (@code{c-hungry-delete-backwards}) @kindex C-c C-Backspace @kindex C-c Backspace @kindex C-c C-DEL @@ -1580,7 +1584,8 @@ Delete any amount of whitespace in the backwards direction (regardless whether hungry-delete mode is enabled or not). This command is bound to both @kbd{C-c C-@key{DEL}} and @kbd{C-c @key{DEL}}, since the more natural one, @kbd{C-c C-@key{DEL}}, is sometimes difficult to type at -a character terminal. +a character terminal@footnote{This command was formerly known as +@code{c-hungry-backspace}.}. @item @kbd{C-c C-d}, @kbd{C-c C-@key{DELETE}}, or @kbd{C-c @key{DELETE}} (@code{c-hungry-delete-forward}) @kindex C-c C-d @@ -5128,7 +5133,7 @@ started on line 2. Lines 4 and 5 get the syntaxes though part of a function. Note that the @code{requires} on Line 3 begins a @dfn{requires -expression}, not a a requires clause, hence its components are not +expression}, not a requires clause, hence its components are not assigned @code{constraint-cont}. See @url{https://en.cppreference.com/w/cpp/language/requires}. diff --git a/doc/misc/dbus.texi b/doc/misc/dbus.texi index e5d867acd40..20d26c80d38 100644 --- a/doc/misc/dbus.texi +++ b/doc/misc/dbus.texi @@ -1208,7 +1208,7 @@ which carries the input parameters to the object owning the method to be called, and a reply message returning the resulting output parameters from the object. -@defun dbus-call-method bus service path interface method &optional :timeout timeout &rest args +@defun dbus-call-method bus service path interface method &optional :timeout timeout :authorizable auth &rest args @anchor{dbus-call-method} This function calls @var{method} on the D-Bus @var{bus}. @var{bus} is either the keyword @code{:system} or the keyword @code{:session}. @@ -1223,6 +1223,10 @@ method call must return. The default value is 25,000. If the method call doesn't return in time, a D-Bus error is raised (@pxref{Errors and Events}). +If the parameter @code{:authorizable} is given and the following +@var{auth} is non-@code{nil}, the invoked method may interactively +prompt the user for authorization. The default is @code{nil}. + The remaining arguments @var{args} are passed to @var{method} as arguments. They are converted into D-Bus types as described in @ref{Type Conversion}. @@ -1302,7 +1306,7 @@ emulate the @code{lshal} command on GNU/Linux systems: @cindex method calls, asynchronous @cindex asynchronous method calls -@defun dbus-call-method-asynchronously bus service path interface method handler &optional :timeout timeout &rest args +@defun dbus-call-method-asynchronously bus service path interface method handler &optional :timeout timeout :authorizable auth &rest args This function calls @var{method} on the D-Bus @var{bus} asynchronously. @var{bus} is either the keyword @code{:system} or the keyword @code{:session}. @@ -1321,6 +1325,10 @@ reply message must arrive. The default value is 25,000. If there is no reply message in time, a D-Bus error is raised (@pxref{Errors and Events}). +If the parameter @code{:authorizable} is given and the following +@var{auth} is non-@code{nil}, the invoked method may interactively +prompt the user for authorization. The default is @code{nil}. + The remaining arguments @var{args} are passed to @var{method} as arguments. They are converted into D-Bus types as described in @ref{Type Conversion}. diff --git a/doc/misc/efaq.texi b/doc/misc/efaq.texi index 5b722f9fd77..73bc2442678 100644 --- a/doc/misc/efaq.texi +++ b/doc/misc/efaq.texi @@ -847,6 +847,7 @@ in the Emacs development repository (@pxref{Latest version of Emacs}). @menu * Origin of the term Emacs:: * Latest version of Emacs:: +* New in Emacs 30:: * New in Emacs 29:: * New in Emacs 28:: * New in Emacs 27:: @@ -920,6 +921,90 @@ Emacs, type @kbd{C-h C-n} (@kbd{M-x view-emacs-news}). You can give this command a prefix argument to read about which features were new in older versions. + +@node New in Emacs 30 +@section What is different about Emacs 30? +@cindex Differences between Emacs 29 and Emacs 30 +@cindex Emacs 30, new features in + +Here's a list of the most important changes in Emacs 30 as compared to +Emacs 29. The full list is too long to fit here, but can be read in the +Emacs @file{NEWS} file by typing @kbd{C-h n} inside Emacs. + +@itemize +@item +Native compilation is now enabled by default. When Emacs is built on a +machine with @samp{libgccjit}, this will improve Emacs performance in +many typical workloads. + +@item +Emacs has been ported to the Android operating system. See the file +@file{java/INSTALL} in the Emacs source distribution for details on how +to build it. + +@item +Numerous performance improvements, for example in parsing JSON, reading +data from subprocesses, handling output from Eshell and in Shell mode, X +selection requests, remote files, and so on. + +@item +Native JSON support is now always available; libjansson is no longer +used. + +@item +New major modes based on the +@uref{https://tree-sitter.github.io/tree-sitter/, tree-sitter library} +library for editing Elixir, HTML, Lua, HEEx, and PHP. + +@item +Support for the EditorConfig standard has been added, an editor-neutral +way to provide directory local (project-wide) settings. It is enabled +via a new global minor mode @code{editorconfig-mode} which makes Emacs +obey the @file{.editorconfig} files. + +@item +Support for touchscreens has been improved. 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. + +@item +Tool bar tweaks. The new minor mode @code{window-tool-bar-mode} +provides a per-window toolbar. Toolbars can be placed on the bottom of +a frame by setting the @code{tool-bar-position} variable on all window +systems but GNUStep and macOS. + +@item +The @samp{which-key} package from GNU ELPA is now included in Emacs. +After enabling the minor mode mode @code{which-key-mode}, if you enter +@kbd{C-x} and wait for one second, the minibuffer will expand with all +available key bindings that follow @kbd{C-x} (or as many as space +allows). + +@item +New global minor mode @code{kill-ring-deindent-mode}. When enabled, +text being saved to the kill ring will be de-indented by the column +number at its start. + +@item +New minor mode @code{visual-wrap-prefix-mode}. Unlike @kbd{M-q}, the +indentation only happens on display, and doesn't change the buffer text +in any way. + +@item +Automatic regeneration of TAGS files using the new global minor mode +@code{etags-regen-mode}. + +@item +Improved warnings from the byte-code compiler to aid Lisp developers. + +@item +Support for underline colors on TTY frames. + +@end itemize + + @node New in Emacs 29 @section What is different about Emacs 29? @cindex Differences between Emacs 28 and Emacs 29 @@ -929,6 +1014,9 @@ Here's a list of the most important changes in Emacs 29 as compared to Emacs 28 (the full list is too long, and can be read in the Emacs @file{NEWS} file by typing @kbd{C-h n} inside Emacs). +Note that Emacs 29.3 and 29.4 both contained important security fixes. +Upgrading is particularly important if you use Emacs as a mail client. + @itemize @item Emacs can now be built with the @@ -1718,7 +1806,7 @@ is better to write ``Emacs and XEmacs.'' * Deleting menus and menu options:: * Turning on syntax highlighting:: * Scrolling only one line:: -* Editing MS-DOS files:: +* Editing Windows files:: * Filling paragraphs with a single space:: * Escape sequences in shell output:: * Start Emacs maximized:: @@ -1786,7 +1874,7 @@ customize, with completion. Colors and faces are supported in non-windowed mode, i.e., on Unix and GNU/Linux text-only terminals and consoles, and when invoked as -@samp{emacs -nw} on X, MS-DOS and MS-Windows. Emacs automatically +@samp{emacs -nw} on X, MS-Windows and MS-DOS. Emacs automatically detects color support at startup and uses it if available. If you think that your terminal supports colors, but Emacs won't use them, check the @code{termcap} entry for your display type for color-related @@ -3073,22 +3161,22 @@ Alternatively, use the following Lisp form in your init file (setq scroll-conservatively most-positive-fixnum) @end lisp -@node Editing MS-DOS files -@section How can I edit MS-DOS files using Emacs? -@cindex Editing MS-DOS files -@cindex MS-DOS files, editing +@node Editing Windows files +@section How can I edit Windows files using Emacs? @cindex Microsoft files, editing @cindex Windows files, editing +@cindex Editing MS-DOS files +@cindex MS-DOS files, editing -Detection and handling of MS-DOS (and Windows) files is performed -transparently. You can open MS-DOS files on a Unix system, edit it, +Detection and handling of Windows (and MS-DOS) files is performed +transparently. You can open Windows files on a Unix system, edit it, and save it without having to worry about the file format. -When editing an MS-DOS style file, the mode line will indicate that it -is a DOS file. On Unix and GNU/Linux systems, and also on a Macintosh, -the string @samp{(DOS)} will appear near the left edge of the mode line; -on DOS and Windows, where the DOS end-of-line (EOL) format is the -default, a backslash (@samp{\}) will appear in the mode line. +When editing a Windows style file, the mode line will indicate that it +is a Windows file. On GNU/Linux, Unix and macOS systems, the string +@samp{(DOS)} will appear near the left edge of the mode line; on Windows +and MS-DOS, where the DOS end-of-line (EOL) format is the default, a +backslash (@samp{\}) will appear in the mode line. @node Filling paragraphs with a single space @section How can I tell Emacs to fill paragraphs with a single space after each period? @@ -3576,6 +3664,21 @@ same privileges as the Emacs process itself. Be aware of this when you use the package system (e.g. @code{M-x list-packages}) with third party archives. Use only third parties that you can trust! +@item +Using an out-of-date Emacs version. + +For security purposes, we recommend always using the latest officially +released version of Emacs. Using old versions of Emacs might put your +security at risk, as newer versions occasionally include important +security fixes. Please review the Emacs release notes and the +@file{etc/NEWS} file for details. + +Upgrading to the most recent version is particularly important if you +use Emacs as a mail client, or to edit files that come from untrusted +sources. You should be able to install the latest version of Emacs +through your system's package manager, and it is always available at +@uref{https://www.gnu.org/software/emacs/, the Emacs website}. + @item The @code{file-local-variable} feature. (Yes, a risk, but easy to change.) @@ -4436,7 +4539,7 @@ display or is invoked with @samp{emacs -nw}, you typically need to use @code{set-terminal-coding-system} to tell Emacs what the terminal can display, even after setting the language environment; otherwise non-@acronym{ASCII} characters will display as @samp{?}. On other operating -systems, such as MS-DOS and MS-Windows, Emacs queries the OS about the +systems, such as MS-Windows and MS-DOS, Emacs queries the OS about the character set supported by the display, and sets up the required terminal coding system automatically. diff --git a/doc/misc/erc.texi b/doc/misc/erc.texi index c7cbf7908b8..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 +@set ERCVER 5.6.1 @set ERCDIST as distributed with Emacs @value{EMACSVER} @include docstyle.texi @syncodeindex fn cp diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi index 69f94fab469..8547131194e 100644 --- a/doc/misc/eshell.texi +++ b/doc/misc/eshell.texi @@ -1201,8 +1201,11 @@ or a string, referring to an environment variable. @cmindex wait @cindex processes, waiting for -@item wait [@var{process}]@dots{} -Wait until each specified @var{process} has exited. +@item wait [-t @var{timeout}] [@var{process}]@dots{} +Wait until each specified @var{process} has exited. Processes can +either be process objects (@pxref{Processes, , , elisp, GNU Emacs Lisp +Reference Manual}) or integer PIDs. If you pass @code{-t} or +@code{--timeout}, wait at most that many seconds before exiting. @cmindex which @item which @var{command}@dots{} 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 diff --git a/doc/misc/gnus.texi b/doc/misc/gnus.texi index 56f259db9a1..b2dfc46f74c 100644 --- a/doc/misc/gnus.texi +++ b/doc/misc/gnus.texi @@ -20413,7 +20413,7 @@ Anyway, if you'd like to dig into it yourself, here's an example: (read-only nil) (orphan -10) (adapt t) - (files "/hom/larsi/News/gnu.SCORE") + (files "/home/larsi/News/gnu.SCORE") (exclude-files "all.SCORE") (local (gnus-newsgroup-auto-expire t) (gnus-summary-make-false-root empty)) diff --git a/doc/misc/org.org b/doc/misc/org.org index 31431a6ffc9..fc2935ebe6d 100644 --- a/doc/misc/org.org +++ b/doc/misc/org.org @@ -23163,7 +23163,7 @@ specify a date December 1, 2005, the call might look like =(diary-date 12 1 2005)= or =(diary-date 1 12 2005)= or =(diary-date 2005 12 1)=, depending on the settings. This has been the source of much confusion. Org mode users can resort to special versions of -these functions, namely ~org-date~, ~org-anniversary~, ~org-cyclic, and +these functions, namely ~org-date~, ~org-anniversary~, ~org-cyclic~, and ~org-block~. These work just like the corresponding ~diary-~ functions, but with stable ISO order of arguments (year, month, day) wherever applicable, independent of the value of diff --git a/doc/misc/trampver.texi b/doc/misc/trampver.texi index bf5c90ee8a9..b17dde18656 100644 --- a/doc/misc/trampver.texi +++ b/doc/misc/trampver.texi @@ -7,7 +7,7 @@ @c In the Tramp GIT, the version number and the bug report address @c are auto-frobbed from configure.ac. -@set trampver 2.7.1-pre +@set trampver 2.7.2-pre @set trampurl https://www.gnu.org/software/tramp/ @set tramp-bug-report-address tramp-devel@@gnu.org @set emacsver 27.1 diff --git a/doc/misc/transient.texi b/doc/misc/transient.texi index 7e8ffcf91bf..22db4e82143 100644 --- a/doc/misc/transient.texi +++ b/doc/misc/transient.texi @@ -31,7 +31,7 @@ General Public License for more details. @finalout @titlepage @title Transient User and Developer Manual -@subtitle for version 0.7.0 +@subtitle for version 0.7.2 @author Jonas Bernoulli @page @vskip 0pt plus 1filll @@ -53,7 +53,7 @@ resource to get over that hurdle is Psionic K's interactive tutorial, available at @uref{https://github.com/positron-solutions/transient-showcase}. @noindent -This manual is for Transient version 0.7.0. +This manual is for Transient version 0.7.2. @insertcopying @end ifnottex @@ -1208,7 +1208,10 @@ prefix's @code{transient--layout} property, but it is often more convenient to use the same form as understood by @code{transient-define-prefix}, described below. If you use the latter approach, you can use the @code{transient-parse-suffixes} and @code{transient-parse-suffix} functions to -transform them from the convenient to the expected form. +transform them from the convenient to the expected form. Depending +on the used group class, @code{transient-parse-suffixes}'s SUFFIXES must be +a list of group vectors (for @code{transient-columns}) or a list of suffix +lists (for all other group classes). If you explicitly specify children and then transform them using @code{:setup-children}, then the class of the group is determined as usual, @@ -1220,6 +1223,32 @@ For backward compatibility, if you fail to do so, @code{transient-column} is used and a warning is displayed. This warning will eventually be replaced with an error. +@lisp +(transient-define-prefix my-finder-by-keyword () + "Select a keyword and list matching packages." + ;; The real `finder-by-keyword' is more convenient + ;; of course, but that is not the point here. + [:class transient-columns + :setup-children + (lambda (_) + (transient-parse-suffixes + 'my-finder-by-keyword + (let ((char (1- ?A))) + (mapcar ; a list ... + (lambda (partition) + (vconcat ; of group vectors ... + (mapcar (lambda (elt) + (let ((keyword (symbol-name (car elt)))) + ; ... where each suffix is a list + (list (format "%c" (cl-incf char)) + keyword + (lambda () + (interactive) + (finder-list-matches keyword))))) + partition))) + (seq-partition finder-known-keywords 7)))))]) +@end lisp + @item The boolean @code{:pad-keys} argument controls whether keys of all suffixes contained in a group are right padded, effectively aligning the diff --git a/doc/misc/widget.texi b/doc/misc/widget.texi index 2e378e86fc7..744b84ac80d 100644 --- a/doc/misc/widget.texi +++ b/doc/misc/widget.texi @@ -3287,6 +3287,16 @@ Face used for pressed buttons. Face used for inactive widgets. @end deffn +@deffn Face widget-unselected +Face used for unselected widgets. This face is also used on the text +labels of radio-button and checkbox widgets. + +The default value inherits from the @code{widget-inactive} face. If you +want to visually distinguish the labels of unselected active +radio-button or checkbox widgets from the labels of unselected inactive +widgets, customize this face to a non-default value. +@end deffn + @defopt widget-mouse-face Face used for highlighting a button when the mouse pointer moves across it. diff --git a/etc/DEBUG b/etc/DEBUG index 4eae090621f..06544674e5d 100644 --- a/etc/DEBUG +++ b/etc/DEBUG @@ -1157,6 +1157,12 @@ Please refer to the LLDB reference on the web for more information about LLDB. If you already know GDB, you will also find a mapping from GDB commands to corresponding LLDB commands there. +** Debugging Emacs on OpenBSD + +To debug Emacs on OpenBSD, use the 'egdb' command from the 'gdb' +package. This reportedly works both if Emacs was compiled with GCC and +if it was compiled with clang. + ** Debugging Emacs on Android. A script located in the java/ directory automates the procedures @@ -1282,39 +1288,39 @@ the crash. The third form is printed when Emacs misuses the JVM in some fashion that is detected by the Android CheckJNI facility. It looks like: -A/art﹕ art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: ... -A/art﹕ art/runtime/check_jni.cc:65] in call to CallVoidMethodV -A/art﹕ art/runtime/check_jni.cc:65] from void android.os.MessageQueue.nativePollOnce(long, int) -A/art﹕ art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable -A/art﹕ art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x87d30ef0 self=0xb4f07800 -A/art﹕ art/runtime/check_jni.cc:65] | sysTid=18828 nice=-11 cgrp=apps sched=0/0 handle=0xb6fdeec8 -A/art﹕ art/runtime/check_jni.cc:65] | state=R schedstat=( 2249126546 506089308 3210 ) utm=183 stm=41 core=3 HZ=100 -A/art﹕ art/runtime/check_jni.cc:65] | stack=0xbe0c8000-0xbe0ca000 stackSize=8MB -A/art﹕ art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) -A/art﹕ art/runtime/check_jni.cc:65] native: #00 pc 00004640 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) -A/art﹕ art/runtime/check_jni.cc:65] native: #01 pc 00002e8d /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) -A/art﹕ art/runtime/check_jni.cc:65] native: #02 pc 00248381 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream >&, int, char const*, art::mirror::ArtMethod*)+68) -A/art﹕ art/runtime/check_jni.cc:65] native: #03 pc 0022cd0b /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream >&) const+146) -A/art﹕ art/runtime/check_jni.cc:65] native: #04 pc 000b189b /system/lib/libart.so (art::JniAbort(char const*, char const*)+582) -A/art﹕ art/runtime/check_jni.cc:65] native: #05 pc 000b1fd5 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60) -A/art﹕ art/runtime/check_jni.cc:65] native: #06 pc 000b50e5 /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1284) -A/art﹕ art/runtime/check_jni.cc:65] native: #07 pc 000bc59f /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+30) -A/art﹕ art/runtime/check_jni.cc:65] native: #08 pc 00063803 /system/lib/libandroid_runtime.so (???) -A/art﹕ art/runtime/check_jni.cc:65] native: #09 pc 000776bd /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::dispatchVsync(long long, int, unsigned int)+40) -A/art﹕ art/runtime/check_jni.cc:65] native: #10 pc 00077885 /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::handleEvent(int, int, void*)+80) -A/art﹕ art/runtime/check_jni.cc:65] native: #11 pc 00010f6f /system/lib/libutils.so (android::Looper::pollInner(int)+482) -A/art﹕ art/runtime/check_jni.cc:65] native: #12 pc 00011019 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92) -A/art﹕ art/runtime/check_jni.cc:65] native: #13 pc 000830c1 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) -A/art﹕ art/runtime/check_jni.cc:65] native: #14 pc 000b22d7 /system/framework/arm/boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+102) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.MessageQueue.nativePollOnce(Native method) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.MessageQueue.next(MessageQueue.java:143) -A/art﹕ art/runtime/check_jni.cc:65] at android.os.Looper.loop(Looper.java:130) -A/art﹕ art/runtime/check_jni.cc:65] at android.app.ActivityThread.main(ActivityThread.java:5832) -A/art﹕ art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke!(Native method) -A/art﹕ art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke(Method.java:372) -A/art﹕ art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) -A/art﹕ art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) -A/art﹕ art/runtime/check_jni.cc:65] +A/art: art/runtime/check_jni.cc:65] JNI DETECTED ERROR IN APPLICATION: ... +A/art: art/runtime/check_jni.cc:65] in call to CallVoidMethodV +A/art: art/runtime/check_jni.cc:65] from void android.os.MessageQueue.nativePollOnce(long, int) +A/art: art/runtime/check_jni.cc:65] "main" prio=5 tid=1 Runnable +A/art: art/runtime/check_jni.cc:65] | group="main" sCount=0 dsCount=0 obj=0x87d30ef0 self=0xb4f07800 +A/art: art/runtime/check_jni.cc:65] | sysTid=18828 nice=-11 cgrp=apps sched=0/0 handle=0xb6fdeec8 +A/art: art/runtime/check_jni.cc:65] | state=R schedstat=( 2249126546 506089308 3210 ) utm=183 stm=41 core=3 HZ=100 +A/art: art/runtime/check_jni.cc:65] | stack=0xbe0c8000-0xbe0ca000 stackSize=8MB +A/art: art/runtime/check_jni.cc:65] | held mutexes= "mutator lock"(shared held) +A/art: art/runtime/check_jni.cc:65] native: #00 pc 00004640 /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) +A/art: art/runtime/check_jni.cc:65] native: #01 pc 00002e8d /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) +A/art: art/runtime/check_jni.cc:65] native: #02 pc 00248381 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream >&, int, char const*, art::mirror::ArtMethod*)+68) +A/art: art/runtime/check_jni.cc:65] native: #03 pc 0022cd0b /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream >&) const+146) +A/art: art/runtime/check_jni.cc:65] native: #04 pc 000b189b /system/lib/libart.so (art::JniAbort(char const*, char const*)+582) +A/art: art/runtime/check_jni.cc:65] native: #05 pc 000b1fd5 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60) +A/art: art/runtime/check_jni.cc:65] native: #06 pc 000b50e5 /system/lib/libart.so (art::ScopedCheck::ScopedCheck(_JNIEnv*, int, char const*)+1284) +A/art: art/runtime/check_jni.cc:65] native: #07 pc 000bc59f /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+30) +A/art: art/runtime/check_jni.cc:65] native: #08 pc 00063803 /system/lib/libandroid_runtime.so (???) +A/art: art/runtime/check_jni.cc:65] native: #09 pc 000776bd /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::dispatchVsync(long long, int, unsigned int)+40) +A/art: art/runtime/check_jni.cc:65] native: #10 pc 00077885 /system/lib/libandroid_runtime.so (android::NativeDisplayEventReceiver::handleEvent(int, int, void*)+80) +A/art: art/runtime/check_jni.cc:65] native: #11 pc 00010f6f /system/lib/libutils.so (android::Looper::pollInner(int)+482) +A/art: art/runtime/check_jni.cc:65] native: #12 pc 00011019 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92) +A/art: art/runtime/check_jni.cc:65] native: #13 pc 000830c1 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) +A/art: art/runtime/check_jni.cc:65] native: #14 pc 000b22d7 /system/framework/arm/boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+102) +A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.nativePollOnce(Native method) +A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.next(MessageQueue.java:143) +A/art: art/runtime/check_jni.cc:65] at android.os.Looper.loop(Looper.java:130) +A/art: art/runtime/check_jni.cc:65] at android.app.ActivityThread.main(ActivityThread.java:5832) +A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke!(Native method) +A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke(Method.java:372) +A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) +A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) +A/art: art/runtime/check_jni.cc:65] In such situations, the first line explains what infraction Emacs committed, while the ensuing ones print backtraces for each running diff --git a/etc/NEWS b/etc/NEWS index af32a93d9c4..f10f9ae4d65 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -36,6 +36,76 @@ applies, and please also update docstrings as needed. * Changes in Specialized Modes and Packages in Emacs 31.1 +** Whitespace + +--- +*** '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 + +--- +*** 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'. + ++++ +*** Eshell's built-in "wait" command now accepts a timeout. +By passing "-t" or "--timeout", you can specify a maximum time to wait +for the processes to exit. Additionally, you can now wait for external +processes by passing their PIDs. + +** SHR + ++++ +*** 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. + +--- +*** 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'. + +** Emacs Lisp mode + +--- +*** Checkdoc no longer warns about missing footer lines in some cases. +Emacs Lisp libraries have traditionally ended with a footer line +(sometimes referred to as "terminating comment"). Their purpose was to +easily detect files that had been truncated in transit on ancient and +less reliable connections: + + ;; some-cool-package.el ends here + +'checkdoc' will no longer warn if that line is missing for packages that +explicitly only support Emacs 30.1 or later, as specified in the +"Package-Requires" header. The reason for keeping the warning for +packages that support earlier versions of Emacs is that package.el in +those versions can't install packages where that line is missing. + +This change affects both 'M-x checkdoc' and the corresponding flymake +backend. + +--- +*** Checkdoc will now flag incorrect formatting in warnings. +This affects calls to 'warn', 'lwarn', 'display-warning', and +'message-box'. + +--- +*** The default of 'checkdoc-verb-check-experimental-flag' is now nil. +In most cases, having it enabled leads to a large amount of false +positives. + * New Modes and Packages in Emacs 31.1 @@ -45,9 +115,21 @@ applies, and please also update docstrings as needed. * Lisp Changes in Emacs 31.1 ++++ +*** Support interactive D-Bus authorization. +A new ':authorizable t' parameter has been added to 'dbus-call-method' +and 'dbus-call-method-asynchronously' to allow the user to interactively +authorize the invoked D-Bus method (e.g., via polkit). + * Changes in Emacs 31.1 on Non-Free Operating Systems +--- +** 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. + ---------------------------------------------------------------------- This file is part of GNU Emacs. diff --git a/etc/NEWS.30 b/etc/NEWS.30 index d8fa92eb71e..31d69ddabab 100644 --- a/etc/NEWS.30 +++ b/etc/NEWS.30 @@ -24,13 +24,6 @@ applies, and please also update docstrings as needed. * Installation Changes in Emacs 30.1 -+++ -** 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 compilation is now enabled by default. 'configure' will enable the Emacs Lisp native compiler, so long as @@ -39,15 +32,12 @@ compilation, configure Emacs with the option: ./configure --with-native-compilation=no ---- -** Emacs now defaults to 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 -Linux and BSD versions of ALSA. Use '--with-sound=alsa' to build with -ALSA on these operating systems instead. ++++ +** 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. @@ -55,9 +45,20 @@ 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': @@ -71,18 +72,20 @@ 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 -** 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 variable '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. - +--- ** 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 @@ -93,17 +96,15 @@ 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. -+++ -** 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'. +--- +** 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'. @@ -122,242 +123,173 @@ 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: +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's reimplemented in native code, reducing GC churn. - -To undo the change, set 'fast-read-process-output' to nil. - - -* Changes in Emacs 30.1 - -** 'describe-function' now shows the type of the function object. -The text used to say things like "car is is a built-in function" -whereas it now says "car is a primitive-function" where "primitive-function" -is the symbol returned by 'cl-type-of' and you can click on it to get -information about that type. - -** 'advice-remove' is now an interactive command. -When called interactively, 'advice-remove' now prompts for an advised -function to the advice to remove. - -** Emacs now supports Unicode Standard version 15.1. - -** 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. - -** Network Security Manager +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. +** 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. +** 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. -** Help ++++ +** 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. +++ -*** 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. - -*** 'describe-function' shows function inferred type when available. -For native compiled Lisp functions 'describe-function' prints (after -the signature) the automatically inferred function type as well. - ---- -*** 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. - ---- -*** '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. - ** Emacs now comes with Org v9.7. See the file "etc/ORG-NEWS" for user-visible changes in Org. -** Outline mode - -*** New commands to show/hide outlines by regexp. -'/ 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. '/ s' ('outline-show-by-heading-regexp') does the same but -shows the matched outlines. ++++ +** 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. +++ -*** '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'. - -** 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. +** 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. --- -** 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 -closed, if possible. +** 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. +++ -** 'write-region-inhibit-fsync' now defaults to t in interactive mode, -as it has in batch mode since Emacs 24. - -+++ -** 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'. -When a positive number, this option limits the call of 'access-file' -for remote files to this 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 face 'display-time-date-and-time'. -This is used for displaying the time and date components of -'display-time-mode'. - ---- -** New icon images for general use. -Several symbolic icons are added to "etc/images/symbols", including -plus, minus, check-mark, star, etc. - -+++ -** 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 Nextstep. - -+++ -** New global minor mode 'modifier-bar-mode'. -When this minor mode is enabled, buttons representing modifier keys -are displayed along the tool bar. - -+++ -** 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. - -+++ -** "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 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. - ---- -** 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'. - -** '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. - -+++ -** CL Print - -+++ -*** 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. - -+++ -*** There is a new chapter in the CL manual documenting cl-print.el. -See the Info node "(cl) Printing". - ** 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 '' and '' 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. @@ -378,19 +310,13 @@ by adding '(category . symbol)' to the condition part of It specifies whether the window of the displayed buffer should be selected or deselected at the end of executing the current command. ---- -*** 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)'. - +++ *** 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' @@ -407,6 +333,31 @@ according to the context stored in a window parameter. 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 --- @@ -428,6 +379,11 @@ the name of the killed buffer that was displayed in that window. 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'. @@ -454,86 +410,214 @@ 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. ---- -*** New user option 'tab-line-tabs-buffer-group-function'. -It provides two choices to group tab buffers by major mode and by -project name. - --- *** Buffers on group tabs are now sorted alphabetically. This will keep the fixed order of tabs, even after switching between them. -+++ -** New optional 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 you want to modify. +** Help -** Emacs Server and Client ++++ +*** 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. --- -*** 'server-eval-args-left' can be used to pop and eval subsequent args. -When '--eval' is passed to emacsclient and Emacs is evaluating each -argument, this variable is set to those arguments not yet evaluated. -It can be used 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). +*** 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. +++ -** 'recover-file' can show diffs between auto save file and current file. +*** 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. ---- -** 'ffap-lax-url' now defaults to nil. -Previously, it was set to t but this broke remote file name detection. - +++ -** Multi-character key echo now ends with a suggestion to use Help. -Customize 'echo-keystrokes-help' to nil to prevent that. +*** '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. -+++ -** 'read-passwd' can toggle the visibility of passwords. -Use 'TAB' in the minibuffer to show or hide the password. Likewise, -there is an icon on the mode-line, which toggles the visibility of the -password when clicking with 'mouse-1'. - -+++ -** 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. +*** 'advice-remove' is now an interactive command. +When called interactively, 'advice-remove' now prompts for an advised +function to the advice to remove. --- -** Support for underline colors on TTY frames. -Colors specified in face underlines will now also be displayed in TTY -frames with the previously mentioned capabilities. +*** 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'. -** Miscellaneous ++++ +*** 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'. -+++ -** 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. +*** '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. -** The default value of 'read-process-output-max' was increased to 65536. * Editing Changes in Emacs 30.1 @@ -552,16 +636,10 @@ buffers. lightly edited for inclusion in Emacs.) +++ -** New user option 'gud-highlight-current-line'. -When enabled, Gud will visually emphasize the line being executed upon -pauses in the debugee's execution, such as those occasioned by -breakpoints being hit. - ---- ** 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: +function call within an indented block: foo () { @@ -570,24 +648,62 @@ foo () argument_3_compute ()); } -will save: +will save this to the kill ring: long_function_with_several_arguments (argument_1_compute (), argument_2_compute (), argument_3_compute ()) -to the kill ring, omitting the two columns of extra indentation that -would otherwise be present in the second and third lines of the -function call. +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. +++ -** Emacs now has better 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 written. Countless packages, -such as Dired and Custom have been adjusted to better understand touch -screen input. +** 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". @@ -596,11 +712,6 @@ 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 command 'kill-matching-buffers-no-ask'. -This works like 'kill-matching-buffers', but without asking for -confirmation. - --- ** New user option 'duplicate-region-final-position'. It controls the placement of point and the region after duplicating a @@ -617,8 +728,49 @@ 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 @@ -644,14 +796,17 @@ 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 @@ -659,6 +814,7 @@ 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: @@ -668,17 +824,20 @@ right quotation marks: 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 ~ >' +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. @@ -686,28 +845,19 @@ This can now be entered using 'C-x 8 E' in addition to the existing * Changes in Specialized Modes and Packages in Emacs 30.1 ---- -** Titdic-cnv -Most of the variables and functions in the file have been renamed to -make sure they all use a 'tit-' namespace prefix. - ---- -** Trace -In batch mode, tracing now sends the trace to stdout. +** Outline mode +++ -** Mwheel -The 'wheel-up/down/left/right' events are now bound unconditionally, -and 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). +*** 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. -** Xterm Mouse mode -This mode now emits 'wheel-up/down/right/left' events 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). ++++ +*** '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 @@ -718,14 +868,21 @@ This user option associates manual names with URLs. It affects the 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. -+++ -** New command 'lldb'. -Run the LLDB debugger, analogous to the 'gud-gdb' command. +** GUD (Grand Unified Debugger) -** GDB MI ++++ +*** 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'. @@ -734,8 +891,8 @@ 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 +'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 @@ -743,21 +900,22 @@ 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, 'M-x gdb' will neither create nor display a separate +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. +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 @@ -767,6 +925,7 @@ 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 @@ -780,22 +939,26 @@ 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'. -*** 'project-try-vc' tries harder to find the responsible VCS. +--- +*** 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, we now -additionally traverse the parent directories until a VCS root is found +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 @@ -808,7 +971,7 @@ you can add this to your init script: --- *** New variable 'project-files-relative-names'. -If it's non-nil, 'project-files' can return file names relative to the +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. @@ -833,32 +996,34 @@ 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 ('C-x v l') ends at a rename, we -now print the old name(s) and a button which jumps to their history. -Git and Hg are supported. Naturally, 'vc-git-print-log-follow' should -be nil for this to work (or '--follow' should not be in -'vc-hg-print-log-switches', in Hg's case). Unlike when the '--follow' -switch is used, commands to see the diff of the old revision ('d'), -check out an old file version ('f') or annotate it right away ('a'), -also work on revisions which precede 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 'vc-annotate-use-short-revision' to nil. +behavior, set user option 'vc-annotate-use-short-revision' to nil. -*** New option 'vc-git-file-name-changes-switches'. +--- +*** 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' 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 +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. @@ -874,21 +1039,11 @@ 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. -** Isearch and Replace - -*** 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. - ** Dired --- @@ -899,13 +1054,15 @@ 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 filenames. -The middle part of a filename whose length exceeds the restriction is +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" @@ -914,16 +1071,19 @@ based on marked files in Dired. Possible backends are 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 @@ -934,21 +1094,6 @@ in size. *** 'dired-listing-switches' handles connection-local values if exist. This allows to customize different switches for different remote machines. -** Registers - -+++ -*** 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. - ** Ediff --- @@ -1081,7 +1226,7 @@ After manually editing 'eshell-aliases-file', you can use this command to load the edited aliases. +++ -*** 'rgrep' is now a builtin command. +*** 'rgrep' is now a builtin Eshell command. Running 'rgrep' in Eshell now uses the Emacs grep facility instead of calling external rgrep. @@ -1094,50 +1239,6 @@ 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. -** Minibuffer and Completions - -*** New commands 'previous-line-completion' and 'next-line-completion'. -Bound to '' and '' 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'. - ** Pcomplete --- @@ -1175,32 +1276,25 @@ 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'. -** Make mode - -*** 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. - ** 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. It is by default bound to -'M-q' in 'prog-mode' and all its descendants. +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 +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 option 'completion-category-overrides' +You can customize the user option 'completion-category-overrides' and set 'display-sort-function' for the category 'imenu'. ** Which Function mode @@ -1312,11 +1406,6 @@ manual "(tramp) Improving performance of asynchronous remote processes". When a direct asynchronous process is invoked, it uses 'tramp-remote-path' for setting the remote 'PATH' environment variable. -** File Notifications - -+++ -*** All backends except w32notify detect unmounting of a watched filesystem now. - ** EWW --- @@ -1386,13 +1475,13 @@ prefix argument, it always displays the readable parts, and with a zero or negative prefix, it always displays the full page. +++ -*** New option 'eww-readable-urls'. +*** 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 option 'eww-readable-adds-to-history'. +*** 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. @@ -1513,10 +1602,12 @@ 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 @@ -1524,6 +1615,7 @@ 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 @@ -1547,10 +1639,12 @@ instead of: 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. @@ -1560,19 +1654,28 @@ and 'python-nav-end-of-block' to the inferior Python process. --- *** 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 error in the error messages +shell, the line indicating the source of an error in the error messages from ExceptionGroup will be recognized as well. -** Scheme mode -Scheme mode now handles regular expression literal '#/regexp/' that is -available in some Scheme implementations. +** 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'. +This keyword enables the user to install packages using package-vc.el. +++ *** New user option 'use-package-vc-prefer-newest'. @@ -1594,7 +1697,7 @@ 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 user option 'nnweb-type' to 'gmane'. +the server variable 'nnweb-type' to 'gmane'. --- *** New user option 'gnus-mode-line-logo'. @@ -1626,7 +1729,7 @@ 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 -dictionary. +dictionaries. --- *** New user option 'dictionary-display-definition-function'. @@ -1665,13 +1768,19 @@ 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'. -*** 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 --- @@ -1680,7 +1789,7 @@ 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. @@ -1692,10 +1801,12 @@ fit on fewer lines without negatively impacting readability. 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 @@ -1703,21 +1814,25 @@ 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 +--- +*** 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, eg. "q«text»". Use this minor +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 page are obsolete. -The Perl documentation in info format is no longer distributed with +--- +*** 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. @@ -1741,38 +1856,17 @@ 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. -** Notifications - -+++ -*** Allow using 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) - -** Image - -+++ -*** Image ':map' property is now recomputed when image is transformed. -Now images with clickable maps work as expected after you run commands -such as 'image-increase-size', 'image-decrease-size', 'image-rotate', -'image-flip-horizontally', and 'image-flip-vertically'. - -+++ -*** New user option 'image-recompute-map-p'. -Set this option to nil to prevent Emacs from recomputing image maps. - ** Image Dired ++++ *** New user option 'image-dired-thumb-naming'. -You can now configure how a thumbnail is named using this option. +You can now configure how thumbnails are named using this option. ** ERT +++ *** New macro 'skip-when' to skip 'ert-deftest' tests. -This can help avoid some awkward skip conditions. For example +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)'. @@ -1782,15 +1876,6 @@ 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. -** URL - -+++ -*** '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 function -'url-gateway-nslookup-host' are consequently also obsolete. - ** Socks +++ @@ -1813,54 +1898,6 @@ 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'. -** Proced - ---- -*** More control on automatic update of Proced buffers. -The user option 'proced-auto-update-flag' can now be set to 2 additional -values, which control automatic updates of Proced buffers that are not -displayed in some window. - -** Kmacro - -+++ -*** New Advanced Macro Counter functions. -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. - -** Kmacro Menu mode - -+++ -*** 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. - -** 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. - ** Calc +++ @@ -1868,10 +1905,10 @@ This command can toggle boolean options for the duration of a session. 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. You may also be interested to know that precomposed fraction -characters, such as ½ (U+00BD VULGAR FRACTION ONE HALF), are also -recognized as rational fractions. They have been since 2004, but it -looks like it was never mentioned in the NEWS, or even the manual. +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 @@ -1889,21 +1926,14 @@ 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. -** Xwidget Webkit +** Widget +++ -*** New user option 'xwidget-webkit-disable-javascript'. -This allows disabling JavaScript in xwidget Webkit sessions. - -** Ls Lisp - ---- -*** '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'. - -** 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'. @@ -1912,6 +1942,7 @@ If non-nil, moving point forward or backward between widgets by typing ** 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 @@ -1929,8 +1960,8 @@ 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 help implement custom -thingatpt providers for "things" that are defined by a text property. +'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'. @@ -1939,15 +1970,9 @@ will return the URL for that bug. ** Miscellaneous ---- -*** 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. - +++ *** New user option 'rcirc-log-time-format'. -This allows for rcirc logs to use a custom timestamp format, than the +This allows for rcirc logs to use a custom timestamp format, which the chat buffers use by default. --- @@ -1963,6 +1988,16 @@ 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: @@ -1974,16 +2009,74 @@ The following new XML schemas are now supported: - Nuget package specification file - Nuget packages config file -** color.el now supports the Oklab color representation. +--- +*** color.el now supports the Oklab color representation. + ++++ +*** New user option 'xwidget-webkit-disable-javascript'. +This allows disabling JavaScript in xwidget Webkit sessions. --- -** 'M-x ping' can now give "ping" additional flags. +*** '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 "ping". +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. @@ -1993,7 +2086,38 @@ There is also a new major mode 'editorconfig-conf-mode' to edit those configuration files. +++ -** New package Track-Changes. +** 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': @@ -2004,46 +2128,13 @@ the functionality of 'after-change-functions': reported (calls to 'before/after-change-functions' that are incorrectly paired, missing, etc...) and reports them adequately. -** New major modes based on the tree-sitter library - +++ -*** New major mode 'html-ts-mode'. -An optional major mode based on the tree-sitter library for editing -HTML files. - -+++ -*** New major mode 'heex-ts-mode'. -A major mode based on the tree-sitter library for editing HEEx files. - -+++ -*** New major mode 'elixir-ts-mode'. -A major mode based on the tree-sitter library for editing Elixir 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. - - -** Minibuffer and Completions - -+++ -*** New global minor mode 'minibuffer-regexp-mode'. -This is a minor mode for editing regular expressions in the minibuffer. -It 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. - -+++ -*** 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 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. @@ -2055,13 +2146,22 @@ dark. In addition to these, we now have 'modus-operandi-tinted' and '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 customization options. +showcases all their user options. +++ -** 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 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. @@ -2070,41 +2170,9 @@ 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 package 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 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 package Which-Key -The 'which-key' package from GNU ELPA is now included in Emacs. It -implements the 'which-key-mode' that displays a table of key bindings -upon entering a partial key chord and waiting for a moment. - * Incompatible Lisp Changes in Emacs 30.1 ---- -** 'subr-native-elisp-p' is renamed to 'native-comp-function-p'. -The previous name still exists but is marked as obsolete. - +++ ** Evaluating a 'lambda' returns an object of type 'interpreted-function'. Instead of representing interpreted functions as lists that start with @@ -2122,6 +2190,16 @@ 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 @@ -2130,60 +2208,22 @@ 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. ---- -** 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'. - +++ -** 'M-TAB' now invokes 'completion-at-point' also 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 bind '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'. - -** '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. - -** 'buffer-match-p' and 'match-buffers' take '&rest args'. -They used to take a single '&optional arg' and were documented to use +** '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. +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 'gcs-elapsed'. +--- +** 'post-gc-hook' runs after updating 'gcs-done' and 'gc-elapsed'. --- -** 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. - ---- -** Connection-local variables are applied in buffers visiting a remote file. +** Connection-local variables are applied in buffers visiting remote files. This overrides possible directory-local or file-local variables with the same name. ---- -** 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. - ---- -** 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'. - +++ ** 'copy-tree' now copies records when its optional 2nd argument is non-nil. @@ -2195,58 +2235,14 @@ assertion only (which is useless). For historical compatibility, an operator character following '^' or '\`' becomes literal, but we advise against relying on this. ---- -** 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'. - +++ ** 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. +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. -+++ -** X color support compatibility aliases are now marked 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 obsolete calling convention of 'sit-for' has been removed. -That convention was: '(sit-for SECONDS MILLISEC &optional NODISP)'. - -** The 'millisec' argument of 'sleep-for' has been declared obsolete. -Use a float value for the first argument instead. - -** 'eshell-process-wait-{seconds,milliseconds}' options are now obsolete. -Instead, use 'eshell-process-wait-time', which supports floating-point -values. - +++ ** Conversion of strings to and from byte-arrays works with multibyte strings. The functions 'dbus-string-to-byte-array' and @@ -2269,13 +2265,80 @@ 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'. +beside ".dir-locals.el". +++ ** 'auto-coding-functions' can know the name of the file. @@ -2284,11 +2347,12 @@ which the text belongs by consulting the variable 'auto-coding-file-name'. +++ ** New user option 'compilation-safety' to control safety of native code. -It's now possible to control how safe is the code generated by native +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' @@ -2298,6 +2362,7 @@ 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. @@ -2309,22 +2374,26 @@ further details. 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 have now corresponding classes. +--- +** 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. @@ -2358,17 +2427,18 @@ the backtrace and other dynamic state at the point of the error. See the Info node "(elisp) Handling Errors". +++ -** Tooltips on fringes. +** 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 'pop-up-frames' action alist entry for 'display-buffer'. +** 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. @@ -2413,11 +2483,13 @@ 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') @@ -2433,34 +2505,34 @@ 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". -Incident to this change, the function 'dnd-handle-one-url' has been -made obsolete, for it cannot take these new handlers into account. +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 compiled with '--enable-checking', you can use this to help debug -either your regexp performance problems or the regexp engine. +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. -** '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 our code if it was compiled with Emacs < 24.3. - +++ ** 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. +warnings about code that will never actually run under some conditions. +++ ** Desktop notifications are now supported on the Haiku operating system. @@ -2468,10 +2540,10 @@ 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 variable 'haiku-pass-control-tab-to-system'. +** 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 operation system. +if an Emacs frame had focus on the Haiku operating system. +++ ** New value 'if-regular' for the REPLACE argument to 'insert-file-contents'. @@ -2495,8 +2567,7 @@ 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. +"rcs2log", when starting one of these built in programs in a subprocess. +++ ** New variable 'case-symbols-as-words' affects case operations for symbols. @@ -2506,100 +2577,24 @@ 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. -+++ -** '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. +--- +** 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. +++ -** 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 user option 'safe-local-variable-directories'. -This user option names directories in which Emacs will treat all -directory-local variables as safe. - -+++ -** 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 inside 'tool-bar-map'. - -** 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'. -Emacs now can set this variable to customize the behavior of the -'transpose-sexps' function. - -+++ -*** New function 'transpose-sexps-default-function'. -The previous implementation is moved into its own function, to be -bound by 'transpose-sexps-function'. - -*** New function 'treesit-transpose-sexps'. -Tree-sitter now unconditionally sets 'transpose-sexps-function' for all -tree-sitter enabled modes. This functionality utilizes the new -'transpose-sexps-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. - -+++ -** Returned strings are never docstrings. +** 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; it is not used as a docstring. Example: +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."' but has no -docstring. Previously, that string was used as both a docstring and +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. @@ -2715,8 +2710,8 @@ default (unconditional) clause. Example: (t (say "some")) (say "goodbye")) -Such a clause will never be executed but is likely to be a mistake, -perhaps due to misplaced brackets. +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'. @@ -2730,9 +2725,9 @@ some obvious cases. Examples: (aset [3 4] 0 8) (aset "abc" 1 ?d) -Such code may have unpredictable behavior because the constants are -part of the program, not data structures generated afresh during -execution, and the compiler does not expect them to change. +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 @@ -2778,6 +2773,112 @@ 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 @@ -2811,34 +2912,12 @@ 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. -** 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. - +++ ** 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). -+++ -** '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. - +++ ** 'treesit-font-lock-rules' now accepts additional global keywords. When supplied with ':default-language LANGUAGE', rules after it will @@ -2936,7 +3015,7 @@ aforementioned functions: ** '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 +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. @@ -2953,6 +3032,12 @@ 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 --- @@ -3015,7 +3100,7 @@ functionalities to operate correctly. ** MS-Windows +++ -*** You can now opt out of following the system's Dark mode. +*** 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 @@ -3023,9 +3108,9 @@ will disregard the system's Dark mode and will always use the default Light mode. --- -*** You can now use Image-Dired even if 'convert' command is not installed. +*** 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' command is not available, Emacs on MS-Windows +'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 diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS index edeb7d3ab6c..bbf26d9515d 100644 --- a/etc/ORG-NEWS +++ b/etc/ORG-NEWS @@ -18,6 +18,9 @@ Please send Org bug reports to mailto:emacs-orgmode@gnu.org. # Here, we list the *most important* changes and changes that _likely_ # require user action for most Org mode users. # Sorted from most important to least important. +*** Arbitrary shell commands may no longer run when turning on Org mode + +This is for security reasons, to avoid running malicious commands. *** =python-mode.el (MELPA)= support in =ob-python.el= is removed @@ -177,7 +180,7 @@ Previously, when exporting to Org, all the citations and =print_bibliography= keywords, were transformed according to the chosen citation processor. -This is no loner the case. All the citation-related markup is now +This is no longer the case. All the citation-related markup is now exported as is. The previous behavior can be reverted by setting new custom option diff --git a/etc/PROBLEMS b/etc/PROBLEMS index abc675ccf48..eb7239a482a 100644 --- a/etc/PROBLEMS +++ b/etc/PROBLEMS @@ -2135,14 +2135,6 @@ with a different toolkit. For example: This produces a build which uses Athena toolkit, and disables toolkit scroll bars which could sometimes be slow. -* Runtime problems specific to PGTK build - -** SECONDARY selections don't work on Wayland. - -This is because the SECONDARY selection is not implemented by the -Wayland compositor being used. A workaround is to use other kinds of -selections. - * Runtime problems on character terminals ** The meta key does not work on xterm. @@ -3478,7 +3470,13 @@ file; for example: "/usr/local/opt/libgccjit/lib/gcc/11" "/usr/local/opt/gcc/lib/gcc/11/gcc/x86_64-apple-darwin20/11.2.0") ":")) -* Runtime problems specific to PGTK +* Runtime problems specific to PGTK build + +** SECONDARY selections don't work on Wayland. + +This is because the SECONDARY selection is not implemented by the +Wayland compositor being used. A workaround is to use other kinds of +selections. ** Giant tool bar icons are displayed in some cases diff --git a/etc/TODO b/etc/TODO index 2750e3c114d..590cd350e0e 100644 --- a/etc/TODO +++ b/etc/TODO @@ -88,6 +88,15 @@ outside of the mode they were written for. Verify the conversion by comparing the value of the keymap before converting it and after (you can see the value in 'C-h v'). +** Change documentation examples to use 'setopt' instead of 'setq' +User options are variables defined with 'defcustom', as opposed to +'defvar' or 'defconst'. It is preferable to use 'setopt' to set user +options instead of 'setq', since it will execute any ‘custom-set’ form +associated with that variable. Pick a package and make sure that it +uses 'setopt' in any examples in its documentation (doc strings, manual, +Commentary section, etc.). Note that 'setopt' is new in Emacs 29.1, so +packages that need support for earlier versions should still use 'setq'. + ** Write more tests Pick a fixed bug from the database, write a test case to make sure it stays fixed. Or pick your favorite programming major-mode, and write @@ -718,10 +727,17 @@ bar. In the mean time, it should process other messages. ** Get some major packages installed +*** Magit +This needs work on getting the relevant copyright assignments. This +task should be highly doable for anyone, but will likely require some +patience. For inspiration, see how this was done for 'use-package': +https://github.com/jwiegley/use-package/issues/282 + *** PSGML, _possibly_ ECB https://lists.gnu.org/r/emacs-devel/2007-05/msg01493.html Check the assignments file for other packages which might go in and have been -missed. +missed. (Not sure if this is still relevant in 2024. For example, both +packages seem to be unmaintained.) ** Make byte-compiler warnings smarter Byte-compiler warnings about functions that might be undefined at run @@ -910,6 +926,12 @@ restore the redirection through funcall. *** Features to be improved or missing +**** Make use of function type declaration + +The native compiler should make use of function type declarations (when +available) to propagate parameter types inside the function for better +value/type predictions. + **** Fix portable dumping so that you can redump without using -batch ***** Redumps and native compiler "preloaded" sub-folder. @@ -944,25 +966,6 @@ the tool bar is performed. Unfortunately, the tool bar (and possible other operations) always resize the frame. -**** Support 'proced' (implement 'process-attributes') -Unfortunately, a user-level process like Emacs does not have the -privileges to get information about other processes under macOS. - -There are other ways to do this: - - 1) Spawn "ps" and parse the output ("ps" has superuser privileges). - - 2) Sign Emacs as part of the distribution process. - - 3) Ask the user to self-sign Emacs, if this feature is of interest. - -Anders Lindgren has implemented -'process-attributes' for macOS, which currently only work when -running Emacs as root. - -See this article by Bozhidar Batsov for an overview of Proced: -https://emacsredux.com/blog/2013/05/02/manage-processes-with-proced/ - **** Tooltip properties Tooltip properties like the background color and font are hard-wired, even though Emacs allows a user to customize such features. @@ -1104,10 +1107,6 @@ corner and track mouse movements, but this did not work well, and was not scalable to the new Lion "resize on every window edge" behavior. [As of trunk r109635, 2012-08-15, the event loop no longer polls.] -**** mouse-avoidance-mode -(mouse-avoidance-mode 'banish) then minimize Emacs, will pop window back -up on top of all others (probably fixed in bug#17439). - **** free_frame_resources, face colors **** Numeric keysetting bug. diff --git a/etc/refcards/orgcard.tex b/etc/refcards/orgcard.tex index 3967459fd81..1860e269706 100644 --- a/etc/refcards/orgcard.tex +++ b/etc/refcards/orgcard.tex @@ -1,5 +1,5 @@ % Reference Card for Org Mode -\def\orgversionnumber{9.7.4} +\def\orgversionnumber{9.7.5} \def\versionyear{2024} % latest update \input emacsver.tex diff --git a/etc/themes/leuven-theme.el b/etc/themes/leuven-theme.el index 7ee0c8cc71e..08bd56ede70 100644 --- a/etc/themes/leuven-theme.el +++ b/etc/themes/leuven-theme.el @@ -848,7 +848,7 @@ more..." `(org-example ((,class (:foreground "blue" :background "#EEFFEE")))) `(org-footnote ((,class (:underline t :foreground "#008ED1")))) `(org-formula ((,class (:foreground "chocolate1")))) - ;; org-habit colours are thanks to zenburn + ;; org-habit colors are thanks to zenburn `(org-habit-ready-face ((t :background "#7F9F7F"))) ; ,zenburn-green `(org-habit-alert-face ((t :background "#E0CF9F" :foreground "#3F3F3F"))) ; ,zenburn-yellow-1 fg ,zenburn-bg `(org-habit-clear-face ((t :background "#5C888B"))) ; ,zenburn-blue-3 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 . */]) -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 - ]]) +]]) 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 ]])]) + # 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 . +# 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 . .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 . +# 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 . .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 . */ #include -#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 . */ 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 . */ #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 +#include + +#include +#include + +#include +#endif /* !defined HAVE_SECCOMP */ @@ -70,6 +80,15 @@ along with GNU Emacs. If not, see . */ /* 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 */ + /* 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 */ + return 0; - again: - rc = waitpid (tracee->pid, &wstatus, __WALL); - if (rc == -1 && errno == EINTR) - goto again; + free_data_error: + free (tracee->exec_data); + tracee->exec_data = NULL; + return 1; +} - if (rc < 0) - return 1; +/* 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 (!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); +static void +finish_exec (struct exec_tracee *tracee, USER_REGS_STRUCT *regs) +{ + USER_WORD size1, loader; + USER_REGS_STRUCT original; - if (rc == -1) - return 2; - else if (rc) - goto again; + size1 = tracee->data_size; - /* Retrieve the signal information and determine whether or not - the system call has completed. */ + /* Record the registers' values as they originally were. */ + memcpy (&original, regs, sizeof *regs); - 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; - -#else /* !__aarch64__ */ - - /* The system call has now completed. Get the registers again. */ - - if (ptrace (PTRACE_GETREGS, tracee->pid, NULL, - &original)) - return 3; - -#endif /* __aarch64__ */ - - *regs = original; - - /* 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; + if (ptrace ((use_seccomp_p ? PTRACE_CONT : PTRACE_SYSCALL), + tracee->pid, 0, 0)) + goto error; - return 0; - - 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; - case 1: - /* 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; + } + 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,7 +1443,347 @@ 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; + 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__ */ + + /* Now wait for the next system call to happen. */ + 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 { @@ -1448,15 +1805,28 @@ process_system_call (struct exec_tracee *tracee) ptrace (PTRACE_SETREGS, tracee->pid, NULL, ®s); #endif /* __aarch64__ */ - /* Now wait for the next system call to happen. */ - ptrace (PTRACE_SYSCALL, tracee->pid, NULL, NULL); + /* 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,9 +2105,17 @@ 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: if (ptrace (PTRACE_GETSIGINFO, pid, 0, &siginfo)) @@ -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/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 7d02e4f4834..0c9e8312b90 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -78,7 +78,7 @@ public class EmacsActivity extends Activity public static EmacsWindow focusedWindow; /* Whether or not this activity is paused. */ - private boolean isPaused; + private boolean isStopped; /* Whether or not this activity is fullscreen. */ private boolean isFullscreen; @@ -196,7 +196,7 @@ public class EmacsActivity extends Activity window.view.requestFocus (); /* If the activity is iconified, send that to the window. */ - if (isPaused) + if (isStopped) window.noticeIconified (); /* Invalidate the focus. Since attachWindow may be called from @@ -308,8 +308,13 @@ public class EmacsActivity extends Activity public final void onStop () { - timeOfLastInteraction = SystemClock.elapsedRealtime (); + /* Iconification was previously reported in onPause, but that was + misinformed, as `onStop' is the actual callback activated upon + changes in an activity's visibility. */ + isStopped = true; + EmacsWindowManager.MANAGER.noticeIconified (this); + timeOfLastInteraction = SystemClock.elapsedRealtime (); super.onStop (); } @@ -403,21 +408,11 @@ public class EmacsActivity extends Activity invalidateFocus (3); } - @Override - public final void - onPause () - { - isPaused = true; - - EmacsWindowManager.MANAGER.noticeIconified (this); - super.onPause (); - } - @Override public final void onResume () { - isPaused = false; + isStopped = false; timeOfLastInteraction = 0; EmacsWindowManager.MANAGER.noticeDeiconified (this); diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java index 82792c3fcca..1c06d394817 100644 --- a/java/org/gnu/emacs/EmacsView.java +++ b/java/org/gnu/emacs/EmacsView.java @@ -267,13 +267,6 @@ public final class EmacsView extends ViewGroup return canvas; } - public synchronized void - prepareForLayout (int wantedWidth, int wantedHeight) - { - measuredWidth = wantedWidth; - measuredHeight = wantedWidth; - } - @Override protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) @@ -773,23 +766,30 @@ public final class EmacsView extends ViewGroup /* Collect the bitmap storage; it could be large. */ Runtime.getRuntime ().gc (); - super.onDetachedFromWindow (); } @Override - public synchronized void + public void onAttachedToWindow () { - isAttachedToWindow = true; + synchronized (this) + { + isAttachedToWindow = true; - /* Dirty the bitmap, as it was destroyed when onDetachedFromWindow - was called. */ - bitmapDirty = true; + /* Dirty the bitmap, as it was destroyed when + onDetachedFromWindow was called. */ + bitmapDirty = true; - /* Now expose the view contents again. */ - EmacsNative.sendExpose (this.window.handle, 0, 0, - measuredWidth, measuredHeight); + /* Rather than unconditionally generating an exposure event upon + window attachment, avoid delivering successive Exposure + events if the size of the window has changed but is still to + be reported by clearing the measured width and height, and + requesting another layout computation. */ + measuredWidth = measuredHeight = 0; + } + + requestLayout (); super.onAttachedToWindow (); } diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 342190113b7..218c5639c89 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -74,6 +74,9 @@ public final class EmacsWindow extends EmacsHandleObject { private static final String TAG = "EmacsWindow"; + /* Whether any windows have yet been created in this session. */ + private static boolean initialWindowCreated; + private static class Coordinate { /* Integral coordinate. */ @@ -192,6 +195,14 @@ public final class EmacsWindow extends EmacsHandleObject this.parent = parent; this.overrideRedirect = overrideRedirect; + /* The initial frame should always be bound to the startup + activity. */ + if (!initialWindowCreated) + { + this.attachmentToken = -1; + initialWindowCreated = true; + } + /* Create the list of children. */ children = new ArrayList (); @@ -492,7 +503,6 @@ public final class EmacsWindow extends EmacsHandleObject /* Attach the view. */ try { - view.prepareForLayout (width, height); windowManager.addView (view, params); /* Record the window manager being used in the @@ -517,11 +527,6 @@ public final class EmacsWindow extends EmacsHandleObject public void run () { - /* Prior to mapping the view, set its measuredWidth and - measuredHeight to some reasonable value, in order to - avoid excessive bitmap dirtying. */ - - view.prepareForLayout (width, height); view.setVisibility (View.VISIBLE); if (!getDontFocusOnMap ()) diff --git a/java/org/gnu/emacs/EmacsWindowManager.java b/java/org/gnu/emacs/EmacsWindowManager.java index 03487e853fb..e4bd995f15a 100644 --- a/java/org/gnu/emacs/EmacsWindowManager.java +++ b/java/org/gnu/emacs/EmacsWindowManager.java @@ -174,6 +174,27 @@ public final class EmacsWindowManager } } + /* Do not create a multitasking activity for the initial frame, + but arrange to start EmacsActivity. */ + if (window.attachmentToken == -1) + { + intent = new Intent (EmacsService.SERVICE, + EmacsActivity.class); + intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK); + + try + { + EmacsService.SERVICE.startActivity (intent); + } + catch (Exception e) + { + Log.w (TAG, "an activity could not be started on behalf" + + " of the mapped default window " + window.handle); + } + + return; + } + intent = new Intent (EmacsService.SERVICE, EmacsMultitaskActivity.class); @@ -205,14 +226,22 @@ public final class EmacsWindowManager window.attachmentToken = token; intent.putExtra (ACTIVITY_TOKEN, token); - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) - EmacsService.SERVICE.startActivity (intent); - else + try { - /* Specify the desired window size. */ - options = ActivityOptions.makeBasic (); - options.setLaunchBounds (window.getGeometry ()); - EmacsService.SERVICE.startActivity (intent, options.toBundle ()); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) + EmacsService.SERVICE.startActivity (intent); + else + { + /* Specify the desired window size. */ + options = ActivityOptions.makeBasic (); + options.setLaunchBounds (window.getGeometry ()); + EmacsService.SERVICE.startActivity (intent, options.toBundle ()); + } + } + catch (Exception e) + { + Log.w (TAG, "an activity could not be started on behalf" + + " of a mapped window, " + window.handle); } pruneWindows (); diff --git a/java/res/drawable/emacs_background.xml b/java/res/drawable/emacs_background.xml index 448ca48d1cb..c6b6decc3b0 100644 --- a/java/res/drawable/emacs_background.xml +++ b/java/res/drawable/emacs_background.xml @@ -21,22 +21,26 @@ along with GNU Emacs. If not, see . --> xmlns:aapt="http://schemas.android.com/aapt" android:width="108dp" android:height="108dp" - android:viewportWidth="512" - android:viewportHeight="512"> - + android:viewportWidth="108" + android:viewportHeight="108"> + - + - + + diff --git a/java/res/drawable/emacs_foreground.xml b/java/res/drawable/emacs_foreground.xml index d4d71f8e29a..06a03240e28 100644 --- a/java/res/drawable/emacs_foreground.xml +++ b/java/res/drawable/emacs_foreground.xml @@ -21,19 +21,13 @@ along with GNU Emacs. If not, see . --> xmlns:aapt="http://schemas.android.com/aapt" android:width="108dp" android:height="108dp" - android:viewportWidth="512" - android:viewportHeight="512"> - - - + android:viewportWidth="108" + android:viewportHeight="108"> + diff --git a/java/res/mipmap-v26/emacs_icon.xml b/java/res/mipmap-v26/emacs_icon.xml index f0a8df92846..5b720e8210f 100644 --- a/java/res/mipmap-v26/emacs_icon.xml +++ b/java/res/mipmap-v26/emacs_icon.xml @@ -20,4 +20,5 @@ along with GNU Emacs. If not, see . --> + 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. */ + - S-1-5-32-545 (group "Users") + Cf. + 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 @@ -60,10 +59,6 @@ #include #include -#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 +#include #include #include #include #include -#if USE_C_LOCALE && HAVE_STRFTIME_L -# include -#endif - #if (defined __NetBSD__ || defined __sun) && REQUIRE_GNUISH_STRFTIME_AM_PM -# include # include "localename.h" +#elif defined _WIN32 && !defined __CYGWIN__ +# include #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 -/* 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) + 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 { - 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)) - { - 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) + 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 { - 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)) - { - 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/ChangeLog.1 b/lisp/ChangeLog.1 index 49296aaf3a7..037bb41092b 100644 --- a/lisp/ChangeLog.1 +++ b/lisp/ChangeLog.1 @@ -570,7 +570,7 @@ 1986-01-18 Richard M. Stallman (rms@prep) - * doctor.el: Fix typo "symtoms". + * doctor.el: Fix typo for "symptoms". 1986-01-10 Richard Mlynarik (mly@prep) 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/cedet/semantic/db-find.el b/lisp/cedet/semantic/db-find.el index 920588abf89..586cb1cf23b 100644 --- a/lisp/cedet/semantic/db-find.el +++ b/lisp/cedet/semantic/db-find.el @@ -622,7 +622,7 @@ Included databases are filtered based on `semanticdb-find-default-throttle'." ;; INCLUDETAG should have some way to reference where it came ;; from! If not, TABLE should provide the way. Each time we ;; look up a tag, we may need to find it in some relative way - ;; and must set our current buffer eto the origin of includetag + ;; and must set our current buffer to the origin of includetag ;; or nothing may work. (setq originfiledir (cond ((semantic-tag-file-name includetag) 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 + ;; " " #'completion-preview-insert-word + ;; " " #'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/completion.el b/lisp/completion.el index 6c758e56eab..fff431eaf69 100644 --- a/lisp/completion.el +++ b/lisp/completion.el @@ -992,7 +992,7 @@ Each symbol is bound to a single completion entry.") ;; Updating the database ;;----------------------------------------------- ;; -;; These are the internal functions used to update the datebase +;; These are the internal functions used to update the database ;; ;; (defvar completion-to-accept nil diff --git a/lisp/dired.el b/lisp/dired.el index 0adf06f471e..33b79cbef85 100644 --- a/lisp/dired.el +++ b/lisp/dired.el @@ -511,7 +511,8 @@ Possible non-nil values: * `cycle': when moving from the last/first visible line, cycle back to the first/last visible line. * `bounded': don't move up/down if the current line is the - first/last visible line." + first/last visible line. +Any other non-nil value is treated as `bounded'." :type '(choice (const :tag "Move to any line" nil) (const :tag "Cycle through non-empty lines" cycle) (const :tag "Stop on last/first non-empty line" bounded)) @@ -2886,7 +2887,7 @@ is controlled by `dired-movement-style'." (point-max)))) (setq wrapped t)) ;; `bounded': go back to the last non-empty line. - ((eq dired-movement-style 'bounded) + (dired-movement-style ; Either 'bounded or anything else non-nil. (while (and (dired-between-files) (not (zerop arg))) (funcall jumpfun (- moving-down)) ;; Point not moving means infinite loop. @@ -5182,7 +5183,7 @@ Interactively with prefix argument, read FILE-NAME." (dired-goto-file file)) ;; Toggle omitting, if it is on, and try again. (when (bound-and-true-p dired-omit-mode) - (dired-omit-mode) + (dired-omit-mode -1) (dired-goto-file file))))))))) ;;;###autoload 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/editorconfig-conf-mode.el b/lisp/editorconfig-conf-mode.el index 3102c3d6581..6afbb42865e 100644 --- a/lisp/editorconfig-conf-mode.el +++ b/lisp/editorconfig-conf-mode.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team +;; Package: editorconfig ;; See ;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or diff --git a/lisp/editorconfig-core-handle.el b/lisp/editorconfig-core-handle.el index b8570ac5c6a..73c26288287 100644 --- a/lisp/editorconfig-core-handle.el +++ b/lisp/editorconfig-core-handle.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team +;; Package: editorconfig ;; See ;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or @@ -126,9 +127,9 @@ If HANDLE is nil return nil." If HANDLE is nil return nil." (when handle - (let ((hash (make-hash-table)) - (file (file-relative-name file (editorconfig-core-handle-path - handle)))) + (let* ((hash (make-hash-table)) + (dir (file-name-directory (editorconfig-core-handle-path handle))) + (file (file-relative-name file dir))) (dolist (section (editorconfig-core-handle-sections handle)) (cl-loop for (key . value) in (editorconfig-core-handle-section-get-properties section file) do (puthash (intern key) value hash))) @@ -142,7 +143,11 @@ This function is a fnmatch with a few modification for EditorConfig usage." (if (string-match-p "/" pattern) (let ((pattern (replace-regexp-in-string "\\`/" "" pattern))) (editorconfig-fnmatch-p name pattern)) - (editorconfig-fnmatch-p (file-name-nondirectory name) pattern))) + ;; The match is not "anchored" so it can be either in the current dir or + ;; in a subdir. Contrary to Zsh patterns, editorconfig's `**/foo' does + ;; not match `foo', so we need to split the problem into two matches. + (or (editorconfig-fnmatch-p name pattern) + (editorconfig-fnmatch-p name (concat "**/" pattern))))) (defun editorconfig-core-handle--parse-file (conf) "Parse EditorConfig file CONF. diff --git a/lisp/editorconfig-core.el b/lisp/editorconfig-core.el index 8183ff6298c..3d7ea88917c 100644 --- a/lisp/editorconfig-core.el +++ b/lisp/editorconfig-core.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team +;; Package: editorconfig ;; See ;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or diff --git a/lisp/editorconfig-fnmatch.el b/lisp/editorconfig-fnmatch.el index 397e424a6f7..8d6e9bb9071 100644 --- a/lisp/editorconfig-fnmatch.el +++ b/lisp/editorconfig-fnmatch.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team +;; Package: editorconfig ;; See ;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or diff --git a/lisp/editorconfig-tools.el b/lisp/editorconfig-tools.el index 512dd67f56f..b9bd3798647 100644 --- a/lisp/editorconfig-tools.el +++ b/lisp/editorconfig-tools.el @@ -3,6 +3,7 @@ ;; Copyright (C) 2011-2024 Free Software Foundation, Inc. ;; Author: EditorConfig Team +;; Package: editorconfig ;; See ;; https://github.com/editorconfig/editorconfig-emacs/graphs/contributors or diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el index 529521ca610..e85b8f1f716 100644 --- a/lisp/emacs-lisp/bytecomp.el +++ b/lisp/emacs-lisp/bytecomp.el @@ -3833,7 +3833,7 @@ This assumes the function has the `important-return-value' property." (defun byte-compile-free-vars-warn (arg var &optional assignment) "Warn if symbol VAR refers to a free variable. VAR must not be lexically bound. -ARG is a position argument, used by byte-compile-warn-x. +ARG is a position argument, used by `byte-compile-warn-x'. If optional argument ASSIGNMENT is non-nil, this is treated as an assignment (i.e. `setq')." (unless (or (not (byte-compile-warning-enabled-p 'free-vars var)) @@ -5489,7 +5489,7 @@ OP and OPERAND are as passed to `byte-compile-out'." (defun byte-compile-out (op &optional operand) "Push the operation onto `byte-compile-output'. OP is an opcode, a symbol. OPERAND is either nil or a number or -a one-element list of a lisp form." +a one-element list of a Lisp form." (when (and (consp operand) (null (cdr operand))) (setq operand (byte-run-strip-symbol-positions operand))) (push (cons op operand) byte-compile-output) diff --git a/lisp/emacs-lisp/checkdoc.el b/lisp/emacs-lisp/checkdoc.el index c22dfb2eb26..d81eba7e85c 100644 --- a/lisp/emacs-lisp/checkdoc.el +++ b/lisp/emacs-lisp/checkdoc.el @@ -262,14 +262,15 @@ with these words enabled." ;;;###autoload(put 'checkdoc-ispell-list-words 'safe-local-variable #'list-of-strings-p) (defcustom checkdoc-max-keyref-before-warn nil - "If non-nil, number of \\\\=[command-to-keystroke] tokens allowed in a doc string. -Any more than this and a warning is generated suggesting that the construct -\\\\={mapvar} be used instead. If the value is nil, never warn. + "Maximum number of \\\\=[command-to-keystroke] tokens allowed in a doc string. -It used to not be practical to use `\\\\=[...]' very many times, -because display of the documentation string would become slow. -This is not an issue on modern machines, unless you have -thousands of substitutions." +Any more than this and a warning is generated suggesting that the +construct \\\\={mapvar} be used instead. If the value is nil, never +warn. + +It used to be impractical to use `\\\\=[...]' very many times, because +display of the documentation string would become slow. This is not an +issue on modern machines, unless you have thousands of substitutions." :type '(choice (const nil) integer) :version "28.1") @@ -289,6 +290,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. @@ -307,11 +309,12 @@ problem discovered. This is useful for adding additional checks.") (defvar checkdoc-diagnostic-buffer "*Style Warnings*" "Name of warning message buffer.") -(defcustom checkdoc-verb-check-experimental-flag t +(defcustom checkdoc-verb-check-experimental-flag nil "Non-nil means to attempt to check the voice of the doc string. This check keys off some words which are commonly misused. See the variable `checkdoc-common-verbs-wrong-voice' if you wish to add your own." - :type 'boolean) + :type 'boolean + :version "31.1") ;;;###autoload(put 'checkdoc-verb-check-experimental-flag 'safe-local-variable #'booleanp) (defvar checkdoc-generate-compile-warnings-flag nil @@ -345,6 +348,7 @@ See Info node `(elisp) Documentation Tips' for background." ;; (setq checkdoc--argument-missing-flag nil) ; optional ;; (setq checkdoc--disambiguate-symbol-flag nil) ; optional ;; (setq checkdoc--interactive-docstring-flag nil) ; optional +;; (setq checkdoc-permit-comma-termination-flag t) ; optional ;; (setq checkdoc-verb-check-experimental-flag nil) ;; Then use `M-x find-dired' ("-name '*.el'") and `M-x checkdoc-dired' @@ -1084,7 +1088,7 @@ Optional argument TAKE-NOTES causes all errors to be logged." Evaluation is done first so the form will be read before the documentation is checked. If there is a documentation error, then the display of what was evaluated will be overwritten by the diagnostic message." - (interactive) + (interactive nil emacs-lisp-mode) (call-interactively #'eval-defun) (checkdoc-defun)) @@ -1095,7 +1099,7 @@ Call `error' if the doc string has problems. If NO-ERROR is non-nil, then do not call error, but call `message' instead. If the doc string passes the test, then check the function for rogue white space at the end of each line." - (interactive) + (interactive nil emacs-lisp-mode) (save-excursion (beginning-of-defun) (when (checkdoc--next-docstring) @@ -2133,7 +2137,7 @@ Examples of recognized abbreviations: \"e.g.\", \"i.e.\", \"cf.\"." (seq (any "cC") "f") ; cf. (seq (any "eE") ".g") ; e.g. (seq (any "iI") "." (any "eE")) ; i.e. - "a.k.a" "etc" "vs" "N.B" + "a.k.a" "etc" "vs" "N.B" "U.S" ;; Some non-standard or less common ones that we ;; might as well accept. "Inc" "Univ" "misc" "resp") @@ -2472,25 +2476,33 @@ Code:, and others referenced in the style guide." (setq err (or - ;; * A footer. Not compartmentalized from lm-verify: too bad. - ;; The following is partially clipped from lm-verify + ;; * Library footer (save-excursion (goto-char (point-max)) - (if (not (re-search-backward - ;; This should match the requirement in - ;; `package-buffer-info'. - (concat "^;;; " (regexp-quote (concat fn fe)) " ends here") - nil t)) - (if (checkdoc-y-or-n-p "No identifiable footer! Add one?") - (progn - (goto-char (point-max)) - (insert "\n(provide '" fn ")\n\n;;; " fn fe " ends here\n")) - (checkdoc-create-error - (format "The footer should be: (provide '%s)\\n;;; %s%s ends here" - fn fn fe) - ;; The buffer may be empty. - (max (point-min) (1- (point-max))) - (point-max))))) + (let* ((footer-line (lm-package-needs-footer-line))) + (if (not (re-search-backward + ;; This should match the requirement in + ;; `package-buffer-info'. + (if footer-line + (concat "^;;; " (regexp-quote (concat fn fe)) " ends here") + (concat "\n(provide '" fn ")\n")) + nil t)) + (if (checkdoc-y-or-n-p (if footer-line + "No identifiable footer! Add one?" + "No `provide' statement! Add one?")) + (progn + (goto-char (point-max)) + (insert (if footer-line + (concat "\n(provide '" fn ")\n\n;;; " fn fe " ends here\n") + (concat "\n(provide '" fn ")\n")))) + (checkdoc-create-error + (if footer-line + (format "The footer should be: (provide '%s)\\n;;; %s%s ends here" + fn fn fe) + (format "The footer should be: (provide '%s)\\n" fn)) + ;; The buffer may be empty. + (max (point-min) (1- (point-max))) + (point-max)))))) err)) ;; The below checks will not return errors if the user says NO @@ -2531,14 +2543,18 @@ Code:, and others referenced in the style guide." "Search between BEG and END for a style error with message text. Optional arguments BEG and END represent the boundary of the check. The default boundary is the entire buffer." - (let ((e nil) - (type nil)) + (let ((e nil)) (if (not (or beg end)) (setq beg (point-min) end (point-max))) (goto-char beg) - (while (setq type (checkdoc-message-text-next-string end)) + (while-let ((type (checkdoc-message-text-next-string end))) (setq e (checkdoc-message-text-engine type))) e)) +(defvar checkdoc--warning-function-re + (rx (or "display-warning" "org-display-warning" + "warn" "lwarn" + "message-box"))) + (defun checkdoc-message-text-next-string (end) "Move cursor to the next checkable message string after point. Return the message classification. @@ -2551,6 +2567,7 @@ Argument END is the maximum bounds to search in." (group (or (seq (* (or wordchar (syntax symbol))) "error") + (regexp checkdoc--warning-function-re) (seq (* (or wordchar (syntax symbol))) (or "y-or-n-p" "yes-or-no-p") (? "-with-timeout")) @@ -2558,8 +2575,13 @@ Argument END is the maximum bounds to search in." (+ (any "\n\t "))) end t)) (let* ((fn (match-string 1)) - (type (cond ((string-match "error" fn) - 'error) + (type (cond ((string-match "error" fn) + 'error) + ((string-match (rx bos + (regexp checkdoc--warning-function-re) + eos) + fn) + 'warning) (t 'y-or-n-p)))) (if (string-match "checkdoc-autofix-ask-replace" fn) (progn (forward-sexp 2) @@ -2629,30 +2651,33 @@ should not end with a period, and should start with a capital letter. The function `y-or-n-p' has similar constraints. Argument TYPE specifies the type of question, such as `error' or `y-or-n-p'." ;; If type is nil, then attempt to derive it. - (if (not type) - (save-excursion - (up-list -1) - (if (looking-at "(format") - (up-list -1)) - (setq type - (cond ((looking-at "(error") - 'error) - (t 'y-or-n-p))))) + (unless type + (save-excursion + (up-list -1) + (when (looking-at "(format") + (up-list -1)) + (setq type + (cond ((looking-at "(error") + 'error) + ((looking-at + (rx "(" (regexp checkdoc--warning-function-re) + (syntax whitespace))) + 'warning) + (t 'y-or-n-p))))) (let ((case-fold-search nil)) (or ;; From the documentation of the symbol `error': ;; In Emacs, the convention is that error messages start with a capital ;; letter but *do not* end with a period. Please follow this convention ;; for the sake of consistency. - (if (and (checkdoc--error-bad-format-p) - (not (checkdoc-autofix-ask-replace - (match-beginning 1) (match-end 1) - "Capitalize your message text?" - (capitalize (match-string 1)) - t))) - (checkdoc-create-error "Messages should start with a capital letter" - (match-beginning 1) (match-end 1)) - nil) + (when (and (checkdoc--error-bad-format-p) + (not (checkdoc-autofix-ask-replace + (match-beginning 1) (match-end 1) + "Capitalize your message text?" + (capitalize (match-string 1)) + t))) + (checkdoc-create-error "Messages should start with a capital letter" + (match-beginning 1) (match-end 1))) ;; In general, sentences should have two spaces after the period. (checkdoc-sentencespace-region-engine (point) (save-excursion (forward-sexp 1) @@ -2662,19 +2687,18 @@ Argument TYPE specifies the type of question, such as `error' or `y-or-n-p'." (save-excursion (forward-sexp 1) (point))) ;; Here are message type specific questions. - (if (and (eq type 'error) - (save-excursion (forward-sexp 1) - (forward-char -2) - (looking-at "\\.")) - (not (checkdoc-autofix-ask-replace (match-beginning 0) - (match-end 0) - "Remove period from error?" - "" - t))) - (checkdoc-create-error - "Error messages should *not* end with a period" - (match-beginning 0) (match-end 0)) - nil) + (when (and (eq type 'error) + (save-excursion (forward-sexp 1) + (forward-char -2) + (looking-at "\\.")) + (not (checkdoc-autofix-ask-replace (match-beginning 0) + (match-end 0) + "Remove period from error?" + "" + t))) + (checkdoc-create-error + "Error messages should *not* end with a period" + (match-beginning 0) (match-end 0))) ;; From `(elisp) Programming Tips': "A question asked in the ;; minibuffer with `yes-or-no-p' or `y-or-n-p' should start with ;; a capital letter and end with '?'." @@ -2827,7 +2851,7 @@ function called to create the messages." ;;;###autoload (defun checkdoc-package-keywords () "Find package keywords that aren't in `finder-known-keywords'." - (interactive) + (interactive nil emacs-lisp-mode) (require 'finder) (let ((unrecognized-keys (cl-remove-if diff --git a/lisp/emacs-lisp/comp-run.el b/lisp/emacs-lisp/comp-run.el index 8e08eca7442..a659d7f68b7 100644 --- a/lisp/emacs-lisp/comp-run.el +++ b/lisp/emacs-lisp/comp-run.el @@ -195,7 +195,7 @@ processes from `comp-async-compilations'" (if native-comp-async-report-warnings-errors (let ((warning-suppress-types (if (eq native-comp-async-report-warnings-errors 'silent) - (cons '(comp) warning-suppress-types) + (cons '(native-compiler) warning-suppress-types) warning-suppress-types)) (regexp (if (eq native-comp-async-warnings-errors-kind 'all) "^.*?\\(?:Error\\|Warning\\): .*$" @@ -211,7 +211,7 @@ processes from `comp-async-compilations'" (accept-process-output process) (goto-char (or comp-last-scanned-async-output (point-min))) (while (re-search-forward regexp nil t) - (display-warning 'comp (match-string 0))) + (display-warning 'native-compiler (match-string 0))) (setq comp-last-scanned-async-output (point-max))))) (accept-process-output process))) @@ -446,8 +446,8 @@ bytecode definition was not changed in the meantime)." (setf comp-files-queue (append comp-files-queue `((,file . ,load))) added-something t) - (display-warning 'comp - (format "No write access for %s skipping." + (display-warning 'native-compiler + (format "Cannot write %s; skipping." out-filename))))))) ;; Perhaps nothing passed `native--compile-async-skip-p'? (when (and added-something diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index bde176310a8..ce339a92edc 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el @@ -75,7 +75,9 @@ This is intended for debugging the compiler itself. 1 emit debug symbols. 2 emit debug symbols and dump pseudo C code. 3 emit debug symbols and dump: pseudo C code, GCC intermediate - passes and libgccjit log file." + passes and libgccjit log file. +When generated, the pseudo C code is deposited in the same directory +as the corresponding .eln file." :type 'natnum :safe #'natnump :version "29.1") @@ -790,21 +792,29 @@ clashes." :byte-func byte-code))) (maphash #'comp--intern-func-in-ctxt byte-to-native-lambdas-h))) -(cl-defmethod comp--spill-lap-function ((form list)) - "Byte-compile FORM, spilling data from the byte compiler." - (unless (memq (car-safe form) '(lambda closure)) - (signal 'native-compiler-error - '("Cannot native-compile, form is not a lambda or closure"))) +(defun comp--spill-lap-single-function (function) + "Byte-compile FUNCTION, spilling data from the byte compiler." (unless (comp-ctxt-output comp-ctxt) (setf (comp-ctxt-output comp-ctxt) (make-temp-file "comp-lambda-" nil ".eln"))) - (let* ((byte-code (byte-compile form)) + (let* ((byte-code (byte-compile function)) (c-name (comp-c-func-name "anonymous-lambda" "F"))) - (setf (comp-ctxt-top-level-forms comp-ctxt) - (list (make-byte-to-native-func-def :name '--anonymous-lambda - :c-name c-name - :byte-func byte-code))) - (maphash #'comp--intern-func-in-ctxt byte-to-native-lambdas-h))) + (setf (comp-ctxt-top-level-forms comp-ctxt) + (list (make-byte-to-native-func-def :name '--anonymous-lambda + :c-name c-name + :byte-func byte-code))) + (maphash #'comp--intern-func-in-ctxt byte-to-native-lambdas-h))) + +(cl-defmethod comp--spill-lap-function ((form list)) + "Byte-compile FORM, spilling data from the byte compiler." + (unless (eq (car-safe form) 'lambda) + (signal 'native-compiler-error + '("Cannot native-compile, form is not a lambda"))) + (comp--spill-lap-single-function form)) + +(cl-defmethod comp--spill-lap-function ((fun interpreted-function)) + "Spill data from the byte compiler for the interpreted-function FUN." + (comp--spill-lap-single-function fun)) (defun comp--intern-func-in-ctxt (_ obj) "Given OBJ of type `byte-to-native-lambda', create a function in `comp-ctxt'." @@ -1055,7 +1065,7 @@ If DST-N is specified, use it; otherwise assume it to be the current slot." "Set constant VAL to current slot." (comp--add-const-to-relocs val) ;; Leave relocation index nil on purpose, will be fixed-up in final - ;; by `comp-finalize-relocs'. + ;; by `comp--finalize-relocs'. (comp--emit `(setimm ,(comp--slot) ,val))) (defun comp--make-curr-block (block-name entry-sp &optional addr) @@ -2792,7 +2802,7 @@ Return t if something was changed." finally (when (= i 100) (display-warning - 'comp + 'native-compiler (format "fwprop pass jammed into %s?" (comp-func-name f)))) (comp-log (format "Propagation run %d times\n" i) 2)) (comp--rewrite-non-locals) @@ -3575,14 +3585,13 @@ Search happens in `native-comp-eln-load-path'." ;;;###autoload (defun native-compile (function-or-file &optional output) "Compile FUNCTION-OR-FILE into native code. -This is the synchronous entry-point for the Emacs Lisp native -compiler. FUNCTION-OR-FILE is a function symbol, a form, or the -filename of an Emacs Lisp source file. If OUTPUT is non-nil, use -it as the filename for the compiled object. If FUNCTION-OR-FILE -is a filename, if the compilation was successful return the -filename of the compiled object. If FUNCTION-OR-FILE is a -function symbol or a form, if the compilation was successful -return the compiled function." +This is the synchronous entry-point for the Emacs Lisp native compiler. +FUNCTION-OR-FILE is a function symbol, a form, an interpreted-function, +or the filename of an Emacs Lisp source file. If OUTPUT is non-nil, use +it as the filename for the compiled object. If FUNCTION-OR-FILE is a +filename, if the compilation was successful return the filename of the +compiled object. If FUNCTION-OR-FILE is a function symbol or a form, if +the compilation was successful return the compiled function." (declare (ftype (function ((or string symbol) &optional string) (or native-comp-function string)))) (comp--native-compile function-or-file nil output)) diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index ba0f8bad393..944a74a91ee 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el @@ -524,7 +524,8 @@ on if the hook has explicitly disabled it. (progn (put ',global-mode 'globalized-minor-mode t) :autoload-end - (defvar-local ,MODE-major-mode nil)) + (defvar-local ,MODE-major-mode nil) + ,@(when predicate `((defvar ,MODE-predicate)))) ;; The actual global minor-mode (define-minor-mode ,global-mode ,(concat (format "Toggle %s in all buffers.\n" pretty-name) diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el index 381b7964a35..deebe5109bd 100644 --- a/lisp/emacs-lisp/edebug.el +++ b/lisp/emacs-lisp/edebug.el @@ -4577,10 +4577,9 @@ With prefix argument, make it a temporary breakpoint." (add-hook 'called-interactively-p-functions #'edebug--called-interactively-skip) (defun edebug--called-interactively-skip (i frame1 frame2) - (when (and (memq (car-safe (nth 1 frame1)) '(lambda closure)) + (when (and (interpreted-function-p (nth 1 frame1)) ;; Lambda value with no arguments. - (null (nth (if (eq (car-safe (nth 1 frame1)) 'lambda) 1 2) - (nth 1 frame1))) + (null (aref (nth 1 frame1) 0)) (memq (nth 1 frame2) '(edebug-enter edebug-default-enter))) ;; `edebug-enter' calls itself on its first invocation. (let ((s 1)) diff --git a/lisp/emacs-lisp/eldoc.el b/lisp/emacs-lisp/eldoc.el index 24afd03fbe6..417c0145be4 100644 --- a/lisp/emacs-lisp/eldoc.el +++ b/lisp/emacs-lisp/eldoc.el @@ -462,7 +462,7 @@ documentation-displaying frontends. For example, KEY can be: The additional KEY `:origin' is always added by ElDoc, its VALUE being the member of `eldoc-documentation-functions' where -DOCSTRING originated. `eldoc-display-functions' may use this +DOCSTRING originated. `eldoc-display-functions' may use this information to organize display of multiple docstrings. Finally, major modes should modify this hook locally, for diff --git a/lisp/emacs-lisp/find-func.el b/lisp/emacs-lisp/find-func.el index 411602ef166..ce783983b77 100644 --- a/lisp/emacs-lisp/find-func.el +++ b/lisp/emacs-lisp/find-func.el @@ -125,7 +125,7 @@ should insert the feature name." (defcustom find-ert-deftest-regexp "(ert-deftest +'%s" - "The regexp used to search for an ert-deftest definition. + "The regexp used to search for an `ert-deftest' definition. Note it must contain a `%s' at the place where `format' should insert the feature name." :type 'regexp diff --git a/lisp/emacs-lisp/lisp-mnt.el b/lisp/emacs-lisp/lisp-mnt.el index f111a77663c..3c7f047d203 100644 --- a/lisp/emacs-lisp/lisp-mnt.el +++ b/lisp/emacs-lisp/lisp-mnt.el @@ -1,7 +1,6 @@ ;;; lisp-mnt.el --- utility functions for Emacs Lisp maintainers -*- lexical-binding:t -*- -;; Copyright (C) 1992, 1994, 1997, 2000-2024 Free Software Foundation, -;; Inc. +;; Copyright (C) 1992-2024 Free Software Foundation, Inc. ;; Author: Eric S. Raymond ;; Maintainer: emacs-devel@gnu.org @@ -71,8 +70,8 @@ ;; ;; Eric S. Raymond ;; ;; * Maintainer line --- should be a single name/address as in the Author -;; line, or an address only. If there is no maintainer -;; line, the person(s) in the Author field are presumed to be it. +;; line, or an address only. If there is no maintainer line, the person(s) in +;; the Author field are presumed to be it. ;; The idea behind these two fields is to be able to write a Lisp function ;; that does "send mail to the author" without having to mine the name out by ;; hand. Please be careful about surrounding the network address with <> if @@ -106,8 +105,10 @@ ;; * Code line --- exists so Lisp can know where commentary and/or ;; change-log sections end. ;; -;; * Footer line --- marks end-of-file so it can be distinguished from -;; an expanded formfeed or the results of truncation. +;; * Footer line --- marks end-of-file so it can be distinguished +;; from an expanded formfeed or the results of truncation. This is +;; required for a package to be installable by package.el in Emacs 29.1 +;; or earlier, but is optional in later versions. ;;; Code: @@ -467,6 +468,29 @@ package version (a string)." (lm--prepare-package-dependencies (package-read-from-string (mapconcat #'identity require-lines " ")))))) +(defun lm-package-needs-footer-line (&optional file) + "Return non-nil if package in current buffer needs a footer line. + +Footer lines (sometimes referred to as \"terminating comments\") look +like this: + + ;;; some-cool-package.el ends here + +Such lines are required for a package to be installable by package.el in +Emacs 29.1 or earlier, but are optional in later versions. If the +package depends on a version of Emacs where package.el requires such +comments, or if no version requirement is specified, return non-nil. + +If optional argument FILE is non-nil, use that file instead of the +current buffer." + (lm-with-file file + ;; Starting in Emacs 30.1, avoid warning if the minimum Emacs + ;; version is specified as 30.1 or later. + (let ((min-emacs (cadar (seq-filter (lambda (x) (eq (car x) 'emacs)) + (lm-package-requires))))) + (or (null min-emacs) + (version< min-emacs "30.1"))))) + (defun lm-keywords (&optional file) "Return the keywords given in file FILE, or current buffer if FILE is nil. The return is a `downcase'-ed string, or nil if no keywords @@ -533,7 +557,6 @@ absent, return nil." (if (and page (string-match (rx bol "<" (+ nonl) ">" eol) page)) (substring page 1 -1) page))) -(defalias 'lm-homepage #'lm-website) ; for backwards-compatibility ;;; Verification and synopses @@ -552,7 +575,7 @@ says display \"OK\" in temp buffer for files that have no problems. Optional argument VERBOSE specifies verbosity level. Optional argument NON-FSF-OK if non-nil means a non-FSF copyright notice is allowed." - ;; FIXME: Make obsolete in favor of checkdoc? + (declare (obsolete checkdoc "31.1")) (interactive (list nil nil t)) (let* ((ret (and verbose "Ok")) name) @@ -593,11 +616,12 @@ copyright notice is allowed." ((not (lm-code-start)) "Can't find a `Code' section marker") ((progn - (goto-char (point-max)) - (not - (re-search-backward - (rx bol ";;; " (regexp name) " ends here") - nil t))) + (when (lm-package-needs-footer-line) + (goto-char (point-max)) + (not + (re-search-backward + (rx bol ";;; " (regexp name) " ends here") + nil t)))) "Can't find the footer line") ((not (and (lm-copyright-mark) (lm-crack-copyright))) "Can't find a valid copyright notice") @@ -663,6 +687,7 @@ Prompts for bug subject TOPIC. Leaves you in a mail buffer." (define-obsolete-function-alias 'lm-code-mark #'lm-code-start "30.1") (define-obsolete-function-alias 'lm-commentary-mark #'lm-commentary-start "30.1") (define-obsolete-function-alias 'lm-history-mark #'lm-history-start "30.1") +(define-obsolete-function-alias 'lm-homepage #'lm-website "31.1") (provide 'lisp-mnt) diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el index bb4797cac8b..4524eccc7ef 100644 --- a/lisp/emacs-lisp/macroexp.el +++ b/lisp/emacs-lisp/macroexp.el @@ -37,7 +37,7 @@ most deeply nested form. Normally a form is manually pushed onto the list at the beginning of `byte-compile-form', etc., and manually popped off at its end. This is to preserve the data in it in the event of a -condition-case handling a signaled error.") +`condition-case' handling a signaled error.") (defmacro macroexp--with-extended-form-stack (expr &rest body) "Evaluate BODY with EXPR pushed onto `byte-compile-form-stack'." diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index fac824d44a4..7cae8d68bc0 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -1161,6 +1161,7 @@ Signal an error if the entire string was not used." (declare-function lm-keywords-list "lisp-mnt" (&optional file)) (declare-function lm-maintainers "lisp-mnt" (&optional file)) (declare-function lm-authors "lisp-mnt" (&optional file)) +(declare-function lm-package-needs-footer-line "lisp-mnt" (&optional file)) (defun package-buffer-info () "Return a `package-desc' describing the package in the current buffer. @@ -1174,23 +1175,18 @@ boundaries." (let ((file-name (match-string-no-properties 1)) (desc (match-string-no-properties 2)) (start (line-beginning-position))) + (require 'lisp-mnt) ;; This warning was added in Emacs 27.1, and should be removed at ;; the earliest in version 31.1. The idea is to phase out the ;; requirement for a "footer line" without unduly impacting users ;; on earlier Emacs versions. See Bug#26490 for more details. (unless (search-forward (concat ";;; " file-name ".el ends here") nil 'move) - ;; Starting in Emacs 30.1, avoid warning if the minimum Emacs - ;; version is specified as 30.1 or later. - (let ((min-emacs (cadar (seq-filter (lambda (x) (eq (car x) 'emacs)) - (lm-package-requires))))) - (when (or (null min-emacs) - (version< min-emacs "30.1")) - (lwarn '(package package-format) :warning - "Package lacks a terminating comment")))) + (when (lm-package-needs-footer-line) + (lwarn '(package package-format) :warning + "Package lacks a terminating comment"))) ;; Try to include a trailing newline. (forward-line) (narrow-to-region start (point)) - (require 'lisp-mnt) ;; Use some headers we've invented to drive the process. (let* (;; Prefer Package-Version; if defined, the package author ;; probably wants us to use it. Otherwise try Version. diff --git a/lisp/emacs-lisp/rmc.el b/lisp/emacs-lisp/rmc.el index 8aa68f13c54..e51396ed8e6 100644 --- a/lisp/emacs-lisp/rmc.el +++ b/lisp/emacs-lisp/rmc.el @@ -182,6 +182,9 @@ Usage example: (read-multiple-choice--short-answers prompt choices help-string show-help))) +(declare-function touch-screen-scroll "touch-screen.el") +(declare-function touch-screen-pinch "touch-screen.el") + (defun read-multiple-choice--short-answers (prompt choices help-string show-help) (let* ((dialog-p (use-dialog-box-p)) (prompt-choices @@ -228,7 +231,10 @@ Usage example: (when (setq command (let ((current-key-remap-sequence (vector tchar))) - (touch-screen-translate-touch nil))) + ;; Provide an empty prompt so that it may + ;; not repeatedly display and/or disable + ;; the on-screen keyboard, or move point. + (touch-screen-translate-touch ""))) (setq command (if (> (length command) 0) (aref command 0) nil)) @@ -243,9 +249,9 @@ Usage example: ;; Respond to scroll and pinch events as if RMC were ;; not in progress. ((eq (car-safe command) 'touchscreen-scroll) - (funcall #'touch-screen-scroll command)) + (touch-screen-scroll command)) ((eq (car-safe command) 'touchscreen-pinch) - (funcall #'touch-screen-pinch command)) + (touch-screen-pinch command)) ;; Prevent other touchscreen-generated events from ;; reaching the default conditional. ((memq (or (and (symbolp command) command) diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el index 699be767ee7..e725c490aba 100644 --- a/lisp/emacs-lisp/subr-x.el +++ b/lisp/emacs-lisp/subr-x.el @@ -158,20 +158,22 @@ removed." (string-trim (replace-regexp-in-string blank " " string t t) blank blank))) -(defun string-fill (string length) - "Try to word-wrap STRING so that no lines are longer than LENGTH. -Wrapping is done where there is whitespace. If there are -individual words in STRING that are longer than LENGTH, the -result will have lines that are longer than LENGTH." +;;;###autoload +(defun string-fill (string width) + "Try to word-wrap STRING so that it displays with lines no wider than WIDTH. +STRING is wrapped where there is whitespace in it. If there are +individual words in STRING that are wider than WIDTH, the result +will have lines that are wider than WIDTH." (declare (important-return-value t)) (with-temp-buffer (insert string) (goto-char (point-min)) - (let ((fill-column length) + (let ((fill-column width) (adaptive-fill-mode nil)) (fill-region (point-min) (point-max))) (buffer-string))) +;;;###autoload (defun string-limit (string length &optional end coding-system) "Return a substring of STRING that is (up to) LENGTH characters long. If STRING is shorter than or equal to LENGTH characters, return the @@ -253,6 +255,7 @@ than this function." (end (substring string (- (length string) length))) (t (substring string 0 length))))) +;;;###autoload (defun string-pad (string length &optional padding start) "Pad STRING to LENGTH using PADDING. If PADDING is nil, the space character is used. If not nil, it @@ -272,6 +275,7 @@ the string." (start (concat (make-string pad-length (or padding ?\s)) string)) (t (concat string (make-string pad-length (or padding ?\s))))))) +;;;###autoload (defun string-chop-newline (string) "Remove the final newline (if any) from STRING." (declare (pure t) (side-effect-free t)) diff --git a/lisp/emulation/cua-base.el b/lisp/emulation/cua-base.el index fb6a8515d9e..8b62b04c99c 100644 --- a/lisp/emulation/cua-base.el +++ b/lisp/emulation/cua-base.el @@ -154,7 +154,7 @@ ;; ;; To start a rectangle, use [C-return] and extend it using the normal ;; movement keys (up, down, left, right, home, end, C-home, -;; C-end). Once the rectangle has the desired size, you can cut or +;; C-end). Once the rectangle has the desired size, you can cut or ;; copy it using C-x and C-c (or C-w and M-w), and you can ;; subsequently insert it - as a rectangle - using C-v (or C-y). So ;; the only new command you need to know to work with cua-mode diff --git a/lisp/emulation/viper-mous.el b/lisp/emulation/viper-mous.el index 322027b56c4..fb31983f1f2 100644 --- a/lisp/emulation/viper-mous.el +++ b/lisp/emulation/viper-mous.el @@ -456,7 +456,7 @@ bindings in the Viper manual." (if (eq 'up event-type) "mouse-3" "down-mouse-3")) (t (error - "%S: invalid button number, %S" key-var key))) + "%S: Invalid button number, %S" key-var key))) meta-spec (if (memq 'meta key) "M-" "") shift-spec diff --git a/lisp/emulation/viper.el b/lisp/emulation/viper.el index 287292a24dc..b62e11b2649 100644 --- a/lisp/emulation/viper.el +++ b/lisp/emulation/viper.el @@ -486,7 +486,7 @@ unless it is coming up in a wrong Viper state." "List specifying how to modify the various major modes to enable some Viperisms. The list has the structure: ((mode viper-state keymap) (mode viper-state keymap) ...). If `mode' is on the list, the `keymap' will be made active (on -the minor-mode-map-alist) in the specified viper state. +the `minor-mode-map-alist') in the specified viper state. If you change this list, have to restart Emacs for the change to take effect. However, if you did the change through the customization widget, then Emacs needs to be restarted only if you deleted a triple mode-state-keymap from the diff --git a/lisp/epg.el b/lisp/epg.el index 7bec91f616d..494bdd68c41 100644 --- a/lisp/epg.el +++ b/lisp/epg.el @@ -676,10 +676,14 @@ callback data (if any)." :command (cons (epg-context-program context) args) :connection-type 'pipe - :coding 'raw-text + :coding '(raw-text . nil) :filter #'epg--process-filter :stderr error-process :noquery t)))) + ;; We encode and decode ourselves the text sent/received from gpg, + ;; so the below disables automatic encoding and decoding by + ;; subprocess communications routines. + (set-process-coding-system process 'raw-text 'raw-text) (setf (epg-context-process context) process))) (defun epg--process-filter (process input) diff --git a/lisp/erc/erc-backend.el b/lisp/erc/erc-backend.el index a75ceffb6c8..9aedc110067 100644 --- a/lisp/erc/erc-backend.el +++ b/lisp/erc/erc-backend.el @@ -260,7 +260,7 @@ or where PARAMETER is a string and VALUE is a string or nil. For compatibility, a raw parameter of the form \"FOO=\" becomes (\"FOO\" . \"\") even though it's equivalent to the preferred -canonical form \"FOO\" and its lisp representation (\"FOO\"). +canonical form \"FOO\" and its Lisp representation (\"FOO\"). Some examples of possible parameters sent by servers: CHANMODES=b,k,l,imnpst - list of supported channel modes @@ -425,7 +425,7 @@ If this value is too low, servers may reject your initial nick request upon reconnecting because they haven't yet noticed that your previous connection is dead. If this happens, try setting this value to 120 or greater and/or exploring the option -`erc-regain-services-alist', which may provide a more proactive +`erc-services-regain-alist', which may provide a more proactive means of handling this situation on some servers." :type 'number) diff --git a/lisp/erc/erc-button.el b/lisp/erc/erc-button.el index 8cf8991e57c..c158b443b89 100644 --- a/lisp/erc/erc-button.el +++ b/lisp/erc/erc-button.el @@ -815,7 +815,7 @@ and `apropos' for other symbols." (defun erc-button--display-error-with-buttons (from to fun nick-p &optional data regexp) - "Replace command in region with keys and return new bounds" + "Replace command in region with keys and return new bounds." (let* ((o (buffer-substring from to)) (s (substitute-command-keys o)) (erc-button-face (and (equal o s) erc-button-face))) diff --git a/lisp/erc/erc-common.el b/lisp/erc/erc-common.el index 3577e697515..057e7981515 100644 --- a/lisp/erc/erc-common.el +++ b/lisp/erc/erc-common.el @@ -363,7 +363,7 @@ instead of a `set' state, which precludes any actual saving." Non-nil inside an ERC module's activation (or deactivation) command, such as `erc-spelling-enable', when it's been called indirectly via the module's minor-mode toggle, i.e., -`erc-spelling-mode'. Nil otherwise. Its value is either the +`erc-spelling-mode'. nil otherwise. Its value is either the symbol `toggle' or an integer produced by `prefix-numeric-value'. See Info node `(elisp) Defining Minor Modes' for more.") diff --git a/lisp/erc/erc-dcc.el b/lisp/erc/erc-dcc.el index b8e16df755b..dec499e727f 100644 --- a/lisp/erc/erc-dcc.el +++ b/lisp/erc/erc-dcc.el @@ -173,7 +173,7 @@ ARGS is a plist. Return nil on no match. The property :nick is treated specially, if it contains a `!' character, it is treated as a nick!user@host string, and compared with the :nick property -value of the individual elements using string-equal. Otherwise it is +value of the individual elements using `string-equal'. Otherwise it is compared with `erc-nick-equal-p' which is IRC case-insensitive." (let ((list erc-dcc-list) result test) diff --git a/lisp/erc/erc-fill.el b/lisp/erc/erc-fill.el index 9d969b39ad2..defef6fe414 100644 --- a/lisp/erc/erc-fill.el +++ b/lisp/erc/erc-fill.el @@ -799,7 +799,7 @@ necessary after revealing previously hidden text with commands like `erc-match-toggle-hidden-fools'." (interactive "P") (unless erc-fill-wrap-mode - (user-error "Module `fill-wrap' not active in current buffer.")) + (user-error "Module `fill-wrap' not active in current buffer")) (save-excursion (with-silent-modifications (let* ((rep (make-progress-reporter diff --git a/lisp/erc/erc-speedbar.el b/lisp/erc/erc-speedbar.el index 3e8c110a31b..e45fb9a7adf 100644 --- a/lisp/erc/erc-speedbar.el +++ b/lisp/erc/erc-speedbar.el @@ -548,7 +548,7 @@ associated with an ERC session." "Speedbar update period.") (defvar-local erc-speedbar--last-ran nil - "When non-nil, a lisp timestamp updated when the speedbar timer runs.") + "When non-nil, a Lisp timestamp updated when the speedbar timer runs.") (defun erc-speedbar--prod-dframe-timer (&rest _) "Refresh speedbar if dormant for `erc-speedbar--force-update-interval-secs'." diff --git a/lisp/erc/erc-stamp.el b/lisp/erc/erc-stamp.el index 7788f0b2d68..bebc1d0be38 100644 --- a/lisp/erc/erc-stamp.el +++ b/lisp/erc/erc-stamp.el @@ -210,11 +210,11 @@ from entering them and instead jump over them." (defvar erc-stamp--current-time nil "The current time when calling `erc-insert-timestamp-function'. -Specifically, this is the same lisp time object used to create +Specifically, this is the same Lisp time object used to create the stamp passed to `erc-insert-timestamp-function'.") (cl-defgeneric erc-stamp--current-time () - "Return a lisp time object to associate with an IRC message. + "Return a Lisp time object to associate with an IRC message. This becomes the message's `erc--ts' text property." (erc-compat--current-lisp-time)) diff --git a/lisp/erc/erc-track.el b/lisp/erc/erc-track.el index 40e83fff974..39a4775ddca 100644 --- a/lisp/erc/erc-track.el +++ b/lisp/erc/erc-track.el @@ -760,7 +760,7 @@ the number of unread messages, according to variables `erc-track-showcount' and `erc-track-showcount-string'. If `erc-track-use-faces' is true and FACES are provided, format -STRING with them. When the mouse hovers above the button, STRING +STRING with them. When the mouse hovers above the button, STRING is displayed according to `erc-track-mouse-face'." ;; We define a new sparse keymap every time, because 1. this data ;; structure is very small, the alternative would require us to diff --git a/lisp/erc/erc.el b/lisp/erc/erc.el index daad48223fa..e9a7aef0ba8 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 +;; 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" +(defconst erc-version "5.6.1-git" "This version of ERC.") (defvar erc-official-location @@ -1868,7 +1868,7 @@ the value of this option is DISPLAY-FUNCTION." "How to display buffers as a result of user interaction. This affects commands like /QUERY and /JOIN when issued interactively at the prompt. It does not apply when calling a -handler for such a command, like `erc-cmd-JOIN', from lisp code. +handler for such a command, like `erc-cmd-JOIN', from Lisp code. See `erc-buffer-display' for a full description of available values. @@ -2269,7 +2269,7 @@ buffer rather than a server buffer.") list match menu move-to-prompt netsplit networks readonly ring stamp track) "Modules to enable while connecting. -When modifying this option in lisp code, use a Custom-friendly +When modifying this option in Lisp code, use a Custom-friendly facilitator, like `setopt', or call `erc-update-modules' afterward. This ensures a consistent ordering and disables removed modules. It also gives packages access to the hook @@ -4476,7 +4476,7 @@ Called with position indicating boundary of interval to be excised.") (defun erc-cmd-CLEAR () "Clear messages in current buffer after informing active modules. Expect modules to perform housekeeping tasks to withstand the -disruption. When called from lisp code, only clear messages up +disruption. When called from Lisp code, only clear messages up to but not including the one occupying the current line." (with-silent-modifications (let ((max (if (>= (point) erc-insert-marker) @@ -7288,7 +7288,7 @@ status switches among VOICE, HALFOP, OP, ADMIN, and OWNER to be the symbol `on' or `off' when needing to influence a new or existing `erc-channel-user' object's `status' slot. Likewise, when UPDATE-MESSAGE-TIME is non-nil, update or initialize the -`last-message-time' slot to the current-time. If changes occur, +`last-message-time' slot to the `current-time'. If changes occur, including creation, run `erc-channel-members-changed-hook'. Return non-nil when meaningful changes, including creation, have occurred. @@ -9173,7 +9173,7 @@ Currently only used by the option `erc-prompt-format'.") ;; As of ERC 5.6, this is identical to the away variant aside from ;; the var names and `eq', which isn't important. (defun erc--format-user-modes () - "Return server's user modes as a string" + "Return server's user modes as a string." (and-let* ((indicator (erc-with-server-buffer (or erc--user-modes-indicator (setq erc--user-modes-indicator (list ""))))) @@ -9730,7 +9730,7 @@ or `erc-kill-buffer-hook' if any other buffer." (defun erc-check-text-conversion () "Check if point is within the ERC prompt and toggle text conversion. If `text-conversion-style' is not `action' if point is within the -prompt or `nil' otherwise, set it to such a value, so as to +prompt or nil otherwise, set it to such a value, so as to guarantee that the input method functions properly for the purpose of typing within the ERC prompt." (when (and (eq major-mode 'erc-mode) diff --git a/lisp/eshell/em-elecslash.el b/lisp/eshell/em-elecslash.el index 60f2c6e4039..a06e5be721d 100644 --- a/lisp/eshell/em-elecslash.el +++ b/lisp/eshell/em-elecslash.el @@ -108,4 +108,4 @@ insertion." (insert "/"))))) (provide 'em-elecslash) -;;; esh-elecslash.el ends here +;;; em-elecslash.el ends here diff --git a/lisp/eshell/em-extpipe.el b/lisp/eshell/em-extpipe.el index 4c92653a3a3..dd06a055755 100644 --- a/lisp/eshell/em-extpipe.el +++ b/lisp/eshell/em-extpipe.el @@ -217,4 +217,4 @@ as though it were Eshell syntax." (error "Unhandled external pipeline in input text")) (provide 'em-extpipe) -;;; esh-extpipe.el ends here +;;; em-extpipe.el ends here diff --git a/lisp/eshell/em-pred.el b/lisp/eshell/em-pred.el index 0be262641ea..a9274e7c60d 100644 --- a/lisp/eshell/em-pred.el +++ b/lisp/eshell/em-pred.el @@ -417,7 +417,7 @@ delimiter. If CHAINED-P is true, then another delimited modifier argument will immediately follow this one. In this case, when the opening and closing delimiters are the same, update point to be just -before the closing delimiter. This allows modifiers like +before the closing delimiter. This allows modifiers like `:s/match/repl' to work as expected." (when-let* ((open (char-after)) (close (cdr (assoc open eshell-pred-delimiter-pairs))) diff --git a/lisp/eshell/esh-cmd.el b/lisp/eshell/esh-cmd.el index aaae19df5d6..b936f68a57a 100644 --- a/lisp/eshell/esh-cmd.el +++ b/lisp/eshell/esh-cmd.el @@ -154,8 +154,7 @@ To prevent a command from executing at all, set :type 'hook) (defcustom eshell-named-command-hook nil - "A set of functions called before -a named command is invoked. + "A set of functions called before a named command is invoked. Each function will be passed the command name and arguments that were passed to `eshell-named-command'. @@ -816,7 +815,7 @@ current ones (see `eshell-duplicate-handles')." This changes COMMAND in-place by converting function calls listed in `eshell-deferrable-commands' to their non-deferrable forms so that Eshell doesn't erroneously allow deferring it. For example, -`eshell-named-command' becomes `eshell-named-command*', " +`eshell-named-command' becomes `eshell-named-command*'." (let ((cmd command)) (when (memq (car cmd) '(let progn)) (setq cmd (car (last cmd)))) @@ -1300,7 +1299,7 @@ have been replaced by constants." (if-let (((memq (car form) eshell-deferrable-commands)) (procs (eshell-make-process-list result))) (if synchronous-p - (apply #'eshell/wait procs) + (funcall #'eshell-wait-for-processes procs) (eshell-manipulate form "inserting ignore form" (setcar form 'ignore) (setcdr form nil)) diff --git a/lisp/eshell/esh-ext.el b/lisp/eshell/esh-ext.el index 3c4deb32601..cf93d2904da 100644 --- a/lisp/eshell/esh-ext.el +++ b/lisp/eshell/esh-ext.el @@ -301,7 +301,17 @@ Return nil, or a list of the form: (INTERPRETER [ARGS] FILE)" (let ((maxlen eshell-command-interpreter-max-length)) (if (and (file-readable-p file) - (file-regular-p file)) + (file-regular-p file) + ;; If the file is zero bytes, it can't possibly have a + ;; shebang. This check may seem redundant, but we can + ;; encounter files that Emacs considers both readable and + ;; regular, but which aren't *actually* readable. This can + ;; happen, for example, with certain kinds of reparse + ;; points like APPEXECLINK on NTFS filesystems (MS-Windows + ;; uses these for "app execution aliases"). In these + ;; cases, the file size is 0, so this check protects us + ;; from errors. + (> (file-attribute-size (file-attributes file)) 0)) (with-temp-buffer (insert-file-contents-literally file nil 0 maxlen) (if (looking-at "#![ \t]*\\([^ \r\t\n]+\\)\\([ \t]+\\(.+\\)\\)?") diff --git a/lisp/eshell/esh-module.el b/lisp/eshell/esh-module.el index db808f8597a..a139bc186d7 100644 --- a/lisp/eshell/esh-module.el +++ b/lisp/eshell/esh-module.el @@ -99,7 +99,7 @@ extension module; if nil, KIND defaults to `extension'." (let ((module-name (symbol-name module)) (prefix (cond ((eq kind 'core) "esh-") ((memq kind '(extension nil)) "em-") - (t (error "unknown module kind %s" kind))))) + (t (error "Unknown module kind %s" kind))))) (if (string-match "^eshell-\\(.*\\)" module-name) (concat prefix (match-string 1 module-name)) (error "Invalid Eshell module name: %s" module)))) diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index e05590f2542..0dcdf3bb76c 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -25,6 +25,7 @@ (require 'esh-arg) (require 'esh-io) +(require 'esh-opt) (require 'esh-util) (require 'pcomplete) @@ -184,16 +185,46 @@ This is like `process-live-p', but additionally checks whether ;; cleared out the handles (see `eshell-sentinel'). (process-get process :eshell-handles))) -(defun eshell-wait-for-process (&rest procs) - "Wait until PROCS have successfully completed." - (dolist (proc procs) - (when (eshell-processp proc) - (while (eshell-process-active-p proc) - (when (input-pending-p) - (discard-input)) - (sit-for eshell-process-wait-time))))) +(defun eshell-wait-for-processes (&optional procs timeout) + "Wait until PROCS have completed execution. +If TIMEOUT is non-nil, wait at most that many seconds. Return non-nil +if all the processes finished executing before the timeout expired." + (let ((expiration (when timeout (time-add (current-time) timeout)))) + (catch 'timeout + (dolist (proc procs) + (while (if (processp proc) + (eshell-process-active-p proc) + (process-attributes proc)) + (when (input-pending-p) + (discard-input)) + (when (and expiration + (not (time-less-p (current-time) expiration))) + (throw 'timeout nil)) + (sit-for eshell-process-wait-time))) + t))) -(defalias 'eshell/wait #'eshell-wait-for-process) +(defun eshell-wait-for-process (&rest procs) + "Wait until PROCS have completed execution." + (declare (obsolete 'eshell-wait-for-processes "31.1")) + (eshell-wait-for-processes procs)) + +(defun eshell/wait (&rest args) + "Wait until processes have completed execution." + (eshell-eval-using-options + "wait" args + '((?h "help" nil nil "show this usage screen") + (?t "timeout" t timeout "timeout in seconds") + :preserve-args + :show-usage + :usage "[OPTION] PROCESS... +Wait until PROCESS(es) have completed execution.") + (when (stringp timeout) + (setq timeout (string-to-number timeout))) + (dolist (arg args) + (unless (or (processp arg) (natnump arg)) + (error "wait: invalid argument type: %s" (type-of arg)))) + (unless (eshell-wait-for-processes args timeout) + (error "wait: timed out after %s seconds" timeout)))) (defun eshell/jobs () "List processes, if there are any." @@ -206,6 +237,11 @@ This is like `process-live-p', but additionally checks whether Usage: kill [-] | ... Accepts PIDs and process objects. Optionally accept signals and signal names." + ;; The implementation below only supports local PIDs. For remote + ;; connections, fall back to the external "kill" command. + (when (file-remote-p default-directory) + (declare-function eshell-external-command "esh-ext" (command args)) + (throw 'eshell-external (eshell-external-command "kill" args))) ;; If the first argument starts with a dash, treat it as the signal ;; specifier. (let ((signum 'SIGINT)) @@ -530,28 +566,34 @@ PROC is the process that's exiting. STRING is the exit message." (not (process-live-p proc)))) (finish-io (lambda () - (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) + (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 + "finished external process `%s'" proc) + (if primary + (run-hook-with-args 'eshell-kill-hook + proc string) + (setcar stderr-live 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)))))) + "buffer for external process `%s' already killed" + proc))))) (funcall finish-io))) (when-let ((entry (assq proc eshell-process-list))) (eshell-remove-process-entry entry)))))) @@ -615,16 +657,14 @@ long to delay between signals." (defun eshell-round-robin-kill (&optional query) "Kill current process by trying various signals in sequence. See the variable `eshell-kill-processes-on-exit'." - (let ((sigs eshell-kill-process-signals)) - (while sigs + (catch 'done + (dolist (sig eshell-kill-process-signals) (eshell-process-interact - (lambda (proc) - (signal-process (process-id proc) (car sigs))) t query) - (setq query nil) - (if (not eshell-process-list) - (setq sigs nil) - (sleep-for eshell-kill-process-wait-time) - (setq sigs (cdr sigs)))))) + (lambda (proc) (signal-process proc sig)) t query) + (when (eshell-wait-for-processes (mapcar #'car eshell-process-list) + eshell-kill-process-wait-time) + (throw 'done nil)) + (setq query nil)))) (defun eshell-query-kill-processes () "Kill processes belonging to the current Eshell buffer, possibly with query." diff --git a/lisp/eshell/esh-util.el b/lisp/eshell/esh-util.el index 1504d89731d..46083184aaa 100644 --- a/lisp/eshell/esh-util.el +++ b/lisp/eshell/esh-util.el @@ -256,7 +256,7 @@ specifying a region in the current buffer, or (:file . FILENAME) to temporarily insert the contents of FILENAME. Before executing BODY, narrow the buffer to the text for COMMAND -and and set point to the beginning of the narrowed region. +and set point to the beginning of the narrowed region. The value returned is the last form in BODY." (declare (indent 1)) @@ -288,7 +288,7 @@ The value returned is the last form in BODY." (defun eshell-find-delimiter (open close &optional bound reverse-p backslash-p) "From point, find the CLOSE delimiter corresponding to OPEN. -The matching is bounded by BOUND. If REVERSE-P is non-nil, +The matching is bounded by BOUND. If REVERSE-P is non-nil, process the region backwards. If BACKSLASH-P is non-nil, or OPEN and CLOSE are different diff --git a/lisp/eshell/eshell.el b/lisp/eshell/eshell.el index 18e05a371a4..b7be3dd1643 100644 --- a/lisp/eshell/eshell.el +++ b/lisp/eshell/eshell.el @@ -176,7 +176,7 @@ (require 'cl-lib)) (require 'esh-util) (require 'esh-module) ;For eshell-using-module -(require 'esh-proc) ;For eshell-wait-for-process +(require 'esh-proc) ;For eshell-wait-for-processes (require 'esh-io) ;For eshell-last-command-status (require 'esh-cmd) @@ -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,26 +337,53 @@ 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-round-robin-kill)) + (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 - (apply #'eshell-wait-for-process (cadr eshell-foreground-command)) + (unless async + (funcall #'eshell-wait-for-processes (cadr eshell-foreground-command)) (cl-assert (not eshell-foreground-command)) (goto-char (point-max)) (while (and (bolp) (not (bobp))) (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 +399,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/files.el b/lisp/files.el index 042b8e2d515..e552f3ac413 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -7263,7 +7263,7 @@ auto-save file, if that is more recent than the visited file." (after-find-file nil nil t)) (t (user-error "Recover-file canceled"))))) -(defvar dired-mode-hook) +(declare-function dired-omit-mode "dired-x" (&optional arg)) (defun recover-session () "Recover auto save files from a previous Emacs session. @@ -7284,14 +7284,12 @@ Then you'll be asked about a number of files to recover." (concat "\\`" (regexp-quote nd))) t) (error "No previous sessions to recover"))) - (require 'dired) - (let ((ls-lisp-support-shell-wildcards t) - ;; Ensure that we don't omit the session files as the user may - ;; have (as suggested by the manual) `dired-omit-mode' in the - ;; hook. - (dired-mode-hook (delete 'dired-omit-mode dired-mode-hook))) + (let ((ls-lisp-support-shell-wildcards t)) (dired (concat auto-save-list-file-prefix "*") - (concat (connection-local-value dired-listing-switches) " -t"))) + (concat (connection-local-value dired-listing-switches) " -t")) + ;; Toggle omitting, if it is on. + (when (bound-and-true-p dired-omit-mode) + (dired-omit-mode -1))) (use-local-map (nconc (make-sparse-keymap) (current-local-map))) (define-key (current-local-map) "\C-c\C-c" 'recover-session-finish) (save-excursion @@ -8087,8 +8085,8 @@ Valid wildcards are `*', `?', `[abc]' and `[a-z]'." (end (insert-directory-adj-pos (+ beg (read (current-buffer))) error-lines))) - (if (memq (char-after end) '(?\n ?\s)) - ;; End is followed by \n or by " -> ". + (if (memq (char-after end) '(?\n ?\s ?/ ?* ?@ ?% ?= ?|)) + ;; End is followed by \n or by output of -F. (put-text-property start end 'dired-filename t) ;; It seems that we can't trust ls's output as to ;; byte positions of filenames. @@ -8195,9 +8193,15 @@ normally equivalent short `-D' option is just passed on to "\\") ; Disregard Unix shell aliases! insert-directory-program " -d " - (if (stringp switches) - switches - (mapconcat #'identity switches " ")) + ;; Quote switches that require quoting + ;; such as "--block-size='1". But don't + ;; quote switches that use patterns + ;; such as "--ignore=PATTERN" (bug#71935). + (mapconcat #'shell-quote-wildcard-pattern + (if (stringp switches) + (split-string-and-unquote switches) + switches) + " ") " -- " ;; Quote some characters that have ;; special meanings in shells; but diff --git a/lisp/frameset.el b/lisp/frameset.el index 436e51905fb..18e2a3ac666 100644 --- a/lisp/frameset.el +++ b/lisp/frameset.el @@ -200,7 +200,7 @@ Properties can be set with ;; - can be ignored by window managers (most positional args, like `height', ;; `width', `left' and `top', and others, like `auto-raise', `auto-lower') ;; - can be set externally in X resources or Window registry (again, most -;; positional parameters, and also `toolbar-lines', `menu-bar-lines' etc.) +;; positional parameters, and also `tool-bar-lines', `menu-bar-lines' etc.) ;, - can contain references to live objects (`buffer-list', `minibuffer') or ;; code (`buffer-predicate') ;; - are set automatically, and cannot be changed (`window-id', `parent-id'), diff --git a/lisp/gnus/ChangeLog.3 b/lisp/gnus/ChangeLog.3 index 1633b8835eb..fa376f02a7e 100644 --- a/lisp/gnus/ChangeLog.3 +++ b/lisp/gnus/ChangeLog.3 @@ -5560,7 +5560,7 @@ 2011-05-10 Jim Meyering - * shr.el (shr-colorize-region): Fix typo "on on -> on". + * shr.el (shr-colorize-region): Fix typo. 2011-05-10 Julien Danjou 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/gnus/gnus-agent.el b/lisp/gnus/gnus-agent.el index 0928b179787..c290f8537e2 100644 --- a/lisp/gnus/gnus-agent.el +++ b/lisp/gnus/gnus-agent.el @@ -153,7 +153,7 @@ this limit." When set to ENABLE, the default, `gnus-agent-expire' will expire old contents from a group's local storage. This value may be overridden to disable expiration in specific categories, topics, and groups. Of -course, you could change gnus-agent-enable-expiration to DISABLE then +course, you could change `gnus-agent-enable-expiration' to DISABLE then enable expiration per categories, topics, and groups." :version "22.1" :group 'gnus-agent @@ -275,14 +275,14 @@ Actually a hash table holding subjects mapped to t.") ;;; (defmacro gnus-agent-with-refreshed-group (group &rest body) - "Performs the body then updates the group's line in the group -buffer. Automatically blocks multiple updates due to recursion." + "Perform the body then update the group's line in the group buffer. +Automatically block multiple updates due to recursion." `(prog1 (let ((gnus-agent-inhibit-update-total-fetched-for t)) ,@body) (when (and gnus-agent-need-update-total-fetched-for (not gnus-agent-inhibit-update-total-fetched-for)) - (with-current-buffer gnus-group-buffer - (setq gnus-agent-need-update-total-fetched-for nil) - (gnus-group-update-group ,group t))))) + (with-current-buffer gnus-group-buffer + (setq gnus-agent-need-update-total-fetched-for nil) + (gnus-group-update-group ,group t))))) (defun gnus-agent-read-file (file) "Load FILE and do a `read' there." @@ -618,8 +618,8 @@ manipulated as follows: (defun gnus-agentize () "Allow Gnus to be an offline newsreader. -The gnus-agentize function is now called internally by gnus when -gnus-agent is set. If you wish to avoid calling gnus-agentize, +The `gnus-agentize' function is now called internally by gnus when +`gnus-agent' is set. If you wish to avoid calling `gnus-agentize', customize `gnus-agent' to nil. This will modify the `gnus-setup-news-hook', and @@ -1785,9 +1785,9 @@ variables. Returns the first non-nil value found." (agent-predicate . gnus-agent-predicate))))))) (defun gnus-agent-fetch-headers (group) - "Fetch interesting headers into the agent. The group's overview -file will be updated to include the headers while a list of available -article numbers will be returned." + "Fetch interesting headers into the agent. +The group's overview file will be updated to include the headers while a +list of available article numbers will be returned." (let* ((fetch-all (and gnus-agent-consider-all-articles ;; Do not fetch all headers if the predicate ;; implies that we only consider unread articles. @@ -4059,8 +4059,7 @@ CLEAN is obsolete and ignored." (defun gnus-agent-update-files-total-fetched-for (group delta &optional method path) - "Update, or set, the total disk space used by the articles that the -agent has fetched." + "Update or set total disk space used by articles that the agent has fetched." (when gnus-agent-total-fetched-hashtb (gnus-agent-with-refreshed-group group @@ -4099,9 +4098,8 @@ agent has fetched." (defun gnus-agent-update-view-total-fetched-for (group agent-over &optional method path) - "Update, or set, the total disk space used by the .agentview and -.overview files. These files are calculated separately as they can be -modified." + "Update or set the total disk space used by the .agentview and .overview files. +These files are calculated separately as they can be modified." (when gnus-agent-total-fetched-hashtb (gnus-agent-with-refreshed-group group diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 9f313108089..5151ad1c1b8 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el @@ -330,8 +330,7 @@ to match a mail address in the From: header, BANNER is one of a symbol If ADDRESS matches author's mail address, it will remove things like advertisements. For example: -\((\"@yoo-hoo\\\\.co\\\\.jp\\\\\\='\" . \"\\n_+\\nDo You Yoo-hoo!\\\\?\\n.*\\n.*\\n\")) -" +\((\"@yoo-hoo\\\\.co\\\\.jp\\\\\\='\" . \"\\n_+\\nDo You Yoo-hoo!\\\\?\\n.*\\n.*\\n\"))" :type '(repeat (cons (regexp :tag "Address") @@ -557,15 +556,15 @@ command, and friends such as `gnus-summary-save-article-rmail'. Gnus provides the following functions: -* gnus-summary-save-in-rmail (Rmail format) -* gnus-summary-save-in-mail (Unix mail format) -* gnus-summary-save-in-folder (MH folder) -* gnus-summary-save-in-file (article format) -* gnus-summary-save-body-in-file (article body) -* gnus-summary-save-in-vm (use VM's folder format) -* gnus-summary-write-to-file (article format -- overwrite) -* gnus-summary-write-body-to-file (article body -- overwrite) -* gnus-summary-save-in-pipe (article format) +* `gnus-summary-save-in-rmail' (Rmail format) +* `gnus-summary-save-in-mail' (Unix mail format) +* `gnus-summary-save-in-folder' (MH folder) +* `gnus-summary-save-in-file' (article format) +* `gnus-summary-save-body-in-file' (article body) +* `gnus-summary-save-in-vm' (use VM's folder format) +* `gnus-summary-write-to-file' (article format -- overwrite) +* `gnus-summary-write-body-to-file' (article body -- overwrite) +* `gnus-summary-save-in-pipe' (article format) The symbol of each function may have the following properties: @@ -5519,8 +5518,7 @@ CHARSET may either be a string or a symbol." (setcdr type (cons (cons 'charset charset) (cdr type))))))) (defun gnus-mime-view-part-as-charset (&optional handle arg event) - "Insert the MIME part under point into the current buffer using the -specified charset." + "Insert MIME part under point into current buffer using specified charset." (interactive (list nil current-prefix-arg last-nonmenu-event) gnus-article-mode) (save-excursion @@ -7304,8 +7302,7 @@ If given a prefix, show the hidden text instead." (point))))))) (defun gnus-block-private-groups (group) - "Allows images in newsgroups to be shown, blocks images in all -other groups." + "Allows images in newsgroups to be shown, blocks images in all other groups." (if (or (gnus-news-group-p group) (gnus-member-of-valid 'global group) (member group gnus-global-groups)) @@ -7389,7 +7386,7 @@ other groups." (define-derived-mode gnus-article-edit-mode message-mode "Article Edit" "Major mode for editing articles. -This is an extended text-mode. +This is an extended `text-mode'. \\{gnus-article-edit-mode-map}" (make-local-variable 'gnus-article-edit-done-function) diff --git a/lisp/gnus/gnus-dired.el b/lisp/gnus/gnus-dired.el index f33c5f7f2e5..f21d84b40c6 100644 --- a/lisp/gnus/gnus-dired.el +++ b/lisp/gnus/gnus-dired.el @@ -24,15 +24,15 @@ ;;; Commentary: ;; This package provides utility functions for intersections of gnus -;; and dired. To enable the gnus-dired-mode minor mode which will +;; and Dired. To enable the gnus-dired-mode minor mode which will ;; have the effect of installing keybindings in dired-mode, place the ;; following in your ~/.gnus: ;; (require 'gnus-dired) ;, isn't needed due to autoload cookies ;; (add-hook 'dired-mode-hook #'turn-on-gnus-dired-mode) -;; Note that if you visit dired buffers before your ~/.gnus file has -;; been read, those dired buffers won't have the keybindings in +;; Note that if you visit Dired buffers before your ~/.gnus file has +;; been read, those Dired buffers won't have the keybindings in ;; effect. To get around that problem, you may want to add the above ;; statements to your ~/.emacs instead. @@ -81,7 +81,7 @@ See `mail-user-agent' for more information." (function :tag "Other"))) (define-minor-mode gnus-dired-mode - "Minor mode for intersections of gnus and dired. + "Minor mode for intersections of gnus and Dired. \\{gnus-dired-mode-map}" :keymap gnus-dired-mode-map @@ -119,7 +119,7 @@ See `mail-user-agent' for more information." ;; Method to attach files to a mail composition. (defun gnus-dired-attach (files-to-attach) - "Attach dired's marked files to a gnus message composition. + "Attach Dired's marked files to a gnus message composition. If called non-interactively, FILES-TO-ATTACH should be a list of filenames." (interactive @@ -180,7 +180,7 @@ filenames." (autoload 'mailcap-parse-mailcaps "mailcap" "" t) (defun gnus-dired-find-file-mailcap (&optional file-name arg) - "In dired, visit FILE-NAME according to the mailcap file. + "In Dired, visit FILE-NAME according to the mailcap file. If ARG is non-nil, open it in a new buffer." (interactive (list (file-name-sans-versions (dired-get-filename) t) @@ -215,7 +215,7 @@ If ARG is non-nil, open it in a new buffer." "File no longer exists; type \\`g' to update Dired buffer"))))) (defun gnus-dired-print (&optional file-name print-to) - "In dired, print FILE-NAME according to the mailcap file. + "In Dired, print FILE-NAME according to the mailcap file. If there is no print command, print in a PostScript image. If the optional argument PRINT-TO is nil, send the image to the printer. diff --git a/lisp/gnus/gnus-msg.el b/lisp/gnus/gnus-msg.el index b18ede58fbf..705dbfa10f2 100644 --- a/lisp/gnus/gnus-msg.el +++ b/lisp/gnus/gnus-msg.el @@ -1918,7 +1918,7 @@ can be attached to them. If not, a new Message buffer is created. This command uses the process/prefix convention, so if you -process-mark several articles, they will all be attached." +`process-mark' several articles, they will all be attached." (interactive "P" gnus-summary-mode) (let ((buffers (message-buffers)) destination) diff --git a/lisp/gnus/gnus-score.el b/lisp/gnus/gnus-score.el index 31ce1328e37..f91299ed3c0 100644 --- a/lisp/gnus/gnus-score.el +++ b/lisp/gnus/gnus-score.el @@ -190,7 +190,7 @@ It can be: * `(regexp file-name ...)' If the `regexp' matches the group name, the first `file-name' will be used as the home score file. (Multiple filenames are - allowed so that one may use gnus-score-file-single-match-alist to + allowed so that one may use `gnus-score-file-single-match-alist' to set this variable.) * A function. diff --git a/lisp/gnus/gnus-search.el b/lisp/gnus/gnus-search.el index 9cff2e2f109..c25163ac770 100644 --- a/lisp/gnus/gnus-search.el +++ b/lisp/gnus/gnus-search.el @@ -135,8 +135,7 @@ transformed." 'gnus-search-ignored-newsgroups "28.1") (defcustom gnus-search-ignored-newsgroups "" - "A regexp to match newsgroups in the active file that should -be skipped when searching." + "Regexp matching newsgroups in the active file to skip when searching." :version "24.1" :type 'regexp) @@ -357,7 +356,7 @@ This can also be set per-server." (defcustom gnus-search-mu-switches nil "A list of strings, to be given as additional arguments to mu. -Note that this should be a list. I.e., do NOT use the following: +Note that this should be a list. I.e., do NOT use the following: (setq gnus-search-mu-switches \"-u -r\") Instead, use this: (setq gnus-search-mu-switches \\='(\"-u\" \"-r\")) @@ -367,7 +366,7 @@ This can also be set per-server." (defcustom gnus-search-mu-remove-prefix (expand-file-name "~/Mail/") "A prefix to remove from the mu results to get a group name. -Usually this will be set to the path to your mail directory. This +Usually this will be set to the path to your mail directory. This can also be set per-server." :version "29.1" :type 'directory) @@ -2186,7 +2185,7 @@ remaining string, then adds all that to the top-level spec." (defun gnus-search-thread (header &optional group server) "Find articles in the thread containing HEADER from GROUP on SERVER. -If gnus-refer-thread-use-search is nil only the current group is +If `gnus-refer-thread-use-search' is nil only the current group is checked for articles; if t all groups on the server containing the article's group will be searched; if a list then all servers in this list will be searched. If possible the newly found diff --git a/lisp/gnus/gnus-sieve.el b/lisp/gnus/gnus-sieve.el index 04af180a9d2..7b4561b52f5 100644 --- a/lisp/gnus/gnus-sieve.el +++ b/lisp/gnus/gnus-sieve.el @@ -133,8 +133,7 @@ Return nil if no rule could be guessed." For example: \(gnus-sieve-string-list \\='(\"to\" \"cc\")) - => \"[\\\"to\\\", \\\"cc\\\"]\" -" + => \"[\\\"to\\\", \\\"cc\\\"]\"" (concat "[\"" (mapconcat #'identity list "\", \"") "\"]")) (defun gnus-sieve-test-list (list) diff --git a/lisp/gnus/message.el b/lisp/gnus/message.el index b2805774162..98f63571389 100644 --- a/lisp/gnus/message.el +++ b/lisp/gnus/message.el @@ -6252,8 +6252,7 @@ subscribed address (and not the additional To and Cc header contents)." (widen))))))) (defun message-idna-to-ascii-rhs () - "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers. -See `message-idna-encode'." + "Possibly IDNA encode non-ASCII domain names in From:, To: and Cc: headers." (interactive nil message-mode) (when message-use-idna (save-excursion @@ -6606,8 +6605,7 @@ they are." (sit-for 0)) (defcustom message-beginning-of-line t - "Whether \\\\[message-beginning-of-line]\ - goes to beginning of header values." + "Whether \\\\[message-beginning-of-line] goes to beginning of header values." :version "22.1" :group 'message-buffers :link '(custom-manual "(message)Movement") @@ -6669,7 +6667,7 @@ beginning of line. When called without a prefix argument, header value spanning multiple lines is treated as a single line. Otherwise, even if N is 1, when point is on a continuation header line, it will be -moved to the beginning " +moved to the beginning." (interactive "^p" message-mode) (cond ;; Go to beginning of header or beginning of line. diff --git a/lisp/gnus/mm-url.el b/lisp/gnus/mm-url.el index be6c9bb7977..788e4b294a0 100644 --- a/lisp/gnus/mm-url.el +++ b/lisp/gnus/mm-url.el @@ -21,7 +21,7 @@ ;;; Commentary: -;; Some code is stolen from w3 and url packages. Some are moved from +;; Some code is stolen from w3 and url packages. Some are moved from ;; nnweb. ;; TODO: Support POST, cookie. diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el index 223da19a164..1df634d3c9b 100644 --- a/lisp/gnus/mm-view.el +++ b/lisp/gnus/mm-view.el @@ -108,14 +108,14 @@ This is only used if `mm-inline-large-images' is set to (delete-region b (+ b 2))))))) (defvar mm-w3m-setup nil - "Whether gnus-article-mode has been setup to use emacs-w3m.") + "Whether `gnus-article-mode' has been setup to use emacs-w3m.") ;; External. (declare-function w3m-detect-meta-charset "ext:w3m" ()) (declare-function w3m-region "ext:w3m" (start end &optional url charset)) (defun mm-setup-w3m () - "Setup gnus-article-mode to use emacs-w3m." + "Setup `gnus-article-mode' to use emacs-w3m." (unless mm-w3m-setup (require 'w3m) (unless (assq 'gnus-article-mode w3m-cid-retrieve-function-alist) diff --git a/lisp/gnus/mml-sec.el b/lisp/gnus/mml-sec.el index 98f8ebbcbcd..141e00223db 100644 --- a/lisp/gnus/mml-sec.el +++ b/lisp/gnus/mml-sec.el @@ -151,9 +151,10 @@ you use Bcc headers to encrypt e-mails to yourself." ;;; Configuration/helper functions (defun mml-signencrypt-style (method &optional style) - "Function for setting/getting the signencrypt-style used. Takes two -arguments, the method (e.g. \"pgp\") and optionally the mode -\(e.g. combined). If the mode is omitted, the current value is returned. + "Function for setting/getting the signencrypt-style used. +Takes two arguments, the method (e.g. \"pgp\") and optionally the mode +\(e.g. combined). If the mode is omitted, the current value is +returned. For example, if you prefer to use combined sign & encrypt with smime, putting the following in your Gnus startup file will diff --git a/lisp/gnus/nnatom.el b/lisp/gnus/nnatom.el index 13286159784..f6885abb634 100644 --- a/lisp/gnus/nnatom.el +++ b/lisp/gnus/nnatom.el @@ -108,15 +108,19 @@ (defvoo nnatom-read-article-function #'nnatom--read-article nil nnfeed-read-article-function) +(defun nnatom--dom-line (node) + "Return NODE's text as a single, whitespace-trimmed line." + (string-trim (replace-regexp-in-string "[\r\n]+" " " (dom-text node) t))) + (defun nnatom--read-title (group) "Return the title of GROUP, or nil." - (dom-text (dom-child-by-tag group 'title))) + (nnatom--dom-line (dom-child-by-tag group 'title))) (defvoo nnatom-read-title-function #'nnatom--read-title nil nnfeed-read-title-function) (defun nnatom--read-description (group) "Return the description of GROUP, or nil." - (dom-text (dom-child-by-tag group 'subtitle))) + (nnatom--dom-line (dom-child-by-tag group 'subtitle))) (defvoo nnatom-read-description-function #'nnatom--read-description nil nnfeed-read-description-function) @@ -125,9 +129,9 @@ (when-let ((a (mapconcat (lambda (author) - (let* ((name (dom-text (dom-child-by-tag author 'name))) + (let* ((name (nnatom--dom-line (dom-child-by-tag author 'name))) (name (unless (string-blank-p name) name)) - (email (dom-text (dom-child-by-tag author 'email))) + (email (nnatom--dom-line (dom-child-by-tag author 'email))) (email (unless (string-blank-p email) email))) (or (and name email (format "%s <%s>" name email)) name email))) (dom-children (dom-child-by-tag article-or-group 'authors)) @@ -142,7 +146,7 @@ (defun nnatom--read-subject (article) "Return the subject of ARTICLE, or nil." - (dom-text (dom-child-by-tag article 'title))) + (nnatom--dom-line (dom-child-by-tag article 'title))) (defvoo nnatom-read-subject-function #'nnatom--read-subject nil nnfeed-read-subject-function) @@ -150,7 +154,7 @@ "Return the ID of ARTICLE. If the ARTICLE doesn't contain an ID but it does contain a subject, return the subject. Otherwise, return nil." - (or (dom-text (dom-child-by-tag article 'id)) + (or (nnatom--dom-line (dom-child-by-tag article 'id)) (nnatom--read-subject article))) (defvoo nnatom-read-id-function #'nnatom--read-id nil nnfeed-read-id-function) @@ -158,14 +162,14 @@ return the subject. Otherwise, return nil." (defun nnatom--read-publish (article) "Return the date and time ARTICLE was published, or nil." (when-let (d (dom-child-by-tag article 'published)) - (date-to-time (dom-text d)))) + (date-to-time (nnatom--dom-line d)))) (defvoo nnatom-read-publish-date-function #'nnatom--read-publish nil nnfeed-read-publish-date-function) (defun nnatom--read-update (article) "Return the date and time of the last update to ARTICLE, or nil." (when-let (d (dom-child-by-tag article 'updated)) - (date-to-time (dom-text d)))) + (date-to-time (nnatom--dom-line d)))) (defvoo nnatom-read-update-date-function #'nnatom--read-update nil nnfeed-read-update-date-function) @@ -185,13 +189,13 @@ return the subject. Otherwise, return nil." (("text/html") . ,(format "[%s] " src label))))) (when-let (((or (eq l 'author) (eq l 'contributor))) - (name (dom-text (dom-child-by-tag link 'name))) + (name (nnatom--dom-line (dom-child-by-tag link 'name))) (name (if (string-blank-p name) (concat "Author" (and (< 1 (cl-incf aut)) (format " %s" aut))) name)) - (uri (dom-text (dom-child-by-tag link 'uri))) + (uri (nnatom--dom-line (dom-child-by-tag link 'uri))) ((not (string-blank-p uri)))) `(((("text/plain") . ,(format "%s: %s\n" name uri)) (("text/html") . ,(format "[%s] " diff --git a/lisp/gnus/nndiary.el b/lisp/gnus/nndiary.el index b6f423ee2f8..97a4600603f 100644 --- a/lisp/gnus/nndiary.el +++ b/lisp/gnus/nndiary.el @@ -30,7 +30,7 @@ ;; =========== ;; nndiary is a mail back end designed to handle mails as diary event -;; reminders. It is now fully documented in the Gnus manual. +;; reminders. It is now fully documented in the Gnus manual. ;; Bugs / Todo: @@ -43,19 +43,19 @@ ;; * We could allow a keyword like `ask' in X-Diary-* headers, that would mean ;; "ask for value upon reception of the message". ;; * We could add an optional header X-Diary-Reminders to specify a special -;; reminders value for this message. Suggested by Jody Klymak. +;; reminders value for this message. Suggested by Jody Klymak. ;; * We should check messages validity in other circumstances than just -;; moving an article from somewhere else (request-accept). For instance, +;; moving an article from somewhere else (request-accept). For instance, ;; when editing / saving and so on. ;; Remarks: ;; ======= -;; * nnoo. NNDiary is very similar to nnml. This makes the idea of using nnoo -;; (to derive nndiary from nnml) natural. However, my experience with nnoo +;; * nnoo. NNDiary is very similar to nnml. This makes the idea of using nnoo +;; (to derive nndiary from nnml) natural. However, my experience with nnoo ;; is that for reasonably complex back ends like this one, nnoo is a burden -;; rather than an help. It's tricky to use, not everything can be inherited, +;; rather than an help. It's tricky to use, not everything can be inherited, ;; what can be inherited and when is not very clear, and you've got to be ;; very careful because a little mistake can fuck up your other back ends, ;; especially because their variables will be use instead of your real ones. @@ -64,16 +64,16 @@ ;; IMHO, nnoo is actually badly designed. A much simpler, and yet more ;; powerful one would be to make *real* functions and variables for a new -;; back end based on another. Lisp is a reflexive language so that's a very +;; back end based on another. Lisp is a reflexive language so that's a very ;; easy thing to do: inspect the function's form, replace occurrences of ;; (even in strings) with , and you're done. ;; * nndiary-get-new-mail, nndiary-mail-source and nndiary-split-methods: ;; NNDiary has some experimental parts, in the sense Gnus normally uses only -;; one mail back ends for mail retrieval and splitting. This back end is -;; also an attempt to make it behave differently. For Gnus developers: as +;; one mail back ends for mail retrieval and splitting. This back end is +;; also an attempt to make it behave differently. For Gnus developers: as ;; you can see if you snarf into the code, that was not a very difficult -;; thing to do. Something should be done about the respooling breakage +;; thing to do. Something should be done about the respooling breakage ;; though. diff --git a/lisp/gnus/nnfeed.el b/lisp/gnus/nnfeed.el index d6963b2e929..2d33d4c813b 100644 --- a/lisp/gnus/nnfeed.el +++ b/lisp/gnus/nnfeed.el @@ -630,12 +630,21 @@ Only HEADERS of a type included in MIME are considered." (deffoo nnfeed-request-type (_group &optional _article) 'unknown) +;; FIXME: Works incorrectly when a group name contains spaces as Gnus actually +;; separates the group name from the description with either a tab or a space. +(defun nnfeed--group-description (name group) + "Return a description line for a GROUP called NAME." + (when-let ((desc (aref group 5)) + ((not (string-blank-p desc)))) + (insert name "\t" desc "\n"))) + (deffoo nnfeed-request-group-description (group &optional server) (when-let ((server (or server (nnfeed--current-server-no-prefix))) (g (nnfeed--group-data group server))) (with-current-buffer nntp-server-buffer (erase-buffer) - (insert group " " (aref g 5) "\n")))) + (nnfeed--group-description group g) + t))) (deffoo nnfeed-request-list-newsgroups (&optional server) (when-let ((server (or server (nnfeed--current-server-no-prefix))) @@ -643,9 +652,8 @@ Only HEADERS of a type included in MIME are considered." ((hash-table-p s))) (with-current-buffer nntp-server-buffer (erase-buffer) - (maphash (lambda (group g) - (insert group " " (aref g 5) "\n")) - s)))) + (maphash #'nnfeed--group-description s) + t))) (deffoo nnfeed-request-rename-group (group new-name &optional server) (when-let ((server (or server (nnfeed--current-server-no-prefix))) diff --git a/lisp/gnus/nnimap.el b/lisp/gnus/nnimap.el index c61dfecfa7a..7b0e42ff89d 100644 --- a/lisp/gnus/nnimap.el +++ b/lisp/gnus/nnimap.el @@ -51,7 +51,7 @@ (defvoo nnimap-server-port nil "The IMAP port used. -If nnimap-stream is `ssl', this will default to `imaps'. If not, +If `nnimap-stream' is `ssl', this will default to `imaps'. If not, it will default to `imap'.") (defvoo nnimap-use-namespaces nil @@ -59,7 +59,7 @@ it will default to `imap'.") If in Gnus your folder names in all start with (e.g.) `INBOX', you probably want to set this to t. The effects of this are purely cosmetic, but changing this variable will affect the -names of your nnimap groups. ") +names of your nnimap groups.") (defvoo nnimap-stream 'undecided "How nnimap talks to the IMAP server. @@ -102,15 +102,15 @@ Possible choices are nil (use default methods), `anonymous', (defvoo nnimap-expunge 'on-exit "When to expunge deleted messages. If `never', deleted articles are marked with the IMAP \\Delete -flag but not automatically expunged. If `immediately', deleted +flag but not automatically expunged. If `immediately', deleted articles are immediately expunged (this requires the server to -support the UID EXPUNGE command). If `on-exit', deleted articles +support the UID EXPUNGE command). If `on-exit', deleted articles are flagged, and all flagged articles are expunged when the group is closed. For backwards compatibility, this variable may also be set to t -or nil. If the server supports UID EXPUNGE, both t and nil are -equivalent to `immediately'. If the server does not support UID +or nil. If the server supports UID EXPUNGE, both t and nil are +equivalent to `immediately'. If the server does not support UID EXPUNGE nil is equivalent to `never', while t will immediately expunge ALL articles that are currently flagged as deleted (i.e., potentially not only the article that was just deleted).") diff --git a/lisp/gnus/nnmail.el b/lisp/gnus/nnmail.el index a9f5b89c6fe..afc6a7470ac 100644 --- a/lisp/gnus/nnmail.el +++ b/lisp/gnus/nnmail.el @@ -602,7 +602,7 @@ These will be logged to the \"*nnmail split*\" buffer." (defvar nnmail-incoming-coding-system mm-text-coding-system - "Coding system used in reading inbox") + "Coding system used in reading inbox.") (defcustom nnmail-pathname-coding-system nil "Coding system for file name." @@ -1306,7 +1306,7 @@ See `nnmail-ignore-broken-references'." :type 'regexp) (defun nnmail-ignore-broken-references () - "Ignore the References line and use In-Reply-To + "Ignore the References line and use In-Reply-To. Eudora has a broken References line, but an OK In-Reply-To." (goto-char (point-min)) diff --git a/lisp/gnus/nnmairix.el b/lisp/gnus/nnmairix.el index c517f85db9b..434e907d536 100644 --- a/lisp/gnus/nnmairix.el +++ b/lisp/gnus/nnmairix.el @@ -35,7 +35,7 @@ ;; Commentary on the code: nnmairix sits between Gnus and the "real" ;; back end which handles the mail (currently nnml, nnimap and -;; nnmaildir were tested). I know this is all a bit hacky, but so far +;; nnmaildir were tested). I know this is all a bit hacky, but so far ;; it works for me. This is the first back end I've written for Gnus, ;; so I'd appreciate any comments, suggestions, bug reports (and, of ;; course, patches) for improving nnmairix. @@ -368,8 +368,9 @@ wrong count of total articles shown by Gnus.") its maildir mail folders (e.g. the Dovecot IMAP server or mutt).") (defvoo nnmairix-default-group nil - "Default search group. This is the group which is used for all -temporary searches, e.g. nnmairix-search.") + "Default search group. +This is the group which is used for all temporary searches, +e.g. nnmairix-search.") ;;; === Internal variables diff --git a/lisp/gnus/nntp.el b/lisp/gnus/nntp.el index fe165662988..393fd01a5d1 100644 --- a/lisp/gnus/nntp.el +++ b/lisp/gnus/nntp.el @@ -300,9 +300,10 @@ backend doesn't catch this error.") (defvar nntp--report-1 nil) (defun nntp-report (&rest args) - "Report an error from the nntp backend. The first string in ARGS -can be a format string. For some commands, the failed command may be -retried once before actually displaying the error report." + "Report an error from the nntp backend. +The first string in ARGS can be a format string. For some commands, the +failed command may be retried once before actually displaying the error +report." (if nntp--report-1 (progn ;; Throw out to nntp-with-open-group-error so that the connection may diff --git a/lisp/gnus/nnvirtual.el b/lisp/gnus/nnvirtual.el index 9eea0f89996..79747dca31f 100644 --- a/lisp/gnus/nnvirtual.el +++ b/lisp/gnus/nnvirtual.el @@ -436,7 +436,8 @@ lines have the correct component server prefix." (defun nnvirtual-update-read-and-marked (read-p update-p) "Copy marks from the virtual group to the component groups. If READ-P is not nil, update the (un)read status of the components. -If UPDATE-P is not nil, call gnus-group-update-group on the components." +If UPDATE-P is not nil, call `gnus-group-update-group' on the +components." (when nnvirtual-current-group (let ((unreads (and read-p (nnvirtual-partition-sequence @@ -642,7 +643,7 @@ then it is left out of the result." (defun nnvirtual-partition-sequence (articles) "Return an association list of component article numbers. -These are indexed by elements of nnvirtual-component-groups, based on +These are indexed by elements of `nnvirtual-component-groups', based on the sequence ARTICLES of virtual article numbers. ARTICLES should be sorted, and can be a compressed sequence. If any of the article numbers has no corresponding component article, then it is left out of diff --git a/lisp/gnus/spam-stat.el b/lisp/gnus/spam-stat.el index f4ad9e48f6f..431cb5e7d7a 100644 --- a/lisp/gnus/spam-stat.el +++ b/lisp/gnus/spam-stat.el @@ -183,7 +183,7 @@ say, `with-spam-stat-max-buffer-size'." :type '(repeat sexp)) (defcustom spam-stat-process-directory-age 90 - "Max. age of files to be processed in directory, in days. + "Maximum age of files to be processed in directory, in days. When using `spam-stat-process-spam-directory' or `spam-stat-process-non-spam-directory', only files that have been touched in this many days will be considered. Without @@ -192,7 +192,7 @@ will start to take a very long time." :type 'integer) (defvar spam-stat-last-saved-at nil - "Time stamp of last change of spam-stat-file on this run") + "Time stamp of last change of `spam-stat-file' on this run.") (defvar spam-stat-syntax-table (let ((table (copy-syntax-table text-mode-syntax-table))) @@ -394,7 +394,7 @@ Use `spam-stat-ngood', `spam-stat-nbad', `spam-stat-good', ;; Saving and Loading (defun spam-stat-save (&optional force) - "Save the `spam-stat' hash table as lisp file. + "Save the `spam-stat' hash table as Lisp file. With a prefix argument save unconditionally." (interactive "P") (when (or force spam-stat-dirty) diff --git a/lisp/gnus/spam.el b/lisp/gnus/spam.el index 1ae214ea4fa..ed667dae31f 100644 --- a/lisp/gnus/spam.el +++ b/lisp/gnus/spam.el @@ -2053,7 +2053,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (add-hook 'bbdb-change-hook #'spam-clear-cache-BBDB)) (defun spam-enter-ham-BBDB (addresses &optional remove) - "Enter an address into the BBDB; implies ham (non-spam) sender" + "Enter an address into the BBDB; implies ham (non-spam) sender." (dolist (from addresses) (when (stringp from) (let* ((parsed-address (gnus-extract-address-components from)) @@ -2091,7 +2091,7 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." (bbdb-gethash (downcase net)))) (defun spam-check-BBDB () - "Mail from people in the BBDB is classified as ham or non-spam" + "Mail from people in the BBDB is classified as ham or non-spam." (let ((net (message-fetch-field "from"))) (when net (setq net (nth 1 (gnus-extract-address-components net))) diff --git a/lisp/help.el b/lisp/help.el index 878dd404256..adc1724d504 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -883,7 +883,8 @@ If INSERT (the prefix arg) is non-nil, insert the message in the buffer." (let ((otherstring (help--key-description-fontified untranslated))) (if (equal string otherstring) string - (if-let ((char-name (char-to-name (aref string 0)))) + (if-let ((char-name (and (length= string 1) + (char-to-name (aref string 0))))) (format "%s '%s' (translated from %s)" string char-name otherstring) (format "%s (translated from %s)" string otherstring))))))) diff --git a/lisp/hi-lock.el b/lisp/hi-lock.el index 64b84cdf859..f595c92041a 100644 --- a/lisp/hi-lock.el +++ b/lisp/hi-lock.el @@ -122,9 +122,10 @@ calls." "Specify when hi-lock should use patterns found in file. If `ask', prompt when patterns found in buffer; if bound to a function, use patterns when function returns t (function is called with patterns -as first argument); if nil or `never' or anything else, don't use file -patterns." +as first argument); if `always', use file patterns without prompt; +if nil or `never' or anything else, don't use file patterns." :type '(choice (const :tag "Do not use file patterns" never) + (const :tag "Always use file patterns" always) (const :tag "Ask about file patterns" ask) (function :tag "Function to check file patterns")) :group 'hi-lock @@ -334,8 +335,8 @@ which can be called interactively, are: (See `font-lock-keywords'.) They may be edited and re-loaded with \\[hi-lock-find-patterns], any valid `font-lock-keywords' form is acceptable. When a file is loaded the patterns are read if `hi-lock-file-patterns-policy' is - `ask' and the user responds y to the prompt, or if - `hi-lock-file-patterns-policy' is bound to a function and that + `always', or if it's `ask' and the user responds y to the prompt, + or if `hi-lock-file-patterns-policy' is bound to a function and that function returns t. \\[hi-lock-find-patterns] @@ -768,6 +769,7 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." ;; Hashcons the regexp, so it can be passed to remove-overlays later. (setq regexp (hi-lock--hashcons regexp)) (setq subexp (or subexp 0)) + (when lighter (setq lighter (propertize lighter 'regexp regexp))) (let ((pattern (list (lambda (limit) (let ((case-fold-search case-fold) (search-spaces-regexp spaces-regexp)) @@ -852,6 +854,7 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." (funcall hi-lock-file-patterns-policy all-patterns)) ((eq hi-lock-file-patterns-policy 'ask) (y-or-n-p "Add patterns from this buffer to hi-lock? ")) + ((eq hi-lock-file-patterns-policy 'always) t) (t nil))) (hi-lock-set-file-patterns all-patterns) (if (called-interactively-p 'interactive) @@ -866,12 +869,31 @@ SPACES-REGEXP is a regexp to substitute spaces in font-lock search." (defun hi-lock-revert-buffer-rehighlight () "Rehighlight hi-lock patterns after `revert-buffer'. Apply the previous patterns after reverting the buffer." - (when-let ((patterns hi-lock-interactive-lighters)) - (lambda () - (when hi-lock-interactive-lighters - (hi-lock-unface-buffer t)) - (dolist (pattern (reverse patterns)) - (highlight-regexp (car pattern) (cadr (nth 1 (caddr pattern)))))))) + (when (or hi-lock-interactive-lighters hi-lock-file-patterns) + (let ((patterns hi-lock-interactive-lighters) + (policy (if hi-lock-file-patterns 'always 'never)) + rehighlight) + (lambda () + ;; When using revert-buffer without preserve-modes + (unless hi-lock-mode + ;; Don't ask about file patterns again + (let ((hi-lock-file-patterns-policy policy)) + (hi-lock-mode 1)) + (setq rehighlight t)) + ;; When using hi-lock overlays, then need to update them + (unless (and font-lock-mode (font-lock-specified-p major-mode) + (not hi-lock-use-overlays)) + (hi-lock-unface-buffer t) + (setq rehighlight t)) + (when rehighlight + (setq hi-lock--unused-faces hi-lock-face-defaults) + (dolist (pattern (reverse patterns)) + (let ((face (hi-lock-keyword->face (cdr pattern)))) + (highlight-regexp (or (get-text-property 0 'regexp (car pattern)) + (car pattern)) + face) + (setq hi-lock--unused-faces + (remove (face-name face) hi-lock--unused-faces))))))))) (defvar hi-lock--hashcons-hash (make-hash-table :test 'equal :weakness t) diff --git a/lisp/ibuffer.el b/lisp/ibuffer.el index c65213f5bde..c1e7788d2e8 100644 --- a/lisp/ibuffer.el +++ b/lisp/ibuffer.el @@ -2374,7 +2374,8 @@ In Ibuffer, you can conveniently perform many operations on the currently open buffers, in addition to filtering your view to a particular subset of them, and sorting by various criteria. -Operations on marked buffers: +Operations on marked buffers (see \"Marking commands\" below + for how to mark buffers): \\ \\[ibuffer-do-save] - Save the marked buffers. \\[ibuffer-do-view] - View the marked buffers in the selected frame. 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/language/cyrillic.el b/lisp/language/cyrillic.el index 87a67915878..f5eef11cfde 100644 --- a/lisp/language/cyrillic.el +++ b/lisp/language/cyrillic.el @@ -33,23 +33,12 @@ ;; are converted to Unicode internally. See ;; . For more info ;; on Cyrillic charsets, see -;; . The KOI and -;; Alternativnyj coding systems should live in code-pages.el, but -;; they've always been preloaded and the coding system autoload -;; mechanism didn't get accepted, so they have to stay here and -;; duplicate code-pages stuff. +;; . ;; Note that 8859-5 maps directly onto the Unicode Cyrillic block, ;; apart from codepoints 160 (NBSP, c.f. U+0400), 173 (soft hyphen, ;; c.f. U+04OD) and 253 (section sign, c.f U+045D). The KOI-8 and ;; Alternativnyj coding systems encode both 8859-5 and Unicode. -;; ucs-tables.el provides unification for cyrillic-iso-8bit. - -;; Customizing `utf-fragment-on-decoding' allows decoding characters -;; from KOI and Alternativnyj into 8859-5 where that's possible. -;; cyrillic-iso8859-5 characters take half as much space in the buffer -;; as the mule-unicode-0100-24ff equivalents, though that's probably -;; not normally a big deal. ;;; Code: diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el index ae4a43797f0..0459db85dbf 100644 --- a/lisp/ls-lisp.el +++ b/lisp/ls-lisp.el @@ -70,7 +70,10 @@ (defun ls-lisp-set-options () "Reset the ls-lisp options that depend on `ls-lisp-emulation'." (mapc 'custom-reevaluate-setting - '(ls-lisp-ignore-case ls-lisp-dirs-first ls-lisp-verbosity))) + '(ls-lisp-ignore-case + ls-lisp-dirs-first + ls-lisp-verbosity + ls-lisp-use-string-collate))) (defcustom ls-lisp-emulation (cond ;; ((eq system-type 'windows-nt) 'MS-Windows) diff --git a/lisp/mail/feedmail.el b/lisp/mail/feedmail.el index 165aafae1f7..ec618940641 100644 --- a/lisp/mail/feedmail.el +++ b/lisp/mail/feedmail.el @@ -1318,7 +1318,7 @@ Then add the functions you want called to either `feedmail-mail-send-hook-queued' or `feedmail-mail-send-hook', as appropriate. The distinction is that `feedmail-mail-send-hook' will be called when you send mail from a composition -buffer (typically by typing C-c C-c), whether the message is sent +buffer (typically by typing \\`C-c C-c'), whether the message is sent immediately or placed in the queue or drafts directory. `feedmail-mail-send-hook-queued' is called when messages are being sent from the queue directory, typically via a call to @@ -1443,10 +1443,11 @@ Called for each message read back out of the queue directory with a single argument, the optional argument used in the call to `feedmail-run-the-queue' or `feedmail-run-the-queue-no-prompts'. Interactively, that argument will be the prefix argument. -Most people want `mail-send' (bound to C-c C-s in mail-mode), but here's +\\ +Most people want `mail-send' (bound to \\[mail-send] in `mail-mode'), but here's your chance to have something different. The default value is just a wrapper function which discards the optional argument and calls -mail-send. If you are a VM user, you might like vm-mail-send, though +`mail-send'. If you are a VM user, you might like vm-mail-send, though you really don't need that. Called with funcall, not call-interactively." :version "24.1" ; changed default :group 'feedmail-queue diff --git a/lisp/mail/mail-extr.el b/lisp/mail/mail-extr.el index cfdbc1b2509..083bab62cab 100644 --- a/lisp/mail/mail-extr.el +++ b/lisp/mail/mail-extr.el @@ -618,7 +618,7 @@ Unless NO-REPLACE is true, at each of the positions in LIST-SYMBOL which lie outside of the range, one character at that position is replaced with a SPC." (or (memq no-replace '(t nil)) - (error "no-replace must be t or nil, evaluable at macroexpand-time")) + (error "`no-replace' must be t or nil, evaluable at macroexpand-time")) `(let ((temp ,list-symbol) ch) (while temp diff --git a/lisp/mail/rmail.el b/lisp/mail/rmail.el index 2b119c7a5c7..5e3633d221c 100644 --- a/lisp/mail/rmail.el +++ b/lisp/mail/rmail.el @@ -519,8 +519,7 @@ For a given message, Rmail applies only the first matching directive. Examples: (\"/dev/null\" \"from\" \"@spam.com\") ; delete all mail from spam.com - (\"RMS\" \"from\" \"rms@\") ; save all mail from RMS. -" + (\"RMS\" \"from\" \"rms@\") ; save all mail from RMS." :group 'rmail :version "21.1" :type '(repeat (sexp :tag "Directive"))) @@ -3686,7 +3685,12 @@ If BUFFER is not swapped, yank out of its message viewer buffer." other-headers) (let ((switch-function (cond (same-window nil) - (rmail-mail-new-frame 'switch-to-buffer-other-frame) + (rmail-mail-new-frame + (progn + ;; Record the frame from which we invoked this command. + (modify-frame-parameters (selected-frame) + '((rmail-orig-frame . t))) + 'switch-to-buffer-other-frame)) (t 'switch-to-buffer-other-window))) yank-action) (if replybuffer @@ -3716,6 +3720,11 @@ If BUFFER is not swapped, yank out of its message viewer buffer." (modify-frame-parameters (selected-frame) '((mail-dedicated-frame . t))))))) +(defun rmail--find-orig-rmail-frame () + (car (filtered-frame-list + (lambda (frame) + (eq (frame-parameter frame 'rmail-orig-frame) t))))) + (defun rmail-mail-return (&optional newbuf) "Try to return to Rmail from the mail window. If optional argument NEWBUF is specified, it is the Rmail buffer @@ -3757,9 +3766,19 @@ to switch to." ;; probably wants to delete it now. ((display-multi-frame-p) (delete-frame)) - ;; The previous frame is where normally they have the Rmail buffer - ;; displayed. - (t (other-frame -1)))) + (t + ;; Try to find the original Rmail frame and make it the top frame. + (let ((fr (selected-frame)) + (orig-fr (rmail--find-orig-rmail-frame))) + (if orig-fr + (progn + (modify-frame-parameters orig-fr '((rmail-orig-frame . nil))) + (select-frame-set-input-focus orig-fr)) + ;; If we cannot find the frame from which we started, punt, and + ;; display the previous frame, which is where they normally have + ;; the Rmail buffer displayed. + (other-frame -1)) + (delete-frame fr))))) (defun rmail-mail () "Send mail in another window. @@ -4295,7 +4314,7 @@ In fact, the non-nil value returned is the summary buffer itself." rmail-summary-buffer)) (defun rmail-summary-displayed () - "t if in RMAIL buffer and an associated summary buffer is displayed." + "Return t if in RMAIL buffer and an associated summary buffer is displayed." (and rmail-summary-buffer (get-buffer-window rmail-summary-buffer))) (defcustom rmail-redisplay-summary nil diff --git a/lisp/mail/rmailmm.el b/lisp/mail/rmailmm.el index 422fe3a7227..b4a0e92136e 100644 --- a/lisp/mail/rmailmm.el +++ b/lisp/mail/rmailmm.el @@ -170,7 +170,7 @@ The value is usually nil, and bound to non-nil while inserting MIME entities.") (defvar rmail-mime-searching nil - "Bound to T inside `rmail-search-mime-message' to suppress expensive + "Bound to t inside `rmail-search-mime-message' to suppress expensive operations such as HTML decoding") ;;; MIME-entity object diff --git a/lisp/mail/sendmail.el b/lisp/mail/sendmail.el index d54fb51dfd3..a720df51d14 100644 --- a/lisp/mail/sendmail.el +++ b/lisp/mail/sendmail.el @@ -671,8 +671,8 @@ switching to, the `*mail*' buffer. See also `mail-setup-hook'." "Major mode for editing mail to be sent. Like Text Mode but with these additional commands: -\\[mail-send] mail-send (send the message) -\\[mail-send-and-exit] mail-send-and-exit (send the message and exit) +\\[mail-send] `mail-send' (send the message) +\\[mail-send-and-exit] `mail-send-and-exit' (send the message and exit) Here are commands that move to a header field (and create it if there isn't): \\[mail-to] move to To: \\[mail-subject] move to Subj: @@ -681,9 +681,9 @@ Here are commands that move to a header field (and create it if there isn't): \\[mail-mail-reply-to] move to Mail-Reply-To: \\[mail-mail-followup-to] move to Mail-Followup-To: \\[mail-text] move to message text. -\\[mail-signature] mail-signature (insert `mail-signature-file' file). -\\[mail-yank-original] mail-yank-original (insert current message, in Rmail). -\\[mail-fill-yanked-message] mail-fill-yanked-message (fill what was yanked). +\\[mail-signature] `mail-signature' (insert `mail-signature-file' file). +\\[mail-yank-original] `mail-yank-original' (insert current message, in Rmail). +\\[mail-fill-yanked-message] `mail-fill-yanked-message' (fill what was yanked). \\[mail-insert-file] insert a text file into the message. \\[mail-add-attachment] attach to the message a file as binary attachment. Turning on Mail mode runs the normal hooks `text-mode-hook' and diff --git a/lisp/mail/supercite.el b/lisp/mail/supercite.el index 9104feb6219..add1582d72a 100644 --- a/lisp/mail/supercite.el +++ b/lisp/mail/supercite.el @@ -727,7 +727,7 @@ If optional ATTRIBS-P is non-nil, the key/value pair is placed in ;; mail header nuking (defvar sc-mail-last-header-nuked-p nil - "True if the last header was nuked.") + "Non-nil if the last header was nuked.") (defun sc-mail-nuke-line () "Nuke the current mail header line." diff --git a/lisp/mh-e/mh-e.el b/lisp/mh-e/mh-e.el index 1a535620602..3d686b4a777 100644 --- a/lisp/mh-e/mh-e.el +++ b/lisp/mh-e/mh-e.el @@ -1104,7 +1104,7 @@ and GNU mailutils." :package-version '(MH-E . "8.0")) (defgroup mh-tool-bar nil - "The tool bar" + "The tool bar." :link '(custom-manual "(mh-e)Tool Bar") :prefix "mh-" :group 'mh-e diff --git a/lisp/mh-e/mh-folder.el b/lisp/mh-e/mh-folder.el index 1dae9a600fd..c90537f1502 100644 --- a/lisp/mh-e/mh-folder.el +++ b/lisp/mh-e/mh-folder.el @@ -520,8 +520,8 @@ font-lock is done highlighting.") ;; Autoload cookie needed by desktop.el ;;;###autoload (define-derived-mode mh-folder-mode fundamental-mode "MH-Folder" - "Major MH-E mode for \"editing\" an MH folder scan listing.\\ - + "Major MH-E mode for \"editing\" an MH folder scan listing. +\\ You can show the message the cursor is pointing to, and step through the messages. Messages can be marked for deletion or refiling into another folder; these commands are executed all at once with a diff --git a/lisp/mh-e/mh-search.el b/lisp/mh-e/mh-search.el index 59dad161c11..5ee70ae081d 100644 --- a/lisp/mh-e/mh-search.el +++ b/lisp/mh-e/mh-search.el @@ -539,7 +539,7 @@ group of results." ;;; Search Menu (easy-menu-define - mh-pick-menu mh-search-mode-map "Menu for MH-E Search" + mh-pick-menu mh-search-mode-map "Menu for MH-E Search." '("Search" ["Perform Search" mh-index-do-search t] ["Search with pick" mh-pick-do-search t])) @@ -594,8 +594,8 @@ as well.") (put 'mh-search-mode 'mode-class 'special) (define-derived-mode mh-search-mode fundamental-mode "MH-Search" - "Mode for creating search templates in MH-E.\\ - + "Mode for creating search templates in MH-E. +\\ Edit this template by entering your search criteria in an appropriate header field that is already there, or create a new field yourself. If the string you're looking for could be diff --git a/lisp/mh-e/mh-show.el b/lisp/mh-e/mh-show.el index 0f90fd6f057..96b148ab49c 100644 --- a/lisp/mh-e/mh-show.el +++ b/lisp/mh-e/mh-show.el @@ -818,8 +818,8 @@ operation." ;;;###mh-autoload (define-derived-mode mh-show-mode text-mode "MH-Show" - "Major mode for showing messages in MH-E.\\ - + "Major mode for showing messages in MH-E. +\\ Email addresses and URLs in the message are highlighted if the option `goto-address-highlight-p' is on, which it is by default. To view the web page for a highlighted URL or to send a message diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index 7eb66bb062b..4ea57ee6572 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -227,14 +227,14 @@ ;; Tips for using ange-ftp: ;; -;; 1. For dired to work on a host which marks symlinks with a trailing @ in +;; 1. For Dired to work on a host which marks symlinks with a trailing @ in ;; an ls -alF listing, you need to (setq dired-ls-F-marks-symlinks t). ;; Most UNIX systems do not do this, but ULTRIX does. If you think that ;; there is a chance you might connect to an ULTRIX machine (such as ;; prep.ai.mit.edu), then set this variable accordingly. This will have -;; the side effect that dired will have problems with symlinks whose names +;; the side effect that Dired will have problems with symlinks whose names ;; end in an @. If you get yourself into this situation then editing -;; dired's ls-switches to remove "F", will temporarily fix things. +;; Dired's ls-switches to remove "F", will temporarily fix things. ;; ;; 2. If you know that you are connecting to a certain non-UNIX machine ;; frequently, and ange-ftp seems to be unable to guess its host-type, @@ -257,8 +257,8 @@ ;; moving them through the local machine. Again, be careful when doing ;; this with binary files on non-Unix machines. ;; -;; 5. Beware that dired over ftp will use your setting of dired-no-confirm -;; (list of dired commands for which confirmation is not asked). You +;; 5. Beware that Dired over ftp will use your setting of dired-no-confirm +;; (list of Dired commands for which confirmation is not asked). You ;; might want to reconsider your setting of this variable, because you ;; might want confirmation for more commands on remote direds than on ;; local direds. For example, I strongly recommend that you not include @@ -266,7 +266,7 @@ ;; might be a good idea to have an alist ange-ftp-dired-no-confirm of ;; pairs ( TYPE . LIST ), where TYPE is an operating system type and LIST ;; is a list of commands for which confirmation would be suppressed. Then -;; remote dired listings would take their (buffer-local) value of +;; remote Dired listings would take their (buffer-local) value of ;; dired-no-confirm from this alist. Who votes for this? ;; --------------------------------------------------------------------- @@ -317,7 +317,7 @@ ;; overwrite FILE.TXT;3, but instead will want to create FILE.TXT;4, and ;; attach the buffer to this file. To get out of this situation, M-x ;; write-file /ymir.claremont.edu:FILE.TXT will attach the buffer to -;; latest version of the file. For this reason, in dired "f" +;; latest version of the file. For this reason, in Dired "f" ;; (dired-find-file), always loads the file sans version, whereas "v", ;; (dired-view-file), always loads the explicit version number. The ;; reasoning being that it reasonable to view old versions of a file, but @@ -514,7 +514,7 @@ ;; containing spaces, but beware that the remote ftpd may not like them ;; much. ;; -;; 12. The dired support for non-Unix-like systems does not currently work. +;; 12. The Dired support for non-Unix-like systems does not currently work. ;; It needs to be reimplemented by modifying the parse-...-listing ;; functions to convert the directory listing to ls -l format. ;; @@ -524,8 +524,8 @@ ;; parsing a listing with the F switch. This will cause ange-ftp to ;; incorrectly get the name of a symlink on a non-ULTRIX host if its name ;; ends in an @. ange-ftp will correct itself if you take F out of the -;; dired ls switches (C-u s will allow you to edit the switches). The -;; dired buffer will be automatically reverted, which will allow ange-ftp +;; Dired ls switches (C-u s will allow you to edit the switches). The +;; Dired buffer will be automatically reverted, which will allow ange-ftp ;; to fix its files hashtable. A cookie to anyone who can think of a ;; fast, sure-fire way to recognize ULTRIX over ftp. @@ -611,9 +611,9 @@ ;; Thanks to Jamie Zawinski for bugfixes and for ideas such as gateways. ;; ;; Thanks to Ken Laprade for improved .netrc parsing, password reading, and -;; dired / shell auto-loading. +;; Dired / shell auto-loading. ;; -;; Thanks to Sebastian Kremer for dired support and for many ideas and +;; Thanks to Sebastian Kremer for Dired support and for many ideas and ;; bugfixes. ;; ;; Thanks to Joe Wells for bugfixes, the original non-UNIX system support, diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index f22aa19f5e3..e7912a2a4a7 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -113,10 +113,10 @@ ;; Use the Emacs Web Wowser (EWW) when not running under X11: ;; (or (eq window-system 'x) -;; (setq browse-url-browser-function #'eww-browse-url)) +;; (setopt browse-url-browser-function #'eww-browse-url)) ;; To always save modified buffers before displaying the file in a browser: -;; (setq browse-url-save-file t) +;; (setopt browse-url-save-file t) ;; To invoke different browsers/tools for different URLs, customize ;; `browse-url-handlers'. In earlier versions of Emacs, the same @@ -419,14 +419,14 @@ value converts ange-ftp-style file names into ftp URLs and prepends `file:' to any file name beginning with `/'. For example, adding to the default a specific translation of an ange-ftp -address to an HTTP URL: +address to an HTTPS URL: - (setq browse-url-filename-alist - \\='((\"/webmaster@webserver:/home/www/html/\" . - \"https://www.example.org/\") - (\"^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*\" . \"ftp://\\2/\") - (\"^/\\([^:@/]+@\\)?\\([^:/]+\\):/*\" . \"ftp://\\1\\2/\") - (\"^/+\" . \"file:/\")))" + (setopt browse-url-filename-alist + \\='((\"/webmaster@webserver:/home/www/html/\" . + \"https://www.example.org/\") + (\"^/\\(ftp@\\|anonymous@\\)?\\([^:/]+\\):/*\" . \"ftp://\\2/\") + (\"^/\\([^:@/]+@\\)?\\([^:/]+\\):/*\" . \"ftp://\\1\\2/\") + (\"^/+\" . \"file:/\")))" :type '(repeat (cons :format "%v" (regexp :tag "Regexp") (string :tag "Replacement"))) @@ -683,6 +683,7 @@ websites are increasingly rare, but they do still exist." :type '(choice (const :tag "HTTP" "http") (const :tag "HTTPS" "https") (string :tag "Something else" "https")) + :risky t :version "29.1") (defun browse-url-url-at-point () diff --git a/lisp/net/dbus.el b/lisp/net/dbus.el index dd5f0e88859..8426d04fefd 100644 --- a/lisp/net/dbus.el +++ b/lisp/net/dbus.el @@ -192,6 +192,10 @@ See /usr/include/dbus-1.0/dbus/dbus-protocol.h.") (defconst dbus-error-failed (concat dbus-error-dbus ".Failed") "A generic error; \"something went wrong\" - see the error message for more.") +(defconst dbus-error-interactive-authorization-required + (concat dbus-error-dbus ".InteractiveAuthorizationRequired") + "Interactive authentication required.") + (defconst dbus-error-invalid-args (concat dbus-error-dbus ".InvalidArgs") "Invalid arguments passed to a method call.") @@ -243,7 +247,9 @@ Otherwise, return result of last form in BODY, or all other errors." (progn ,@body) (dbus-error (when dbus-debug (signal (car err) (cdr err)))))) -(defvar dbus-event-error-functions '(dbus-notice-synchronous-call-errors) +(defvar dbus-event-error-functions + '(dbus-notice-synchronous-call-errors + dbus-warn-interactive-authorization-required) "Functions to be called when a D-Bus error happens in the event handler. Every function must accept two arguments, the event and the error variable caught in `condition-case' by `dbus-error'.") @@ -282,6 +288,18 @@ The result will be made available in `dbus-return-values-table'." (setcar result :error) (setcdr result er)))) +(defun dbus-warn-interactive-authorization-required (ev er) + "Detect `dbus-error-interactive-authorization-required'." + (when (string-equal (cadr er) dbus-error-interactive-authorization-required) + (lwarn 'dbus :warning "%S" (cdr er)) + (let* ((key (list :serial + (dbus-event-bus-name ev) + (dbus-event-serial-number ev))) + (result (gethash key dbus-return-values-table))) + (when (consp result) + (setcar result :complete) + (setcdr result nil))))) + (defun dbus-call-method (bus service path interface method &rest args) "Call METHOD on the D-Bus BUS. @@ -297,6 +315,10 @@ TIMEOUT specifies the maximum number of milliseconds before the method call must return. The default value is 25,000. If the method call doesn't return in time, a D-Bus error is raised. +If the parameter `:authorizable' is given and the following AUTH +is non-nil, the invoked method may interactively prompt the user +for authorization. The default is nil. + All other arguments ARGS are passed to METHOD as arguments. They are converted into D-Bus types via the following rules: @@ -427,6 +449,10 @@ TIMEOUT specifies the maximum number of milliseconds before the method call must return. The default value is 25,000. If the method call doesn't return in time, a D-Bus error is raised. +If the parameter `:authorizable' is given and the following AUTH +is non-nil, the invoked method may interactively prompt the user +for authorization. The default is nil. + All other arguments ARGS are passed to METHOD as arguments. They are converted into D-Bus types via the following rules: diff --git a/lisp/net/dictionary.el b/lisp/net/dictionary.el index b12f3fa4368..f17dc160997 100644 --- a/lisp/net/dictionary.el +++ b/lisp/net/dictionary.el @@ -472,7 +472,7 @@ Otherwise, `dictionary-search' displays definitions in a *Dictionary* buffer." :vert-only t :help "Go backwards in history.") map) - "Like the default `tool-bar-map', but with additions for Dictionary mode") + "Like the default `tool-bar-map', but with additions for Dictionary mode.") ;;;###autoload (define-derived-mode dictionary-mode special-mode "Dictionary" diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el index ea90e4a7e77..da8955d52c9 100644 --- a/lisp/net/eudc.el +++ b/lisp/net/eudc.el @@ -382,7 +382,7 @@ The translation is done according to When REVERSE is nil or omitted, the attribute names are translated from EUDC generic names to protocol-specific -names. When REVERSE is non-nil, the translation is from +names. When REVERSE is non-nil, the translation is from protocol-specific names back to EUDC generic names." (if eudc-protocol-attributes-translation-alist (mapcar (lambda (attribute) @@ -406,7 +406,7 @@ The translation is done according to When REVERSE is nil or omitted, the attribute names are translated from EUDC generic names to protocol-specific -names. When REVERSE is non-nil, the translation is from +names. When REVERSE is non-nil, the translation is from protocol-specific names back to EUDC generic names." (if eudc-protocol-attributes-translation-alist (let (trans) @@ -918,7 +918,7 @@ non-nil, collect results from all servers." (if valid-comment-given comment nil))) (progn (error "Error: the function referenced by \ -`eudc-inline-expansion-format' is expected to return a list.") +`eudc-inline-expansion-format' is expected to return a list") nil)))) ;; fallback behavior (nil function, or non-matching type) @@ -1110,7 +1110,7 @@ queries the server for the existing fields and displays a corresponding form." (eudc-install-menu) (if eudc-ignore-options-file (warn "Not saving bookmark due to `eudc-ignore-options-file'\ - customization. Instead, customize `eudc-server-hotlist' to include %s:%s" + customization. Instead, customize `eudc-server-hotlist' to include %s:%s" protocol server) (eudc-save-options)))) diff --git a/lisp/net/eww.el b/lisp/net/eww.el index fd8f80065b1..b2e1c5a72e5 100644 --- a/lisp/net/eww.el +++ b/lisp/net/eww.el @@ -1306,7 +1306,7 @@ This consults the entries in `eww-readable-urls' (which see)." "Check if point is within a field and toggle text conversion. Set `text-conversion-style' to the value `action' if it isn't already and point is within the prompt field, or if -`text-conversion-style' is `nil', so as to guarantee that +`text-conversion-style' is nil, so as to guarantee that the input method functions properly for the purpose of typing within text input fields." (when (and (eq major-mode 'eww-mode) @@ -1370,13 +1370,22 @@ 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))) - (unless (image-property image :original-scale) - (setf (image-property image :original-scale) - (or (image-property image :scale) 1))) + '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) + 'default))))) + (when (eq original-scale 'default) + (setq original-scale (image-compute-scaling-factor + image-scaling-factor))) (setf (image-property image :scale) - (* (image-property image :original-scale) scaling))))))) + (* original-scale scaling))))))) (defun eww--url-at-point () "`thing-at-point' provider function." 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/imap.el b/lisp/net/imap.el index a06740528e9..614fc56b513 100644 --- a/lisp/net/imap.el +++ b/lisp/net/imap.el @@ -228,7 +228,7 @@ See also `imap-log'." :type 'boolean) (defcustom imap-shell-host "gateway" - "Hostname of rlogin proxy." + "Hostname of SSH proxy." :type 'string) (defcustom imap-default-user (user-login-name) diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index b913ba9e0a3..659035d4acb 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -1197,7 +1197,7 @@ With no argument or nil as argument, use the current buffer." "Return PROCESS server name, given by the 001 response." (with-rcirc-process-buffer process (or rcirc-server-name - (warn "server name for process %S unknown" process)))) + (warn "Server name for process %S unknown" process)))) (defun rcirc-nick (process) "Return PROCESS nick." diff --git a/lisp/net/shr.el b/lisp/net/shr.el index 3dadcb9a09b..39271cc5296 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 (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 @@ -2261,8 +2342,9 @@ See `outline-search-function' for BOUND, MOVE, BACKWARD and LOOKING-AT." (defun shr--fix-tbody (tbody) (nconc (list 'tbody (dom-attributes tbody)) (cl-loop for child in (dom-children tbody) - collect (if (or (stringp child) - (not (eq (dom-tag child) 'tr))) + for tag = (and (not (stringp child)) (dom-tag child)) + unless (or (eq tag 'thead) (eq tag 'tfoot)) + collect (if (not (eq tag 'tr)) (list 'tr nil (list 'td nil child)) child)))) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 5b1c4ba5b19..b26a93fc6e4 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -919,7 +919,7 @@ will be used." (defun tramp-adb-handle-get-remote-uid (vec id-format) "Like `tramp-get-remote-uid' for Tramp files. - ID-FORMAT valid values are `string' and `integer'." +ID-FORMAT valid values are `string' and `integer'." (tramp-adb-send-command vec "id") (tramp-read-id-output vec) (tramp-get-connection-property vec (format "uid-%s" id-format))) diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index ecb9071eb57..5b2646a0b03 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -630,7 +630,7 @@ If the buffer runs `dired', the buffer is reverted." ;;;###tramp-autoload (defun tramp-recompile-elpa-command-completion-p (_symbol _buffer) "A predicate for `tramp-recompile-elpa'. -It is completed by \"M-x TAB\" only if package.el is loaded, and +It is completed by `M-x TAB' only if package.el is loaded, and Tramp is an installed ELPA package." ;; We cannot apply `package-installed-p', this would also return the ;; builtin package. diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index 1d6f47dc364..8781230c00c 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el @@ -46,18 +46,22 @@ (unless (= emacs-major-version (car (version-to-list tramp-compat-emacs-compiled-version))) - (warn "Tramp has been compiled with Emacs %s, this is Emacs %s" + (lwarn 'tramp :warning + "Tramp has been compiled with Emacs %s, this is Emacs %s" tramp-compat-emacs-compiled-version emacs-version)) (with-eval-after-load 'docker-tramp - (warn (concat "Package `docker-tramp' has been obsoleted, " - "please use integrated package `tramp-container'"))) + (lwarn 'tramp :warning + (concat "Package `docker-tramp' has been obsoleted, " + "please use integrated package `tramp-container'"))) (with-eval-after-load 'kubernetes-tramp - (warn (concat "Package `kubernetes-tramp' has been obsoleted, " - "please use integrated package `tramp-container'"))) + (lwarn 'tramp :warning + (concat "Package `kubernetes-tramp' has been obsoleted, " + "please use integrated package `tramp-container'"))) (with-eval-after-load 'tramp-nspawn - (warn (concat "Package `tramp-nspawn' has been obsoleted, " - "please use integrated package `tramp-container'"))) + (lwarn 'tramp :warning + (concat "Package `tramp-nspawn' has been obsoleted, " + "please use integrated package `tramp-container'"))) ;; For not existing functions, obsolete functions, or functions with a ;; changed argument list, there are compiler warnings. We want to diff --git a/lisp/net/tramp-crypt.el b/lisp/net/tramp-crypt.el index a7af64bff5c..d44a656035d 100644 --- a/lisp/net/tramp-crypt.el +++ b/lisp/net/tramp-crypt.el @@ -117,7 +117,7 @@ initializing a new encrypted remote directory." ;; `command-completion-default-include-p'. (defun tramp-crypt-command-completion-p (symbol _buffer) "A predicate for Tramp interactive commands. -They are completed by \"M-x TAB\" only when encryption support is enabled." +They are completed by `M-x TAB' only when encryption support is enabled." (and tramp-crypt-enabled ;; `tramp-crypt-remove-directory' needs to be completed only in ;; case we have already encrypted directories. diff --git a/lisp/net/tramp-message.el b/lisp/net/tramp-message.el index 8d6458ce07a..36079c8844c 100644 --- a/lisp/net/tramp-message.el +++ b/lisp/net/tramp-message.el @@ -127,7 +127,7 @@ The outline level is equal to the verbosity of the Tramp message." ;; `command-completion-default-include-p'. (defun tramp-debug-buffer-command-completion-p (_symbol buffer) "A predicate for Tramp interactive commands. -They are completed by \"M-x TAB\" only in Tramp debug buffers." +They are completed by `M-x TAB' only in Tramp debug buffers." (declare (tramp-suppress-trace t)) (with-current-buffer buffer (string-equal @@ -468,8 +468,7 @@ to `tramp-message'." (declare (tramp-suppress-trace t)) (let (signal-hook-function) (apply 'tramp-message vec-or-proc 2 fmt-string arguments) - (display-warning - 'tramp (apply #'format-message fmt-string arguments) :warning))) + (lwarn 'tramp :warning fmt-string arguments))) (defun tramp-test-message (fmt-string &rest arguments) "Emit a Tramp message according `default-directory'." diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index bce7c323dad..4a0c09ff722 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -107,7 +107,7 @@ detected as prompt when being sent on echoing hosts, therefore.") (defcustom tramp-use-connection-share (not (eq system-type 'windows-nt)) "Whether to use connection share in ssh or PuTTY. -Set it to t, if you want Tramp to apply respective options. These +Set it to t, if you want Tramp to apply respective options. These are `tramp-ssh-controlmaster-options' for ssh, and \"-share\" for PuTTY. Set it to nil, if you use Control* or Proxy* options in your ssh configuration. diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index f97ed66c58b..e8329c82743 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -78,6 +78,7 @@ (defvar tramp-postfix-ipv6-regexp) (defvar tramp-postfix-host-format) (defvar tramp-postfix-host-regexp) +(defvar tramp-host-with-port-regexp) (defvar tramp-remote-file-name-spec-regexp) (defvar tramp-file-name-structure) (defvar tramp-file-name-regexp) @@ -878,6 +879,7 @@ to be set, depending on VALUE." tramp-postfix-ipv6-regexp (tramp-build-postfix-ipv6-regexp) tramp-postfix-host-format (tramp-build-postfix-host-format) tramp-postfix-host-regexp (tramp-build-postfix-host-regexp) + tramp-host-with-port-regexp (tramp-build-host-with-port-regexp) tramp-remote-file-name-spec-regexp (tramp-build-remote-file-name-spec-regexp) tramp-file-name-structure (tramp-build-file-name-structure) @@ -955,7 +957,8 @@ The `ftp' syntax does not support methods.") "Return `tramp-postfix-method-format' according to `tramp-syntax'." (tramp-lookup-syntax tramp-postfix-method-format-alist)) -(defvar tramp-postfix-method-format nil ; Init'd when defining `tramp-syntax'! +(defvar tramp-postfix-method-format + nil ; Initialized when defining `tramp-syntax'! "String matching delimiter between method and user or host names. The `ftp' syntax does not support methods. Used in `tramp-make-tramp-file-name'.") @@ -964,7 +967,8 @@ Used in `tramp-make-tramp-file-name'.") "Return `tramp-postfix-method-regexp'." (rx (literal (tramp-build-postfix-method-format)))) -(defvar tramp-postfix-method-regexp nil ; Init'd when defining `tramp-syntax'! +(defvar tramp-postfix-method-regexp + nil ; Initialized when defining `tramp-syntax'! "Regexp matching delimiter between method and user or host names. Derived from `tramp-postfix-method-format'.") @@ -1059,11 +1063,18 @@ Derived from `tramp-prefix-port-format'.") (defconst tramp-port-regexp (rx (+ digit)) "Regexp matching port numbers.") -(defconst tramp-host-with-port-regexp +(defun tramp-build-host-with-port-regexp () + "Return `tramp-host-with-port-regexp'." (rx - (group (regexp tramp-host-regexp)) + (group (| (regexp tramp-host-regexp) + (: (regexp tramp-prefix-ipv6-regexp) + (? (regexp tramp-ipv6-regexp)) + (regexp tramp-postfix-ipv6-regexp)))) (regexp tramp-prefix-port-regexp) - (group (regexp tramp-port-regexp))) + (group (regexp tramp-port-regexp)))) + +(defvar tramp-host-with-port-regexp + nil ; Initialized when defining `tramp-syntax'! "Regexp matching host names with port numbers.") (defconst tramp-postfix-hop-format "|" @@ -2688,7 +2699,7 @@ Run BODY." ;; `command-completion-default-include-p'. (defun tramp-command-completion-p (_symbol buffer) "A predicate for Tramp interactive commands. -They are completed by \"M-x TAB\" only if the current buffer is remote." +They are completed by `M-x TAB' only if the current buffer is remote." (tramp-tramp-file-p (tramp-get-default-directory buffer))) (defun tramp-connectable-p (vec-or-filename) diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el index a0dbd3d55fb..8b2700a0d96 100644 --- a/lisp/net/trampver.el +++ b/lisp/net/trampver.el @@ -7,7 +7,7 @@ ;; Maintainer: Michael Albinus ;; Keywords: comm, processes ;; Package: tramp -;; Version: 2.7.1-pre +;; Version: 2.7.2-pre ;; Package-Requires: ((emacs "27.1")) ;; Package-Type: multi ;; URL: https://www.gnu.org/software/tramp/ @@ -40,7 +40,7 @@ ;; ./configure" to change them. ;;;###tramp-autoload -(defconst tramp-version "2.7.1-pre" +(defconst tramp-version "2.7.2-pre" "This version of Tramp.") ;;;###tramp-autoload @@ -78,7 +78,7 @@ ;; Check for Emacs version. (let ((x (if (not (string-version-lessp emacs-version "27.1")) "ok" - (format "Tramp 2.7.1-pre is not fit for %s" + (format "Tramp 2.7.2-pre is not fit for %s" (replace-regexp-in-string "\n" "" (emacs-version)))))) (unless (string-equal "ok" x) (error "%s" x))) @@ -106,7 +106,8 @@ ("2.4.3.27.1" . "27.1") ("2.4.5.27.2" . "27.2") ("2.5.2.28.1" . "28.1") ("2.5.3.28.2" . "28.2") ("2.5.4" . "28.3") ("2.6.0.29.1" . "29.1") ("2.6.2.29.2" . "29.2") ("2.6.3-pre" . "29.3") - ("2.6.3" . "29.4"))) + ("2.6.3" . "29.4") + ("2.7.1.30.1" . "30.1"))) (add-hook 'tramp-unload-hook (lambda () diff --git a/lisp/org/ob-R.el b/lisp/org/ob-R.el index f365a68da81..de2d27a9a70 100644 --- a/lisp/org/ob-R.el +++ b/lisp/org/ob-R.el @@ -484,7 +484,7 @@ Returns a placeholder string for insertion, to later be replaced by `org-babel-comint-async-filter'." (org-babel-comint-async-register session (current-buffer) - "^\\(?:[>.+] \\)*\\[1\\] \"ob_comint_async_R_\\(.+?\\)_\\(.+\\)\"$" + "^\\(?:[>.+] \\)*\\[1\\] \"ob_comint_async_R_\\(start\\|end\\|file\\)_\\(.+\\)\"$" 'org-babel-chomp 'ob-session-async-R-value-callback) (cl-case result-type diff --git a/lisp/org/ob-core.el b/lisp/org/ob-core.el index db75f1f0ad5..60f213fe751 100644 --- a/lisp/org/ob-core.el +++ b/lisp/org/ob-core.el @@ -22,6 +22,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Commentary: + ;;; Code: (require 'org-macs) @@ -1778,7 +1780,7 @@ shown below. #+PROPERTY: var foo=1, bar=2 -HEADER-ARGUMENTS is alist of all the arguments." +HEADER-ARGUMENTS is an alist of all the arguments." (let (results) (mapc (lambda (pair) (if (eq (car pair) :var) @@ -2861,7 +2863,7 @@ file's directory then expand relative links. If the optional TYPE is passed as `attachment' and the path is a descendant of the DEFAULT-DIRECTORY, the generated link will be -specified as an an \"attachment:\" style link." +specified as an \"attachment:\" style link." (when (stringp result) (let* ((result-file-name (expand-file-name result)) (base-file-name (buffer-file-name (buffer-base-buffer))) @@ -2959,9 +2961,9 @@ used as a string to be appended to #+begin_example line." (goto-char body-start) (insert body)))) -(defun org-babel-merge-params (&rest plists) - "Combine all parameter association lists in PLISTS. -Later elements of PLISTS override the values of previous elements. +(defun org-babel-merge-params (&rest alists) + "Combine all parameter association lists in ALISTS. +Later elements of ALISTS override the values of previous elements. This takes into account some special considerations for certain parameters when merging lists." (let* ((results-exclusive-groups @@ -2990,8 +2992,8 @@ parameters when merging lists." ;; Some keywords accept multiple values. We need to treat ;; them specially. vars results exports) - (dolist (plist plists) - (dolist (pair plist) + (dolist (alist alists) + (dolist (pair alist) (pcase pair (`(:var . ,value) (let ((name (cond diff --git a/lisp/org/ob-exp.el b/lisp/org/ob-exp.el index 5516530c5b7..30b2a42a6c4 100644 --- a/lisp/org/ob-exp.el +++ b/lisp/org/ob-exp.el @@ -22,6 +22,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Commentary: + ;;; Code: (require 'org-macs) diff --git a/lisp/org/ob-lilypond.el b/lisp/org/ob-lilypond.el index a8d85ce7c85..ef747d9bb2c 100644 --- a/lisp/org/ob-lilypond.el +++ b/lisp/org/ob-lilypond.el @@ -160,7 +160,7 @@ Otherwise, execute block according to header settings." (org-babel-lilypond-process-basic body params))) (defun org-babel-lilypond-tangle () - "Tangle lilypond blocks, then `org-babel-liypond-execute-tangled-ly'." + "Tangle lilypond blocks, then `org-babel-lilypond-execute-tangled-ly'." (interactive) (if (org-babel-tangle nil "yes" "lilypond") (org-babel-lilypond-execute-tangled-ly) nil)) diff --git a/lisp/org/ob-lob.el b/lisp/org/ob-lob.el index 110675fc561..eaa66872f1f 100644 --- a/lisp/org/ob-lob.el +++ b/lisp/org/ob-lob.el @@ -22,6 +22,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Commentary: + ;;; Code: (require 'org-macs) diff --git a/lisp/org/ob-plantuml.el b/lisp/org/ob-plantuml.el index 17b9d140832..229b4bad2c8 100644 --- a/lisp/org/ob-plantuml.el +++ b/lisp/org/ob-plantuml.el @@ -116,7 +116,7 @@ This function is called by `org-babel-execute-src-block'." (let* ((do-export (member "file" (cdr (assq :result-params params)))) (out-file (if do-export (or (cdr (assq :file params)) - (error "No :file provided but :results set to file. For plain text output, set :results to verbatim")) + (error "No :file provided but :results set to file. For plain text output, set :results to verbatim")) (org-babel-temp-file "plantuml-" ".txt"))) (cmdline (cdr (assq :cmdline params))) (in-file (org-babel-temp-file "plantuml-")) 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/ob-python.el b/lisp/org/ob-python.el index 3f81449ebf1..8a3c24f7038 100644 --- a/lisp/org/ob-python.el +++ b/lisp/org/ob-python.el @@ -279,7 +279,7 @@ be removed after minimum supported version reaches emacs29." This checks `org-babel-python-command', and then `org-babel-python-command-session' (if IS-SESSION) or `org-babel-python-command-nonsession' (if not IS-SESSION). If -IS-SESSION, this might return `nil', which means to use +IS-SESSION, this might return nil, which means to use `python-shell-calculate-command'." (or (unless (eq org-babel-python-command 'auto) org-babel-python-command) @@ -300,7 +300,7 @@ unless the Python session was created outside Org." (defun org-babel-python-initiate-session-by-key (&optional session) "Initiate a python session. If there is not a current inferior-process-buffer matching -SESSION then create it. If inferior process already +SESSION then create it. If inferior process already exists (e.g. if it was manually started with `run-python'), make sure it's configured to work with ob-python. If session has already been configured as such, do nothing. Return the @@ -356,7 +356,7 @@ initialized session." (defun org-babel-python-initiate-session (&optional session _params) "Initiate Python session named SESSION according to PARAMS. If there is not a current inferior-process-buffer matching -SESSION then create it. If inferior process already +SESSION then create it. If inferior process already exists (e.g. if it was manually started with `run-python'), make sure it's configured to work with ob-python. If session has already been configured as such, do nothing." @@ -537,7 +537,7 @@ Returns a placeholder string for insertion, to later be replaced by `org-babel-comint-async-filter'." (org-babel-comint-async-register session (current-buffer) - "ob_comint_async_python_\\(.+\\)_\\(.+\\)" + "ob_comint_async_python_\\(start\\|end\\|file\\)_\\(.+\\)" 'org-babel-chomp 'org-babel-python-async-value-callback) (pcase result-type (`output diff --git a/lisp/org/ob-scheme.el b/lisp/org/ob-scheme.el index 3f04667f276..29fdcd1ec6d 100644 --- a/lisp/org/ob-scheme.el +++ b/lisp/org/ob-scheme.el @@ -143,14 +143,14 @@ If the variables HOST and PORT are set, connect to the running Scheme REPL." (current-buffer))))) (defun org-babel-scheme-make-session-name (buffer name impl) - "Generate a name for the session buffer. + "Generate a NAME for the session BUFFER. For a named session, the buffer name will be the session name. If the session is unnamed (nil), generate a name. If the session is `none', use nil for the session name, and -org-babel-scheme-execute-with-geiser will use a temporary session." +`org-babel-scheme-execute-with-geiser' will use a temporary session." (cond ((not name) (concat buffer " " (symbol-name impl) " REPL")) ((string= name "none") nil) (name))) diff --git a/lisp/org/ob-shell.el b/lisp/org/ob-shell.el index 35d9e93761b..1f3c0f9cef8 100644 --- a/lisp/org/ob-shell.el +++ b/lisp/org/ob-shell.el @@ -92,10 +92,10 @@ variables." name)) (funcall (if (fboundp 'defvar-1) #'defvar-1 #'set) ;Emacs-29 (intern (concat "org-babel-default-header-args:" name)) - nil) + org-babel-default-header-args:shell) (funcall (if (fboundp 'defvar-1) #'defvar-1 #'set) ;Emacs-29 (intern (concat "org-babel-header-args:" name)) - nil))) + org-babel-header-args:shell))) (defcustom org-babel-shell-names '("sh" "bash" "zsh" "fish" "csh" "ash" "dash" "ksh" "mksh" "posh") @@ -338,7 +338,7 @@ return the value of the last statement in BODY." (org-babel-comint-async-register session (current-buffer) - "ob_comint_async_shell_\\(.+\\)_\\(.+\\)" + "ob_comint_async_shell_\\(start\\|end\\|file\\)_\\(.+\\)" 'ob-shell-async-chunk-callback nil) (org-babel-comint-async-delete-dangling-and-eval diff --git a/lisp/org/ob-tangle.el b/lisp/org/ob-tangle.el index c89763efad7..fe143b039ff 100644 --- a/lisp/org/ob-tangle.el +++ b/lisp/org/ob-tangle.el @@ -184,8 +184,7 @@ replace contents otherwise." :safe t) (defun org-babel-find-file-noselect-refresh (file) - "Find file ensuring that the latest changes on disk are -represented in the file." + "Find file ensuring that the latest changes on disk are represented in the file." (find-file-noselect file 'nowarn) (with-current-buffer (get-file-buffer file) (revert-buffer t t t))) @@ -386,10 +385,10 @@ The following forms are currently recognized: ((integerp mode) (if (string-match-p "^[0-7][0-7][0-7]$" (format "%o" mode)) mode - (user-error "%1$o is not a valid file mode octal. \ + (user-error "%1$o is not a valid file mode octal. \ Did you give the decimal value %1$d by mistake?" mode))) ((not (stringp mode)) - (error "File mode %S not recognized as a valid format." mode)) + (error "File mode %S not recognized as a valid format" mode)) ((string-match-p "^o0?[0-7][0-7][0-7]$" mode) (string-to-number (replace-regexp-in-string "^o" "" mode) 8)) ((string-match-p "^[ugoa]*\\(?:[+=-][rwxXstugo]*\\)+\\(,[ugoa]*\\(?:[+=-][rwxXstugo]*\\)+\\)*$" mode) @@ -400,7 +399,7 @@ Did you give the decimal value %1$d by mistake?" mode))) ",g=" (delete ?- (substring mode 3 6)) ",o=" (delete ?- (substring mode 6 9))) 0)) - (t (error "File mode %S not recognized as a valid format. See `org-babel-interpret-file-mode'." mode)))) + (t (error "File mode %S not recognized as a valid format. See `org-babel-interpret-file-mode'" mode)))) (defun org-babel-tangle-clean () "Remove comments inserted by `org-babel-tangle'. diff --git a/lisp/org/ob.el b/lisp/org/ob.el index d3a29b83351..064faafd7cf 100644 --- a/lisp/org/ob.el +++ b/lisp/org/ob.el @@ -21,6 +21,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Commentary: + ;;; Code: (require 'org-macs) diff --git a/lisp/org/org-agenda.el b/lisp/org/org-agenda.el index 10f25be8a8d..b2a5ff92734 100644 --- a/lisp/org/org-agenda.el +++ b/lisp/org/org-agenda.el @@ -1041,7 +1041,7 @@ headlines as the agenda display heavily relies on them." :type 'hook) (defcustom org-agenda-mouse-1-follows-link nil - "Non-nil means mouse-1 on a link will follow the link in the agenda. + "Non-nil means \\`mouse-1' on a link will follow the link in the agenda. A longer mouse click will still set point. Needs to be set before org.el is loaded." :group 'org-agenda-startup @@ -1100,7 +1100,7 @@ removed from entry text before it is shown in the agenda." :type 'string) (defcustom org-agenda-start-with-archives-mode nil - "Initial value of archive-mode in a newly created agenda window. + "Initial value of archive mode in a newly created agenda window. See `org-agenda-archives-mode' for acceptable values and their meaning." :group 'org-agenda-startup @@ -9190,7 +9190,7 @@ When called with a prefix argument, include all archive files as well." (org-agenda-do-context-action)) (defun org-agenda-previous-line () - "Move cursor to the previous line, and show if follow-mode is active." + "Move cursor to the previous line, and show if follow mode is active." (interactive) (call-interactively 'previous-line) (org-agenda-do-context-action)) diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index c6fd507b08b..316cd7eee4b 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -3261,7 +3261,7 @@ The details of what will be saved are regulated by the variable (and (buffer-live-p b) (buffer-file-name b) (or (not org-clock-persist-query-save) - (y-or-n-p (format "Save current clock (%s) " + (y-or-n-p (format "Save current clock (%s)?" org-clock-heading)))))) (insert (format "(setq org-clock-stored-resume-clock '(%S . %d))\n" @@ -3301,7 +3301,7 @@ The details of what will be saved are regulated by the variable (`(,(and file (pred file-exists-p)) . ,position) (with-current-buffer (find-file-noselect file) (when (or (not org-clock-persist-query-resume) - (y-or-n-p (format "Resume clock (%s) " + (y-or-n-p (format "Resume clock (%s)?" (save-excursion (goto-char position) (org-get-heading t t))))) diff --git a/lisp/org/org-colview.el b/lisp/org/org-colview.el index 961ae0fbe54..bc93941e47d 100644 --- a/lisp/org/org-colview.el +++ b/lisp/org/org-colview.el @@ -1662,7 +1662,7 @@ definition." ;; Insert affiliated keywords before the table. (when content-lines (while (string-match-p "\\`[ \t]*#\\+" (car content-lines)) - (insert (pop content-lines) "\n"))) + (insert (string-trim-left (pop content-lines)) "\n"))) (save-excursion ;; Insert table at point. (insert @@ -1675,7 +1675,7 @@ definition." (let ((case-fold-search t)) (dolist (line content-lines) (when (string-match-p "\\`[ \t]*#\\+TBLFM:" line) - (insert "\n" line) + (insert "\n" (string-trim-left line)) (unless recalc (setq recalc t)))))) (when recalc (org-table-recalculate 'all t)) (org-table-align) diff --git a/lisp/org/org-element-ast.el b/lisp/org/org-element-ast.el index fba6b37e662..f3f74928004 100644 --- a/lisp/org/org-element-ast.el +++ b/lisp/org/org-element-ast.el @@ -231,7 +231,7 @@ when NODE is an anonymous node." (define-inline org-element-type-p (node types) "Return non-nil when NODE type is one of TYPES. - TYPES can be a type symbol or a list of symbols." +TYPES can be a type symbol or a list of symbols." (inline-letevals (node types) (if (listp (inline-const-val types)) (inline-quote (memq (org-element-type ,node t) ,types)) @@ -270,7 +270,7 @@ Return value is the containing property name, as a keyword, or nil." "Dynamically computed value. The value can be obtained by calling FUNCTION with containing syntax -node as first argument and ARGS list as remainting arguments. +node as first argument and ARGS list as remaining arguments. If the function throws `:org-element-deferred-retry' signal, assume that the syntax node has been modified by side effect and retry diff --git a/lisp/org/org-element.el b/lisp/org/org-element.el index 191bb5698d1..811d3227653 100644 --- a/lisp/org/org-element.el +++ b/lisp/org/org-element.el @@ -110,7 +110,7 @@ ;; to current setup. (defconst org-element-archive-tag "ARCHIVE" - "Tag marking a substree as archived.") + "Tag marking a subtree as archived.") (defconst org-element-citation-key-re (rx "@" (group (one-or-more (any word "-.:?!`'/*@+|(){}<>&_^$#%~")))) @@ -181,8 +181,7 @@ Drawer's name is located in match group 1.") (rx line-start (0+ (any ?\s ?\t)) ":" (1+ (any ?- ?_ word)) ":" (0+ (any ?\s ?\t)) line-end) - "Regexp matching opening or closing line of a drawer. -Drawer's name is located in match group 1.") + "Regexp matching opening or closing line of a drawer.") (defconst org-element-dynamic-block-open-re (rx line-start (0+ (any ?\s ?\t)) @@ -4679,7 +4678,7 @@ element it has to parse." ;; ;; In general, the checks below should be as efficient as ;; possible, especially early in the `cond' form. (The - ;; early checks will contribute to al subsequent parsers as + ;; early checks will contribute to all subsequent parsers as ;; well). (cond ;; Item. @@ -5956,7 +5955,7 @@ better to remove the commands advised in such a way from this list.") (defmacro org-element--cache-log-message (format-string &rest args) "Add a new log message for org-element-cache. -FORMAT-STRING and ARGS are the same arguments as in `foramt'." +FORMAT-STRING and ARGS are the same arguments as in `format'." `(when (or org-element--cache-diagnostics (eq org-element--cache-self-verify 'backtrace)) (let* ((format-string (concat (format "org-element-cache diagnostics(%s): " @@ -6226,7 +6225,7 @@ the cache." ;; children starting at the same pos. (not (org-element-type-p hashed '(section org-data table)))) hashed - ;; No appriate HASHED. Search the cache. + ;; No appropriate HASHED. Search the cache. (while node (let* ((element (avl-tree--node-data node)) (begin (org-element-begin element))) @@ -8323,7 +8322,7 @@ the cache." limit-count)) (cache-walk-abort)) ;; Make sure that we have a cached - ;; element at the new STAR. + ;; element at the new START. (when start (element-match-at-point))) ;; Check if the buffer or cache has been modified. (unless (org-with-base-buffer nil diff --git a/lisp/org/org-faces.el b/lisp/org/org-faces.el index 785fb22dbc0..21b23b641ca 100644 --- a/lisp/org/org-faces.el +++ b/lisp/org/org-faces.el @@ -690,8 +690,8 @@ If it is less than 8, the level-1 face gets reused for level N+1 etc." (defcustom org-cycle-level-faces t "Non-nil means level styles cycle after level `org-n-level-faces'. Then so level org-n-level-faces+1 is styled like level 1. -If nil, then all levels >= org-n-level-faces are styled like -level org-n-level-faces." +If nil, then all levels >= `org-n-level-faces' are styled like +level `org-n-level-faces'." :group 'org-appearance :group 'org-faces :version "24.1" 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/org/org-fold-core.el b/lisp/org/org-fold-core.el index 8372b86b087..4eb875aff2f 100644 --- a/lisp/org/org-fold-core.el +++ b/lisp/org/org-fold-core.el @@ -160,7 +160,7 @@ ;; If one wants to search invisible text without using the provided ;; functions, it is important to keep in mind that 'invisible text ;; property may have multiple possible values (not just nil and -;; t). Hence, (next-single-char-property-change pos 'invisible) is not +;; t). Hence, (next-single-char-property-change pos 'invisible) is not ;; guaranteed to return the boundary of invisible/visible text. ;;; Interactive searching inside folded text (via isearch) @@ -1172,7 +1172,7 @@ because otherwise all these markers will point to nowhere." This is used to allow searching in regions hidden via text properties. As for [2020-05-09 Sat], Isearch only has special handling of hidden overlays. Any text hidden via text properties is not revealed even if `search-invisible' -is set to `t'.") +is set to t.") (defvar-local org-fold-core--isearch-local-regions (make-hash-table :test 'equal) "Hash table storing temporarily shown folds from isearch matches.") diff --git a/lisp/org/org-fold.el b/lisp/org/org-fold.el index 1b62168c483..33b43fd3b56 100644 --- a/lisp/org/org-fold.el +++ b/lisp/org/org-fold.el @@ -733,8 +733,7 @@ go to the parent and show the entire tree." ;;; Handling changes in folded elements (defun org-fold--extend-changed-region (from to) - "Consider folded regions in the next/previous line when fixing -region visibility. + "Consider folded regions in the next/previous line when fixing region visibility. This function is intended to be used as a member of `org-fold-core-extend-changed-region-functions'." ;; If the edit is done in the first line of a folded drawer/block, diff --git a/lisp/org/org-goto.el b/lisp/org/org-goto.el index 5e4c05a7683..cb74942a5e7 100644 --- a/lisp/org/org-goto.el +++ b/lisp/org/org-goto.el @@ -20,6 +20,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see . +;;; Commentary: + ;;; Code: (require 'org-macs) diff --git a/lisp/org/org-habit.el b/lisp/org/org-habit.el index e17ee27fc6f..8b344f0c99f 100644 --- a/lisp/org/org-habit.el +++ b/lisp/org/org-habit.el @@ -69,7 +69,7 @@ relative to the current effective date." :type 'boolean) (defcustom org-habit-show-all-today nil - "If non-nil, will show the consistency graph of all habits on + "If non-nil, show the consistency graph of all habits on today's agenda, even if they are not scheduled." :group 'org-habit :type 'boolean) diff --git a/lisp/org/org-indent.el b/lisp/org/org-indent.el index 39dda4332aa..cabed6acf72 100644 --- a/lisp/org/org-indent.el +++ b/lisp/org/org-indent.el @@ -105,7 +105,7 @@ For details see the variable `org-adapt-indentation'." (defcustom org-indent-post-buffer-init-functions nil "Hook run after org-indent finishes initializing a buffer. -The function(s) in in this hook must accept a single argument representing +The function(s) in this hook must accept a single argument representing the initialized buffer." :group 'org-indent :package-version '(Org . "9.7") diff --git a/lisp/org/org-inlinetask.el b/lisp/org/org-inlinetask.el index a4136a13d2c..3292250cd69 100644 --- a/lisp/org/org-inlinetask.el +++ b/lisp/org/org-inlinetask.el @@ -172,7 +172,7 @@ The number of levels is controlled by `org-inlinetask-min-level'." (not (org-inlinetask-end-p)))) (defun org-inlinetask-in-task-p () - "Return true if point is inside an inline task." + "Return non-nil if point is inside an inline task." (save-excursion (forward-line 0) (let ((case-fold-search t)) diff --git a/lisp/org/org-macs.el b/lisp/org/org-macs.el index 694e747b04e..a6ff0e54512 100644 --- a/lisp/org/org-macs.el +++ b/lisp/org/org-macs.el @@ -1228,7 +1228,7 @@ This function forces `tab-width' value because it is used as a part of the parser, to ensure parser consistency when calculating list indentation." `(progn - (unless (= 8 tab-width) (error "Tab width in Org files must be 8, not %d. Please adjust your `tab-width' settings for Org mode." tab-width)) + (unless (= 8 tab-width) (error "Tab width in Org files must be 8, not %d. Please adjust your `tab-width' settings for Org mode" tab-width)) (string-width (buffer-substring-no-properties (line-beginning-position) (point))))) diff --git a/lisp/org/org-mobile.el b/lisp/org/org-mobile.el index 82f97fd3635..2a6dd4e7986 100644 --- a/lisp/org/org-mobile.el +++ b/lisp/org/org-mobile.el @@ -392,7 +392,7 @@ agenda view showing the flagged items." (org-agenda nil "?")))))) (defun org-mobile-check-setup () - "Check if org-mobile-directory has been set up." + "Check if `org-mobile-directory' has been set up." (org-mobile-cleanup-encryption-tempfile) (unless (and org-directory (stringp org-directory) diff --git a/lisp/org/org-mouse.el b/lisp/org/org-mouse.el index 6bc7f788fb9..322d9868266 100644 --- a/lisp/org/org-mouse.el +++ b/lisp/org/org-mouse.el @@ -561,7 +561,7 @@ SCHEDULED: or DEADLINE: or ANYTHINGLIKETHIS:" (save-excursion (org-apply-on-list wrap-fun nil))))) (defun org-mouse-bolp () - "Return true if there only spaces, tabs, and `*' before point. + "Return non-nil if there only spaces, tabs, and `*' before point. This means, between the beginning of line and the point." (save-excursion (skip-chars-backward " \t*") (bolp))) diff --git a/lisp/org/org-persist.el b/lisp/org/org-persist.el index 52f4b0eef27..b93e32274e9 100644 --- a/lisp/org/org-persist.el +++ b/lisp/org/org-persist.el @@ -666,7 +666,14 @@ When INNER is non-nil, do not try to match as list of containers." (fboundp 'file-attribute-inode-number)) (file-attribute-inode-number (file-attributes file)))) - (setq hash (secure-hash 'md5 associated)) + (setq hash + ;; `secure-hash' may trigger interactive dialog when it + ;; cannot determine the coding system automatically. + ;; Force coding system that works reliably for any text + ;; to avoid it. The has will be consistent anyway, as + ;; long as we use the same coding system. + (let ((coding-system-for-write 'emacs-internal)) + (secure-hash 'md5 associated))) (puthash associated (list (buffer-modified-tick associated) file inode hash) diff --git a/lisp/org/org-refile.el b/lisp/org/org-refile.el index 20b5fbd02c0..9dea34449a7 100644 --- a/lisp/org/org-refile.el +++ b/lisp/org/org-refile.el @@ -470,8 +470,8 @@ See also `org-refile-use-outline-path'. If you are using target caching (see `org-refile-use-cache'), you have to clear the target cache in order to find new targets. -This can be done with a `0' prefix (`C-0 C-c C-w') or a triple -prefix argument (`C-u C-u C-u C-c C-w')." +This can be done with a `0' prefix (\\`C-0 C-c C-w') or a triple +prefix argument (\\`C-u C-u C-u C-c C-w')." (interactive "P") (if (member arg '(0 (64))) (org-refile-cache-clear) @@ -557,7 +557,7 @@ prefix argument (`C-u C-u C-u C-c C-w')." (let ((origin (point-marker))) ;; Handle special case when we refile to exactly same ;; location with tree promotion/demotion. Point marker - ;; saved by `org-width-wide-buffer' (`save-excursion') + ;; saved by `org-with-wide-buffer' (`save-excursion') ;; will then remain before the inserted subtree in ;; unexpected location. (set-marker-insertion-type origin t) @@ -666,12 +666,12 @@ this function appends the default value from #'completing-read)) (extra (if org-refile-use-outline-path "/" "")) (cbnex (concat (buffer-name) extra)) - (filename (and cfn (expand-file-name cfn))) + (filename (and cfn (file-truename cfn))) (tbl (mapcar (lambda (x) (if (and (not (member org-refile-use-outline-path '(file full-file-path title))) - (not (equal filename (nth 1 x)))) + (not (equal filename (file-truename (nth 1 x))))) (cons (concat (car x) extra " (" (file-name-nondirectory (nth 1 x)) ")") (cdr x)) diff --git a/lisp/org/org-src.el b/lisp/org/org-src.el index 262bd462814..0a9062f053a 100644 --- a/lisp/org/org-src.el +++ b/lisp/org/org-src.el @@ -950,16 +950,16 @@ remotely with point temporarily at the start of the code block in the Org buffer. This command is not bound to a key by default, to avoid conflicts -with language major mode bindings. To bind it to C-c @ in all +with language major mode bindings. To bind it to \\`C-c @' in all language major modes, you could use (add-hook \\='org-src-mode-hook (lambda () (define-key org-src-mode-map \"\\C-c@\" \\='org-src-do-key-sequence-at-code-block))) -In that case, for example, C-c @ t issued in code edit buffers -would tangle the current Org code block, C-c @ e would execute -the block and C-c @ h would display the other available +In that case, for example, \\`C-c @ t' issued in code edit buffers +would tangle the current Org code block, \\`C-c @ e' would execute +the block and \\`C-c @ h' would display the other available Org-babel commands." (interactive "kOrg-babel key: ") (if (equal key (kbd "C-g")) (keyboard-quit) diff --git a/lisp/org/org-table.el b/lisp/org/org-table.el index 4a2623b5538..8a0943a48b9 100644 --- a/lisp/org/org-table.el +++ b/lisp/org/org-table.el @@ -622,7 +622,7 @@ This variable is set by `org-before-change-function'. `org-table-align' sets it back to nil.") (defvar orgtbl-after-send-table-hook nil - "Hook for functions attaching to `C-c C-c', if the table is sent. + "Hook for functions attaching to \\`C-c C-c', if the table is sent. This can be used to add additional functionality after the table is sent to the receiver position, otherwise, if table is not sent, the functions are not run.") @@ -5423,7 +5423,7 @@ conflicting binding to this key outside `orgtbl-mode'." (org-table-next-row))) (defun orgtbl-self-insert-command (N) - "Like `self-insert-command', use overwrite-mode for whitespace in tables. + "Like `self-insert-command', use `overwrite-mode' for whitespace in tables. If the cursor is in a table looking at whitespace, the whitespace is overwritten, and the table is not marked as requiring realignment." (interactive "p") @@ -6156,7 +6156,7 @@ supported. It is also possible to use the following one: ;;;###autoload (defun orgtbl-to-orgtbl (table params) - "Convert the `orgtbl-mode' TABLE into another orgtbl-mode table. + "Convert the `orgtbl-mode' TABLE into another `orgtbl-mode' table. TABLE is a list, each entry either the symbol `hline' for a horizontal separator line, or a list of fields for that line. diff --git a/lisp/org/org-version.el b/lisp/org/org-version.el index 6bef3101bbe..c02aff62ec4 100644 --- a/lisp/org/org-version.el +++ b/lisp/org/org-version.el @@ -5,13 +5,13 @@ (defun org-release () "The release version of Org. Inserted by installing Org mode or when a release is made." - (let ((org-release "9.7.4")) + (let ((org-release "9.7.5")) org-release)) ;;;###autoload (defun org-git-version () "The Git version of Org mode. Inserted by installing Org or when a release is made." - (let ((org-git-version "release_9.7.4-7-g165319")) + (let ((org-git-version "release_9.7.5-9-ga091ca")) org-git-version)) (provide 'org-version) diff --git a/lisp/org/org.el b/lisp/org/org.el index 2be404e368e..96b0e0b0ce1 100644 --- a/lisp/org/org.el +++ b/lisp/org/org.el @@ -9,7 +9,7 @@ ;; URL: https://orgmode.org ;; Package-Requires: ((emacs "26.1")) -;; Version: 9.7.4 +;; Version: 9.7.5 ;; This file is part of GNU Emacs. ;; @@ -2670,7 +2670,7 @@ is non-nil." (defcustom org-read-date-popup-calendar t "Non-nil means pop up a calendar when prompting for a date. -In the calendar, the date can be selected with mouse-1. However, the +In the calendar, the date can be selected with \\`mouse-1'. However, the minibuffer will also be active, and you can simply enter the date as well. When nil, only the minibuffer will be available." :group 'org-time @@ -4541,6 +4541,7 @@ directory." ;; Fake Org mode: `org-element-at-point' ;; doesn't need full set-up. (let ((major-mode 'org-mode)) + (setq-local tab-width 8) (setq alist (org--collect-keywords-1 keywords unique directory @@ -4854,7 +4855,7 @@ Respect keys that are already there." (defvar org-selected-window nil "Used in various places to store a window configuration.") (defvar org-finish-function nil - "Function to be called when `C-c C-c' is used. + "Function to be called when \\`C-c C-c' is used. This is for getting out of special buffers like capture.") (defvar org-last-state) @@ -11007,7 +11008,7 @@ containing the regular expression and the callback, onto the list. The list can contain several entries if `org-occur' has been called several time with the KEEP-PREVIOUS argument. Otherwise, this list will only contain one set of parameters. When the highlights are -removed (for example with `C-c C-c', or with the next edit (depending +removed (for example with \\`C-c C-c', or with the next edit (depending on `org-remove-highlights-with-change'), this variable is emptied as well.") @@ -15434,7 +15435,7 @@ When SUPPRESS-TMP-DELAY is non-nil, suppress delays like (defun org-modify-ts-extra (ts-string pos nincrements increment-step) "Change the lead-time/repeat fields at POS in timestamp string TS-STRING. POS is the position in the timestamp string to be changed. -NINCREMENTS is the number of incremenets/decrements. +NINCREMENTS is the number of increments/decrements. INCREMENT-STEP is step used for a single increment when POS in on minutes. Before incrementing minutes, they are rounded to @@ -17086,7 +17087,7 @@ Set `org-speed-command' to the appropriate command as a side effect." (make-string 1 (aref kv (1- (length kv))))))))) (defun org-self-insert-command (N) - "Like `self-insert-command', use overwrite-mode for whitespace in tables. + "Like `self-insert-command', use `overwrite-mode' for whitespace in tables. If the cursor is in a table looking at whitespace, the whitespace is overwritten, and the table is not marked as requiring realignment." (interactive "p") @@ -17235,9 +17236,9 @@ word constituents." (call-interactively 'transpose-words))) (defvar org-ctrl-c-ctrl-c-hook nil - "Hook for functions attaching themselves to `C-c C-c'. + "Hook for functions attaching themselves to \\`C-c C-c'. -This can be used to add additional functionality to the `C-c C-c' +This can be used to add additional functionality to the \\`C-c C-c' key which executes context-dependent commands. This hook is run before any other test, while `org-ctrl-c-ctrl-c-final-hook' is run after the last test. @@ -17248,9 +17249,9 @@ it should do its thing and then return a non-nil value. If the context is wrong, just do nothing and return nil.") (defvar org-ctrl-c-ctrl-c-final-hook nil - "Hook for functions attaching themselves to `C-c C-c'. + "Hook for functions attaching themselves to \\`C-c C-c'. -This can be used to add additional functionality to the `C-c C-c' +This can be used to add additional functionality to the \\`C-c C-c' key which executes context-dependent commands. This hook is run after any other test, while `org-ctrl-c-ctrl-c-hook' is run before the first test. @@ -19064,7 +19065,7 @@ appear in the form of file names, tags, todo states or search strings. If you answer \"yes\" to the prompt, you might want to check and remove such private information before sending the email.") (add-text-properties (point-min) (point-max) '(face org-warning)) - (when (yes-or-no-p "Include your Org configuration and Org warning log ") + (when (yes-or-no-p "Include your Org configuration and Org warning log?") (mapatoms (lambda (v) (and (boundp v) @@ -21802,7 +21803,7 @@ It also provides the following special moves for convenience: arg)) (defvar org--single-lines-list-is-paragraph t - "Treat plain lists with single line items as a whole paragraph") + "Treat plain lists with single line items as a whole paragraph.") (defun org--paragraph-at-point () "Return paragraph, or equivalent, element at point. diff --git a/lisp/org/ox-icalendar.el b/lisp/org/ox-icalendar.el index 9921865ad51..858d146d6d9 100644 --- a/lisp/org/ox-icalendar.el +++ b/lisp/org/ox-icalendar.el @@ -932,14 +932,14 @@ Return VTODO component as a string." :repeater-unit dl))))) ;; TODO Implement via RDATE with changing DURATION (org-display-warning "Not yet implemented: \ -different repeaters on SCHEDULED and DEADLINE. Skipping.") +different repeaters on SCHEDULED and DEADLINE. Skipping.") nil) ;; DEADLINE has repeater but SCHEDULED doesn't ((and dl-repeat-p (and sc (not sc-repeat-p))) ;; TODO SCHEDULED should only apply to first instance; ;; use RDATE with custom DURATION to implement that (org-display-warning "Not yet implemented: \ -repeater on DEADLINE but not SCHEDULED. Skipping.") +repeater on DEADLINE but not SCHEDULED. Skipping.") nil) ((or sc-repeat-p dl-repeat-p) (concat diff --git a/lisp/org/ox-latex.el b/lisp/org/ox-latex.el index a34646763a6..fcb0e20dc7e 100644 --- a/lisp/org/ox-latex.el +++ b/lisp/org/ox-latex.el @@ -1391,7 +1391,7 @@ default values of which are given by `org-latex-engraved-preamble' and "\n")) (t (funcall gen-theme-spec engraved-theme)))) (funcall gen-theme-spec engraved-theme)) - (warn "Cannot engrave source blocks. Consider installing `engrave-faces'.") + (warn "Cannot engrave source blocks. Consider installing `engrave-faces'.") "% WARNING syntax highlighting unavailable as engrave-faces-latex was missing.\n") "\n"))) @@ -3548,7 +3548,7 @@ and FLOAT are extracted from SRC-BLOCK and INFO in `org-latex-src-block'." When the THEME symbol is non-nil, that theme will be used. When INLINE is nil, a Verbatim environment wrapped in a Code -environment will be used. When t, a Verb command will be used. +environment will be used. When t, a Verb command will be used. When OPTIONS is provided, as either a string or list of key-value pairs accepted by `org-latex--make-option-string', it is passed @@ -3591,7 +3591,7 @@ to the Verbatim environment or Verb command." engraved-wrapped "}") engraved-wrapped)) - (user-error "Cannot engrave code as `engrave-faces-latex' is unavailable."))) + (user-error "Cannot engrave code as `engrave-faces-latex' is unavailable"))) (cl-defun org-latex-src-block--engraved (&key src-block info lang caption caption-above-p num-start retain-labels attributes float &allow-other-keys) diff --git a/lisp/org/ox-publish.el b/lisp/org/ox-publish.el index 13f9b6b53b4..9f943cedc34 100644 --- a/lisp/org/ox-publish.el +++ b/lisp/org/ox-publish.el @@ -88,7 +88,7 @@ cdr of each element is in one of the following forms: (:components (\"project-1\" \"project-2\" ...)) -When the CDR of an element of org-publish-project-alist is in +When the CDR of an element of `org-publish-project-alist' is in this second form, the elements of the list after `:components' are taken to be components of the project, which group together files requiring different publishing options. When you publish diff --git a/lisp/org/ox.el b/lisp/org/ox.el index 6fa21be9063..75839e6c88a 100644 --- a/lisp/org/ox.el +++ b/lisp/org/ox.el @@ -1931,7 +1931,7 @@ Return a string." (progn ,@body) (org-link-broken (pcase (plist-get info :with-broken-links) - (`nil (user-error "Org export aborted. Unable to resolve link: %S\nSee `org-export-with-broken-links'." (nth 1 err))) + (`nil (user-error "Org export aborted. Unable to resolve link: %S\nSee `org-export-with-broken-links'" (nth 1 err))) (`mark (org-export-data (format "[BROKEN LINK: %s]" (nth 1 err)) info)) (_ nil)))))) diff --git a/lisp/progmodes/cc-awk.el b/lisp/progmodes/cc-awk.el index e299f4fa8d2..e377c4831fc 100644 --- a/lisp/progmodes/cc-awk.el +++ b/lisp/progmodes/cc-awk.el @@ -990,7 +990,7 @@ "ERRNO" "FIELDWIDTHS" "FILENAME" "FNR" "FPAT" "FS" "FUNCTAB" "IGNORECASE" "LINT" "NF" "NR" "OFMT" "OFS" "ORS" "PREC" "PROCINFO" "RLENGTH" "ROUNDMODE" "RS" "RSTART" "RT" "SUBSEP" - "SYNTAB" "TEXTDOMAIN") t) "\\>") + "SYMTAB" "TEXTDOMAIN") t) "\\>") 'font-lock-variable-name-face) ;; Special file names. (acm, 2002/7/22) @@ -1011,9 +1011,11 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ ;; Do the same (almost) with ;; (regexp-opt '("/inet/tcp/lport/rhost/rport" "/inet/udp/lport/rhost/rport" ;; "/inet/raw/lport/rhost/rport") 'words) + ;; , replacing "inet" with "inet[46]?" + ;; , replacing "lport", "rhost", and "rport" with "[[:alnum:]]+". ;; This cannot be combined with the above pattern, because the match number ;; for the (optional) closing \" would then exceed 9. - '("\\(\"/inet/\\(\\(raw\\|\\(tc\\|ud\\)p\\)/lport/rhost/rport\\)\\)\\>\ + '("\\(\"/inet[46]?/\\(\\(raw\\|\\(tc\\|ud\\)p\\)/[[:alnum:]]+/[[:alnum:]]+/[[:alnum:]]+\\)\\)\\>\ \\(\\(\"\\)\\|\\([^\"/\n\r][^\"\n\r]*\\)?$\\)" (1 font-lock-variable-name-face t) (6 font-lock-variable-name-face t t)) @@ -1035,8 +1037,8 @@ std\\(err\\|in\\|out\\)\\|user\\)\\)\\>\ '("adump" "and" "asort" "asorti" "atan2" "bindtextdomain" "close" "compl" "cos" "dcgettext" "dcngettext" "exp" "extension" "fflush" "gensub" "gsub" "index" "int" "isarray" "length" "log" "lshift" - "match" "mktime" "or" "patsplit" "print" "printf" "rand" "rshift" - "sin" "split" "sprintf" "sqrt" "srand" "stopme" + "match" "mkbool" "mktime" "or" "patsplit" "print" "printf" "rand" + "rshift" "sin" "split" "sprintf" "sqrt" "srand" "stopme" "strftime" "strtonum" "sub" "substr" "system" "systime" "tolower" "toupper" "typeof" "xor") t) diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 0b50844732f..7dc850cb839 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -13864,7 +13864,7 @@ comment at the start of cc-engine.el for more info." ;; ;; This is true when point is at the last non syntactic WS position on the ;; line, there is a macro call last on the line, and this particular macro's - ;; name is defined by the regexp `c-vs-macro-regexp' as not needing a + ;; name is defined by the regexp `c-macro-with-semi-re' as not needing a ;; semicolon. (save-excursion (save-restriction diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 06b919f26fd..72cfdfa8653 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1954,7 +1954,7 @@ ender." ;; The following is no longer used (2020-02-16). ;; (c-lang-defconst c-last-open-c-comment-start-on-line-re ;; "Regexp which matches the last block comment start on the -;; current ine, if any, or nil in those languages without block +;; current one, if any, or nil in those languages without block ;; comments. When a match is found, submatch 1 contains the comment ;; starter." ;; t "\\(/\\*\\)\\([^*]\\|\\*+\\([^*/]\\|$\\)\\)*$" @@ -4396,10 +4396,9 @@ a label construct. This catches C++'s inheritance construct \"class foo (c-lang-defconst c-opt-extra-label-key "Optional regexp matching labels. -Normally, labels are detected according to `c-nonlabel-token-key', -`c-decl-prefix-re' and `c-nonlabel-decl-prefix-re'. This regexp can -be used if there are additional labels that aren't recognized that -way." +Normally, labels are detected according to `c-nonlabel-token-key' and +`c-decl-prefix-re'. This regexp can be used if there are additional +labels that aren't recognized that way." t nil objc (c-make-keywords-re t (c-lang-const c-protection-kwds))) (c-lang-defvar c-opt-extra-label-key (c-lang-const c-opt-extra-label-key)) diff --git a/lisp/progmodes/cperl-mode.el b/lisp/progmodes/cperl-mode.el index 68ad7eda9a7..217125e1599 100644 --- a/lisp/progmodes/cperl-mode.el +++ b/lisp/progmodes/cperl-mode.el @@ -161,13 +161,13 @@ for constructs with multiline if/unless/while/until/for/foreach condition." :group 'cperl-autoinsert-details) (defcustom cperl-file-style nil - "Indentation style to use in cperl-mode. + "Indentation style to use in `cperl-mode'. Setting this option will override options as given in `cperl-style-alist' for the keyword provided here. If nil, then the individual options as customized are used. \"PBP\" is the style recommended in the Book \"Perl Best Practices\" by Damian Conway. \"CPerl\" is the traditional style -of cperl-mode, and \"PerlStyle\" follows the Perl documentation +of `cperl-mode', and \"PerlStyle\" follows the Perl documentation in perlstyle. The other styles have been developed for other programming languages, mostly C." :type '(choice (const "PBP") @@ -232,7 +232,7 @@ to the right of the start of its line." :group 'cperl-indentation-details) (defcustom cperl-continued-brace-offset 0 "Extra indent for substatements that start with open-braces. -This is in addition to cperl-continued-statement-offset." +This is in addition to `cperl-continued-statement-offset'." :type 'integer :group 'cperl-indentation-details) (defcustom cperl-close-paren-offset -1 @@ -819,7 +819,7 @@ B) Speed of editing operations. of, say, long POD sections.") (defvar cperl-tips-faces 'please-ignore-this-line - "CPerl mode uses following faces for highlighting: + "CPerl mode uses the following faces for highlighting: `cperl-array-face' Array names `cperl-hash-face' Hash names diff --git a/lisp/progmodes/dcl-mode.el b/lisp/progmodes/dcl-mode.el index b8ca1f2d600..686555221cb 100644 --- a/lisp/progmodes/dcl-mode.el +++ b/lisp/progmodes/dcl-mode.el @@ -500,7 +500,6 @@ Variables controlling indentation style and extra features: dcl-imenu-label-call Change the text that is used as sub-listing labels in imenu. -To run code after DCL mode has loaded, use `with-eval-after-load'. Turning on DCL mode calls the value of the variable `dcl-mode-hook' with no args, if that value is non-nil. diff --git a/lisp/progmodes/ebrowse.el b/lisp/progmodes/ebrowse.el index 37b3a5f190b..a8a0495ab11 100644 --- a/lisp/progmodes/ebrowse.el +++ b/lisp/progmodes/ebrowse.el @@ -851,7 +851,7 @@ Return the buffer created." For each member, a symbol is added to the table. Members are extracted from the buffer-local tree `ebrowse--tree-table'. -Each symbol has its property `ebrowse-info' set to a list (TREE MEMBER-LIST +Each symbol has its property `ebrowse-tree' set to a list (TREE MEMBER-LIST MEMBER) where TREE is the tree in which the member is defined, MEMBER-LIST is a symbol describing the member list in which the member is found, and MEMBER is a MEMBER structure describing the member. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index df4cbe50dc0..5845aff39b7 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -494,7 +494,7 @@ If this variable's value can also be an alist ((COMMAND . ACTION) ...) where COMMAND is a symbol designating a command, such as `eglot-rename', `eglot-code-actions', `eglot-code-action-quickfix', etc. ACTION is one of the symbols -described above. The value `t' for COMMAND is accepted and its +described above. The value t for COMMAND is accepted and its ACTION is the default value for commands not in the alist." :type (let ((basic-choices '((const :tag "Use diff" diff) @@ -1415,7 +1415,7 @@ INTERACTIVE is ignored and provided for backward compatibility." (unless (or (null current-server) (y-or-n-p "\ [eglot] Shut down current connection before attempting new one?")) - (user-error "[eglot] Connection attempt aborted by user.")) + (user-error "[eglot] Connection attempt aborted by user")) (prog1 (append (eglot--guess-contact t) '(t)) (when current-server (ignore-errors (eglot-shutdown current-server)))))) (eglot--connect (eglot--ensure-list managed-major-modes) @@ -1871,15 +1871,25 @@ Doubles as an indicator of snippet support." (unless (bound-and-true-p yas-minor-mode) (yas-minor-mode 1)) (apply #'yas-expand-snippet args))))) -(defun eglot--format-markup (markup) - "Format MARKUP according to LSP's spec." - (pcase-let ((`(,string ,mode) - (if (stringp markup) (list markup 'gfm-view-mode) - (list (plist-get markup :value) - (pcase (plist-get markup :kind) - ("markdown" 'gfm-view-mode) - ("plaintext" 'text-mode) - (_ major-mode)))))) + (defun eglot--format-markup (markup) + "Format MARKUP according to LSP's spec. +MARKUP is either an LSP MarkedString or MarkupContent object." + (let (string mode language) + (cond ((stringp markup) + (setq string markup + mode 'gfm-view-mode)) + ((setq language (plist-get markup :language)) + ;; Deprecated MarkedString + (setq string (concat "```" language "\n" + (plist-get markup :value) "\n```") + mode 'gfm-view-mode)) + (t + ;; MarkupContent + (setq string (plist-get markup :value) + mode (pcase (plist-get markup :kind) + ("markdown" 'gfm-view-mode) + ("plaintext" 'text-mode) + (_ major-mode))))) (with-temp-buffer (setq-local markdown-fontify-code-blocks-natively t) (insert string) @@ -2544,7 +2554,7 @@ THINGS are either registrations or unregisterations (sic)." (defun eglot--TextDocumentIdentifier () "Compute TextDocumentIdentifier object for current buffer. -Sets `eglot--TextDocumentIdentifier-uri' (which see) as a side effect." +Sets `eglot--TextDocumentIdentifier-cache' (which see) as a side effect." (unless eglot--TextDocumentIdentifier-cache (let ((truename (file-truename (or buffer-file-name (ignore-errors @@ -3925,7 +3935,7 @@ If NOERROR, return predicate, else erroring function." ;;; List connections mode (define-derived-mode eglot-list-connections-mode tabulated-list-mode - "" "Eglot mode for listing server connections + "" "Eglot mode for listing server connections. \\{eglot-list-connections-mode-map}" :interactive nil (setq-local tabulated-list-format @@ -3967,12 +3977,12 @@ If NOERROR, return predicate, else erroring function." "Face used for parameter inlay hint overlays.") (defvar-local eglot--outstanding-inlay-hints-region (cons nil nil) - "Jit-lock-calculated (FROM . TO) region with potentially outdated hints") + "Jit-lock-calculated (FROM . TO) region with potentially outdated hints.") (defvar-local eglot--outstanding-inlay-hints-last-region nil) (defvar-local eglot--outstanding-inlay-regions-timer nil - "Helper timer for `eglot--update-hints'") + "Helper timer for `eglot--update-hints'.") (defun eglot--update-hints (from to) "Jit-lock function for Eglot inlay hints." diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 7d0312eb2a4..9bf6f9217c8 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1633,7 +1633,10 @@ integer value is also printed as a character of that codepoint. If `eval-expression-debug-on-error' is non-nil, which is the default, this command arranges for all errors to enter the debugger." (interactive "P") - (values--store-value + (funcall + ;; Not sure why commit 4428c27c1ae7d stored into `values' only when + ;; `eval-expression-debug-on-error' was nil, but let's preserve that. + (if eval-expression-debug-on-error #'identity #'values--store-value) (handler-bind ((error (if eval-expression-debug-on-error #'eval-expression--debug #'ignore))) (elisp--eval-last-sexp eval-last-sexp-arg-internal)))) diff --git a/lisp/progmodes/etags.el b/lisp/progmodes/etags.el index 597612196fd..d3eb0d46e9b 100644 --- a/lisp/progmodes/etags.el +++ b/lisp/progmodes/etags.el @@ -1364,7 +1364,7 @@ hits the start of file." (cond (line (progn (goto-char (point-min)) (forward-line (1- line)))) (startpos (goto-char startpos)) - (t (error "etags.el BUG: bogus direct file tag"))) + (t (error "etags.el: BUG: bogus direct file tag"))) ;; This constant is 1/2 the initial search window. ;; There is no sense in making it too small, ;; since just going around the loop once probably @@ -2182,7 +2182,7 @@ file name, add `tag-partial-file-name-match-p' to the list value.") (when (symbolp symbs) (if (boundp symbs) (setq symbs (symbol-value symbs)) - (warn "symbol `%s' has no value" symbs) + (warn "Symbol `%s' has no value" symbs) (setq symbs nil)) (if (obarrayp symbs) (mapatoms add-xref symbs) diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 6301b77beca..e72f25fd0cd 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -218,7 +218,7 @@ this is used." (face :tag "Face")))) (defcustom flymake-autoresize-margins t - "If non-nil, automatically resize margin-width calling flymake--resize-margins. + "If non-nil, automatically resize margin-width calling `flymake--resize-margins'. Only relevant if `flymake-indicator-type' is set to margins." :version "30.1" diff --git a/lisp/progmodes/gdb-mi.el b/lisp/progmodes/gdb-mi.el index c8b086cfad2..2981965ee0c 100644 --- a/lisp/progmodes/gdb-mi.el +++ b/lisp/progmodes/gdb-mi.el @@ -1285,8 +1285,8 @@ no input, and GDB is waiting for input." (defun gdb-mouse-until (event) "Continue running until a source line past the current line. The destination source line can be selected either by clicking -with mouse-3 on the fringe/margin or dragging the arrow -with mouse-1 (default bindings)." +with \\`mouse-3' on the fringe/margin or dragging the arrow +with \\`mouse-1' (default bindings)." (interactive "e") (let ((start (event-start event)) (end (event-end event))) @@ -1302,8 +1302,8 @@ with mouse-1 (default bindings)." (defun gdb-mouse-jump (event) "Set execution address/line. -The destination source line can be selected either by clicking with C-mouse-3 -on the fringe/margin or dragging the arrow with C-mouse-1 (default bindings). +The destination source line can be selected either by clicking with \\`C-mouse-3' +on the fringe/margin or dragging the arrow with \\`C-mouse-1' (default bindings). Unlike `gdb-mouse-until' the destination address can be before the current line, and no execution takes place." (interactive "e") @@ -5122,7 +5122,7 @@ commands) or source buffers (that display program source code)." (defun gdb--buffer-type (buffer) "Return the type of BUFFER if it is a function buffer. -Buffer type is like `gdb-registers-type', `gdb-stack-buffer'. +Buffer type is like `gdb-registers-buffer', `gdb-stack-buffer'. These symbols are used by `gdb-get-buffer-create'. Return nil if BUFFER is not a GDB function buffer." diff --git a/lisp/progmodes/grep.el b/lisp/progmodes/grep.el index 459f00e6805..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 @@ -1181,9 +1189,7 @@ REGEXP is used as a string in the prompt." (files (completing-read (format-prompt "Search for \"%s\" in files matching wildcard" default regexp) - (completion-table-merge - (lambda (_string _pred _action) defaults) - #'read-file-name-internal) + (completion-table-merge defaults #'completion-file-name-table) nil nil nil 'grep-files-history defaults))) (and files (or (cdr (assoc files grep-files-aliases)) diff --git a/lisp/progmodes/hideif.el b/lisp/progmodes/hideif.el index 98e567299a1..9bcac0d8dc5 100644 --- a/lisp/progmodes/hideif.el +++ b/lisp/progmodes/hideif.el @@ -2407,7 +2407,7 @@ first arg will be `hif-etc'." 'c99 t))) ((eq token 'hif-comma) (if etc - (error "Syntax error: no comma allowed after `...'."))) + (error "Syntax error: no comma allowed after `...'"))) (t (push token result)))) (setq result (nreverse result)) diff --git a/lisp/progmodes/idlw-help.el b/lisp/progmodes/idlw-help.el index 7bed69a738b..c311e1c5377 100644 --- a/lisp/progmodes/idlw-help.el +++ b/lisp/progmodes/idlw-help.el @@ -62,8 +62,8 @@ is used in preference to the old `idlwave-html-help-location'." (if (memq system-type '(ms-dos windows-nt)) nil "/usr/local/etc/") - "The directory where the idl_html_help/ dir lives. Obsolete for IDL -6.2 or later (see `idlwave-html-system-help-location')." + "The directory where the idl_html_help/ dir lives. +Obsolete for IDL 6.2 or later (see `idlwave-html-system-help-location')." :type 'directory) (defcustom idlwave-help-use-assistant t diff --git a/lisp/progmodes/idlwave.el b/lisp/progmodes/idlwave.el index 30442fa0d34..b3e9eb58196 100644 --- a/lisp/progmodes/idlwave.el +++ b/lisp/progmodes/idlwave.el @@ -798,7 +798,7 @@ upper case, regardless of this variable." (defcustom idlwave-reserved-word-upcase nil "Non-nil means, reserved words will be made upper case via abbrev expansion. If nil case of reserved words is controlled by `idlwave-abbrev-change-case'. -Has effect only if in abbrev-mode." +Has effect only if in `abbrev-mode'." :group 'idlwave-abbrev-and-indent-action :type 'boolean) diff --git a/lisp/progmodes/inf-lisp.el b/lisp/progmodes/inf-lisp.el index 687b176009e..85fc6b930f5 100644 --- a/lisp/progmodes/inf-lisp.el +++ b/lisp/progmodes/inf-lisp.el @@ -347,7 +347,7 @@ The actually processing is done by DO-STRING and DO-REGION DEFVAR forms reset the variables to the init values." (save-excursion ;; Find the end of the defun this way to avoid having the region - ;; possibly end with a comment (it there'a a comment after the + ;; possibly end with a comment (it there's a comment after the ;; final parenthesis). (beginning-of-defun) (forward-sexp) diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el index bb4a7df3340..4ceb211ade1 100644 --- a/lisp/progmodes/java-ts-mode.el +++ b/lisp/progmodes/java-ts-mode.el @@ -155,8 +155,8 @@ "Java operators for tree-sitter font-locking.") (defun java-ts-mode--string-highlight-helper () -"Returns, for strings, a query based on what is supported by -the available version of Tree-sitter for java." + "Return, for strings, a query based on what is supported by +the available version of Tree-sitter for Java." (condition-case nil (progn (treesit-query-capture 'java '((text_block) @font-lock-string-face)) `((string_literal) @font-lock-string-face diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index f5629ff8fbe..f8140c14a49 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -2493,7 +2493,7 @@ Returns t if successful, nil if no term was found." t))) (defun js--chained-expression-p () - "A helper for js--proper-indentation that handles chained expressions. + "Helper for `js--proper-indentation' that handles chained expressions. A chained expression is when the current line starts with '.' and the previous line also has a '.' expression. This function returns the indentation for the current line if it is @@ -3634,7 +3634,33 @@ Check if a node type is available, then return the right indent rules." :language 'javascript :feature 'escape-sequence :override t - '((escape_sequence) @font-lock-escape-face)) + '((escape_sequence) @font-lock-escape-face) + + ;; "document" should be first, to avoid overlap. + :language 'jsdoc + :override t + :feature 'document + '((document) @font-lock-doc-face) + + :language 'jsdoc + :override t + :feature 'keyword + '((tag_name) @font-lock-constant-face) + + :language 'jsdoc + :override t + :feature 'bracket + '((["{" "}"]) @font-lock-bracket-face) + + :language 'jsdoc + :override t + :feature 'property + '((type) @font-lock-type-face) + + :language 'jsdoc + :override t + :feature 'definition + '((identifier) @font-lock-variable-name-face)) "Tree-sitter font-lock settings.") (defun js--fontify-template-string (node override start end &rest _) @@ -3857,6 +3883,9 @@ See `treesit-thing-settings' for more information.") "Nodes that designate sexps in JavaScript. See `treesit-thing-settings' for more information.") +(defvar js--treesit-jsdoc-beginning-regexp (rx bos "/**") + "Regular expression matching the beginning of a jsdoc block comment.") + ;;;###autoload (define-derived-mode js-ts-mode js-base-mode "JavaScript" "Major mode for editing JavaScript. @@ -3882,7 +3911,8 @@ See `treesit-thing-settings' for more information.") (setq-local syntax-propertize-function #'js-ts--syntax-propertize) ;; Tree-sitter setup. - (treesit-parser-create 'javascript) + (setq-local treesit-primary-parser (treesit-parser-create 'javascript)) + ;; Indent. (setq-local treesit-simple-indent-rules js--treesit-indent-rules) ;; Navigation. @@ -3904,11 +3934,20 @@ See `treesit-thing-settings' for more information.") ;; Fontification. (setq-local treesit-font-lock-settings js--treesit-font-lock-settings) (setq-local treesit-font-lock-feature-list - '(( comment definition) + '(( comment document definition) ( keyword string) ( assignment constant escape-sequence jsx number pattern string-interpolation) ( bracket delimiter function operator property))) + + (when (treesit-ready-p 'jsdoc t) + (setq-local treesit-range-settings + (treesit-range-rules + :embed 'jsdoc + :host 'javascript + :local t + `(((comment) @capture (:match ,js--treesit-jsdoc-beginning-regexp @capture)))))) + ;; Imenu (setq-local treesit-simple-imenu-settings `(("Function" "\\`function_declaration\\'" nil nil) diff --git a/lisp/progmodes/lua-ts-mode.el b/lisp/progmodes/lua-ts-mode.el index 0568e0d273c..06daadbc1fd 100644 --- a/lisp/progmodes/lua-ts-mode.el +++ b/lisp/progmodes/lua-ts-mode.el @@ -58,7 +58,8 @@ (defcustom lua-ts-mode-hook nil "Hook run after entering `lua-ts-mode'." :type 'hook - :options '(flymake-mode + :options '(eglot-ensure + flymake-mode hs-minor-mode outline-minor-mode) :version "30.1") @@ -116,7 +117,7 @@ (defcustom lua-ts-indent-continuation-lines t "Controls how multi-line if/else statements are aligned. -If t, then continuation lines are indented by `lua-ts-indent-offset': +If non-nil, then continuation lines are indented by `lua-ts-indent-offset': if a and b then @@ -721,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/pascal.el b/lisp/progmodes/pascal.el index bd39b64aefc..802c02dcfa4 100644 --- a/lisp/progmodes/pascal.el +++ b/lisp/progmodes/pascal.el @@ -297,7 +297,8 @@ are handled in another way, and should not be added to this list." ;;;###autoload (define-derived-mode pascal-mode prog-mode "Pascal" - "Major mode for editing Pascal code.\\ + "Major mode for editing Pascal code. +\\ TAB indents for Pascal code. Delete converts tabs to spaces as it moves back. \\[completion-at-point] completes the word around current point with respect \ @@ -333,7 +334,7 @@ Variables controlling indentation/edit style: regardless of where in the line point is when the TAB command is used. `pascal-auto-endcomments' (default t) Non-nil means a comment { ... } is set after the ends which ends cases and - functions. The name of the function or case will be set between the braces. + functions. The name of the function or case will be set between the braces. `pascal-auto-lineup' (default t) List of contexts where auto lineup of :'s or ='s should be done. @@ -496,7 +497,8 @@ This puts the mark at the end, and point at the beginning." (pascal-beg-of-defun)) (defun pascal-comment-area (start end) - "Put the region into a Pascal comment.\\ + "Put the region into a Pascal comment. +\\ The comments that are in this area are \"deformed\": `*)' becomes `!(*' and `}' becomes `!{'. These deformed comments are returned to normal if you use diff --git a/lisp/progmodes/perl-mode.el b/lisp/progmodes/perl-mode.el index 68685fb6625..13d5d7f9451 100644 --- a/lisp/progmodes/perl-mode.el +++ b/lisp/progmodes/perl-mode.el @@ -1128,16 +1128,9 @@ Returns (parse-state) if line starts inside a string." ;; Move back over whitespace before the openbrace. ;; If openbrace is not first nonwhite thing on the line, ;; 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))))))))) + (save-excursion (skip-chars-backward " \t") + (if (bolp) 0 perl-brace-imaginary-offset)) + (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/php-ts-mode.el b/lisp/progmodes/php-ts-mode.el index 1f7d6f5b3ee..1298b39311b 100644 --- a/lisp/progmodes/php-ts-mode.el +++ b/lisp/progmodes/php-ts-mode.el @@ -36,6 +36,7 @@ ;; * https://github.com/tree-sitter/tree-sitter-php ;; * https://github.com/tree-sitter/tree-sitter-html ;; * https://github.com/tree-sitter/tree-sitter-javascript +;; * https://github.com/tree-sitter/tree-sitter-jsdoc ;; * https://github.com/tree-sitter/tree-sitter-css ;; * https://github.com/claytonrcarter/tree-sitter-phpdoc ;; @@ -86,6 +87,7 @@ (phpdoc . ("https://github.com/claytonrcarter/tree-sitter-phpdoc")) (html . ("https://github.com/tree-sitter/tree-sitter-html" "v0.20.3")) (javascript . ("https://github.com/tree-sitter/tree-sitter-javascript" "v0.21.2")) + (jsdoc . ("https://github.com/tree-sitter/tree-sitter-jsdoc" "v0.21.0")) (css . ("https://github.com/tree-sitter/tree-sitter-css" "v0.21.0"))) "Treesitter language parsers required by `php-ts-mode'. You can customize this variable if you want to stick to a specific @@ -717,7 +719,7 @@ characters of the current line." (c-ts-common-comment-2nd-line-matcher c-ts-common-comment-2nd-line-anchor 1))) - "Tree-sitter indentation rules for for `phpdoc'.") + "Tree-sitter indentation rules for `phpdoc'.") ;;; Font-lock @@ -977,7 +979,8 @@ characters of the current line." :override t :feature 'property `((attribute_name) @font-lock-variable-name-face)) - "Tree-sitter font-lock settings for `php-html-ts-mode'.") + "Tree-sitter Font-lock settings for HTML when embedded in PHP. +Like `html-ts-mode--font-lock-settings' but adapted for `php-ts-mode'.") (defvar php-ts-mode--phpdoc-font-lock-settings (treesit-font-lock-rules @@ -1295,6 +1298,7 @@ Depends on `c-ts-common-comment-setup'." (treesit-ready-p 'phpdoc) (treesit-ready-p 'html) (treesit-ready-p 'javascript) + (treesit-ready-p 'jsdoc) (treesit-ready-p 'css))) (error "Tree-sitter for PHP isn't available. You can install the parsers with M-x @@ -1333,6 +1337,12 @@ Depends on `c-ts-common-comment-setup'." (start_tag (tag_name)) (raw_text) @cap)) + :embed 'jsdoc + :host 'javascript + :local t + `(((comment) @cap + (:match ,js--treesit-jsdoc-beginning-regexp @cap))) + :embed 'css :host 'html :offset '(1 . -1) @@ -1561,7 +1571,7 @@ The optional TYPE can be the symbol \"port\", \"hostname\", \"document-root\" or (defun run-php (&optional cmd config) "Run an PHP interpreter as a inferior process. -Arguments CMD an CONFIG, default to `php-ts-mode-php-executable' +Arguments CMD and CONFIG, default to `php-ts-mode-php-executable' and `php-ts-mode-php-config' respectively, control which PHP interpreter is run. Prompt for CMD if `php-ts-mode-php-executable' is nil. Optional CONFIG, if supplied, is the php.ini file to use." diff --git a/lisp/progmodes/python.el b/lisp/progmodes/python.el index ca5ecfab6ea..a00289d6de9 100644 --- a/lisp/progmodes/python.el +++ b/lisp/progmodes/python.el @@ -1140,8 +1140,8 @@ fontified." For example, Lvl1 | Lvl2[Lvl3[Lvl4[Lvl5 | None]], Lvl2]. This structure is represented via nesting binary_operator and subscript nodes. This function iterates over all levels and -highlight identifier nodes. If TYPE-REGEX is not nil fontify type -identifier only if it matches against TYPE-REGEX. NODE is the +highlight identifier nodes. If TYPE-REGEX is not nil fontify type +identifier only if it matches against TYPE-REGEX. NODE is the binary_operator node. OVERRIDE is the override flag described in `treesit-font-lock-rules'. START and END mark the region to be fontified." @@ -5612,8 +5612,6 @@ See `python-check-command' for the default." doc = '{objtype} {name}{args}'.format( objtype=objtype, name=name, args=args ) - else: - doc = doc.splitlines()[0] except: doc = '' return doc" @@ -7044,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" @@ -7128,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/progmodes/ruby-mode.el b/lisp/progmodes/ruby-mode.el index f6ef175e11e..3bcfa9ee7df 100644 --- a/lisp/progmodes/ruby-mode.el +++ b/lisp/progmodes/ruby-mode.el @@ -336,7 +336,7 @@ Only has effect when `ruby-use-smie' is t." "If non-nil, align chained method calls. Each method call on a separate line will be aligned to the column -of its parent. Example: +of its parent. Example: my_array.select { |str| str.size > 5 } .map { |str| str.downcase } @@ -386,7 +386,7 @@ Only has effect when `ruby-use-smie' is t." "Non-nil to align the body of a block to the statement's start. The body and the closer will be aligned to the column where the -statement containing the block starts. Example: +statement containing the block starts. Example: foo.bar .each do @@ -2557,7 +2557,7 @@ If there is no Rubocop config file, Rubocop will be passed a flag "Non-nil with allow `ruby-flymake-rubocop' to use `bundle exec'. When the value is `check', it will first see whether Gemfile exists in the same directory as the configuration file, and whether it mentions -the gem \"rubocop\". When t, it's used unconditionally. " +the gem \"rubocop\". When t, it is used unconditionally." :type '(choice (const :tag "Always" t) (const :tag "No" nil) (const :tag "If rubocop is in Gemfile" check)) diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el index baf0e1ec013..b7a52b06b24 100644 --- a/lisp/progmodes/rust-ts-mode.el +++ b/lisp/progmodes/rust-ts-mode.el @@ -267,7 +267,11 @@ to be checked as its standard input." eos) @font-lock-type-face)) ((scoped_identifier path: (identifier) @rust-ts-mode--fontify-scope)) - ((scoped_type_identifier path: (identifier) @rust-ts-mode--fontify-scope))) + ((scoped_type_identifier path: (identifier) @rust-ts-mode--fontify-scope)) + ;; Sometimes the parser can't determine if an identifier is a type, + ;; so we use this heuristic. See bug#69625 for the full discussion. + ((identifier) @font-lock-type-face + (:match ,(rx bos upper) @font-lock-type-face))) :language 'rust :feature 'property @@ -427,7 +431,7 @@ delimiters < and >'s." (?> '(5 . ?<)))))))) (defun rust-ts-mode--prettify-symbols-compose-p (start end match) - "Return true iff the symbol MATCH should be composed. + "Return non-nil if the symbol MATCH should be composed. See `prettify-symbols-compose-predicate'." (and (fboundp 'prettify-symbols-default-compose-p) (prettify-symbols-default-compose-p start end match) diff --git a/lisp/progmodes/verilog-mode.el b/lisp/progmodes/verilog-mode.el index a83bad0e8ed..65545d523a8 100644 --- a/lisp/progmodes/verilog-mode.el +++ b/lisp/progmodes/verilog-mode.el @@ -9950,7 +9950,7 @@ For example if declare A A (.B(SIG)) then B will be included in the list." (setq sig-list (cons (list (match-string-no-properties 1) nil nil) sig-list)))) sig-list))) -(defvar verilog-cache-has-lisp nil "True if any AUTO_LISP in buffer.") +(defvar verilog-cache-has-lisp nil "Non-nil if any AUTO_LISP in buffer.") (make-variable-buffer-local 'verilog-cache-has-lisp) (defun verilog-read-auto-lisp-present () @@ -14043,7 +14043,7 @@ Typing \\[verilog-auto] will call my-verilog-insert-hello and expand the above into: /*AUTOINSERTLISP(my-verilog-insert-hello \"world\")*/ - // Beginning of automatic insert lisp + // Beginning of automatic insert Lisp initial $write(\"hello world\"); // End of automatics @@ -15400,7 +15400,7 @@ and the case items." (defun verilog-highlight-region (beg end _old-len) "Colorize included files and modules in the (changed?) region. -Clicking on the middle-mouse button loads them in a buffer (as in dired)." +Clicking on the middle-mouse button loads them in a buffer (as in Dired)." (when (or verilog-highlight-includes verilog-highlight-modules) (save-excursion diff --git a/lisp/progmodes/xref.el b/lisp/progmodes/xref.el index fb6c9dad73b..5ecb8664da0 100644 --- a/lisp/progmodes/xref.el +++ b/lisp/progmodes/xref.el @@ -487,7 +487,7 @@ Override existing value with NEW-VALUE if NEW-VALUE is set." (set-window-parameter w 'xref--history (xref--make-xref-history)))))) (defun xref--get-history () - "Return xref history using xref-history-storage." + "Return xref history using `xref-history-storage'." (funcall xref-history-storage)) (defun xref--push-backward (m) @@ -993,7 +993,6 @@ point." ;; suggested by Johan Claesson "to further reduce finger movement": (define-key map (kbd ".") #'xref-next-line) (define-key map (kbd ",") #'xref-prev-line) - (define-key map (kbd "g") #'xref-revert-buffer) (define-key map (kbd "M-,") #'xref-quit-and-pop-marker-stack) map)) @@ -1011,13 +1010,16 @@ point." #'xref--imenu-extract-index-name) (setq-local add-log-current-defun-function #'xref--add-log-current-defun) + (setq-local revert-buffer-function #'xref--revert-buffer) (setq-local outline-minor-mode-cycle t) (setq-local outline-minor-mode-use-buttons 'insert) (setq-local outline-search-function (lambda (&optional bound move backward looking-at) (outline-search-text-property 'xref-group nil bound move backward looking-at))) - (setq-local outline-level (lambda () 1))) + (setq-local outline-level (lambda () 1)) + (add-hook 'revert-buffer-restore-functions + #'xref-revert-buffer-restore-point nil t)) (defvar xref--transient-buffer-mode-map (let ((map (make-sparse-keymap))) @@ -1273,22 +1275,16 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)." xref--original-window-intent (assoc-default 'display-action alist)) (setq xref--fetcher fetcher))) -(defun xref-revert-buffer () +(defun xref--revert-buffer (&rest _) ; Ignore `revert-buffer' args. "Refresh the search results in the current buffer." - (interactive) (let ((inhibit-read-only t) - (buffer-undo-list t) - restore-functions) - (when (boundp 'revert-buffer-restore-functions) - (run-hook-wrapped 'revert-buffer-restore-functions - (lambda (f) (push (funcall f) restore-functions) nil))) + (buffer-undo-list t)) (save-excursion (condition-case err (let ((alist (xref--analyze (funcall xref--fetcher))) (inhibit-modification-hooks t)) (erase-buffer) - (prog1 (xref--insert-xrefs alist) - (mapc #'funcall (delq nil restore-functions)))) + (xref--insert-xrefs alist)) (user-error (erase-buffer) (insert @@ -1296,6 +1292,28 @@ Return an alist of the form ((GROUP . (XREF ...)) ...)." (error-message-string err) 'face 'error))))))) +;;; FIXME: Make this alias obsolete in future release. +(defalias 'xref-revert-buffer #'revert-buffer) + +(defun xref-revert-buffer-restore-point () + "Restore point on a previous item or group after reverting." + (let* ((item + (when (xref--item-at-point) + (buffer-substring-no-properties (pos-bol) (pos-eol)))) + (group + (save-excursion + (when (or (get-text-property (point) 'xref-group) + (and item (xref--search-property 'xref-group t) + (get-text-property (point) 'xref-group))) + (buffer-substring-no-properties (pos-bol) (pos-eol)))))) + (when (or item group) + (lambda () + (goto-char (point-min)) + (when (and group (search-forward (concat "\n" group "\n") nil t)) + (goto-char (pos-bol 0))) + (when (and item (search-forward (concat "\n" item "\n") nil t)) + (goto-char (pos-bol 0))))))) + (defun xref--auto-jump-first (buf value) (when value (select-window (get-buffer-window buf)) diff --git a/lisp/shell.el b/lisp/shell.el index 9399906715f..e1936ff1119 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -764,9 +764,10 @@ command." (setq-local comint-input-ring-size hsize)) (setq comint-input-ring-file-name (concat remote hfile))) - (if (or (equal comint-input-ring-file-name "") - (equal (file-truename comint-input-ring-file-name) - (file-truename null-device))) + (if (and comint-input-ring-file-name + (or (equal comint-input-ring-file-name "") + (equal (file-truename comint-input-ring-file-name) + (file-truename null-device)))) (setq comint-input-ring-file-name nil)) ;; Arrange to write out the input ring on exit, if the shell doesn't ;; do this itself. diff --git a/lisp/simple.el b/lisp/simple.el index b48f46fc711..17625fad66f 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -4061,7 +4061,7 @@ REASON describes the reason that the boundary is being added; see (defun undo-auto--boundaries (cause) "Check recently changed buffers and add a boundary if necessary. REASON describes the reason that the boundary is being added; see -`undo-last-boundary' for more information." +`undo-auto--last-boundary-cause' for more information." ;; (Bug #23785) All commands should ensure that there is an undo ;; boundary whether they have changed the current buffer or not. (when (eq cause 'command) @@ -6703,28 +6703,53 @@ If ARG is zero, kill current line but exclude the trailing newline." (unless (eq last-command 'kill-region) (kill-new "") (setq last-command 'kill-region)) - (cond ((zerop arg) - ;; We need to kill in two steps, because the previous command - ;; could have been a kill command, in which case the text - ;; before point needs to be prepended to the current kill - ;; ring entry and the text after point appended. Also, we - ;; need to use save-excursion to avoid copying the same text - ;; twice to the kill ring in read-only buffers. - (save-excursion - (kill-region (point) (progn (forward-visible-line 0) (point)))) - (kill-region (point) (progn (end-of-visible-line) (point)))) - ((< arg 0) - (save-excursion - (kill-region (point) (progn (end-of-visible-line) (point)))) - (kill-region (point) - (progn (forward-visible-line (1+ arg)) - (unless (bobp) (backward-char)) - (point)))) - (t - (save-excursion - (kill-region (point) (progn (forward-visible-line 0) (point)))) - (kill-region (point) - (progn (forward-visible-line arg) (point)))))) + ;; - We need to kill in two steps, because the previous command + ;; could have been a kill command, in which case the text before + ;; point needs to be prepended to the current kill ring entry and + ;; the text after point appended. + ;; - We need to be careful to avoid copying text twice to the kill + ;; ring in read-only buffers. + ;; - We need to determine the boundaries of visible lines before we + ;; do the first kill. Otherwise `after-change-functions' may + ;; change visibility (bug#65734). + (let (;; The beginning of both regions to kill + (regions-begin (point-marker)) + ;; The end of the first region to kill. Moreover, after + ;; evaluation of the value form, (point) will be the end of + ;; the second region to kill. + (region1-end (cond ((zerop arg) + (prog1 (save-excursion + (forward-visible-line 0) + (point-marker)) + (end-of-visible-line))) + ((< arg 0) + (prog1 (save-excursion + (end-of-visible-line) + (point-marker)) + (forward-visible-line (1+ arg)) + (unless (bobp) (backward-char)))) + (t + (prog1 (save-excursion + (forward-visible-line 0) + (point-marker)) + (forward-visible-line arg)))))) + ;; - Pass the marker positions and not the markers themselves. + ;; kill-region determines whether to prepend or append to a + ;; previous kill by checking the direction of the region. But + ;; it deletes the content and hence moves the markers before + ;; that. That effectively makes every region delimited by + ;; markers an (empty) forward region. + ;; - Make the first kill-region emit a non-local exit only if the + ;; second kill-region below would not operate on a non-empty + ;; region. + (let ((kill-read-only-ok (or kill-read-only-ok + (/= regions-begin (point))))) + (kill-region (marker-position regions-begin) + (marker-position region1-end))) + (kill-region (marker-position regions-begin) + (point)) + (set-marker regions-begin nil) + (set-marker region1-end nil))) (defun forward-visible-line (arg) "Move forward by ARG lines, ignoring currently invisible newlines only. 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/tab-bar.el b/lisp/tab-bar.el index 6ab6324540e..edec6543a82 100644 --- a/lisp/tab-bar.el +++ b/lisp/tab-bar.el @@ -1023,7 +1023,11 @@ It should return the formatted tab group name to display in the tab bar." (defcustom tab-bar-tab-group-face-function #'tab-bar-tab-group-face-default "Function to define a tab group face. -Function gets one argument: a tab." +Function gets one argument: a tab. +Please note that if you customized `tab-bar-tab-face-function' +and want to use the same faces for non-group tabs with +`tab-bar-format-tabs-groups' as well, then you can set this +variable to the same function." :type 'function :group 'tab-bar :version "28.1") @@ -1451,11 +1455,20 @@ and the newly selected tab." (defcustom tab-bar-select-restore-windows #'tab-bar-select-restore-windows "Function called when selecting a tab to handle windows whose buffer was killed. When a tab-bar tab displays a window whose buffer was killed since -this tab was last selected, this function determines what to do with -that window. By default, either a random buffer is displayed instead of -the killed buffer, or the window gets deleted. However, with the help -of `window-restore-killed-buffer-windows' it's possible to handle such -situations better by displaying an information about the killed buffer." +this tab was last selected, this variable determines what to do with +that window. + +If this variable is nil, there is no special handling; +`set-window-configuration' will decide what to do with the window, +then either a random buffer is displayed instead of the killed buffer, +or the window gets deleted. + +If this variable is a function, display another buffer in that window, +and pass that buffer to the function. See the variable +`window-restore-killed-buffer-windows' for the calling convention. + +By default, `tab-bar-select-restore-windows' displays a placeholder buffer +in the same window to give information about the killed buffer." :type '(choice (const :tag "No special handling" nil) (const :tag "Show placeholder buffers" tab-bar-select-restore-windows) diff --git a/lisp/tab-line.el b/lisp/tab-line.el index 1d14fda9825..462a0a27692 100644 --- a/lisp/tab-line.el +++ b/lisp/tab-line.el @@ -555,10 +555,15 @@ This means that switching to a buffer previously shown in the same window will keep the same order of tabs that was before switching. And newly displayed buffers are added to the end of the tab line." (let* ((old-buffers (window-parameter nil 'tab-line-buffers)) + (buffer-positions (let ((index-table (make-hash-table :test 'eq))) + (seq-do-indexed + (lambda (buf idx) (puthash buf idx index-table)) + old-buffers) + index-table)) (new-buffers (sort (tab-line-tabs-window-buffers) :key (lambda (buffer) - (or (seq-position old-buffers buffer) - most-positive-fixnum))))) + (gethash buffer buffer-positions + most-positive-fixnum))))) (set-window-parameter nil 'tab-line-buffers new-buffers) new-buffers)) diff --git a/lisp/term/android-win.el b/lisp/term/android-win.el index 3e0f71abf91..df1cdc5143e 100644 --- a/lisp/term/android-win.el +++ b/lisp/term/android-win.el @@ -223,7 +223,7 @@ VALUE should be something suitable for passing to ;; time. This pre-command-hook clears the overlay before any command ;; and should be set whenever a preedit overlay is visible. (defun android-clear-preedit-text () - "Clear the pre-edit overlay and remove itself from pre-command-hook. + "Clear the pre-edit overlay and remove itself from `pre-command-hook'. This function should be installed in `pre-command-hook' whenever preedit text is displayed." (when android-preedit-overlay @@ -629,4 +629,4 @@ accessible to other programs." (provide 'android-win) -;; android-win.el ends here. +;;; android-win.el ends here diff --git a/lisp/term/pgtk-win.el b/lisp/term/pgtk-win.el index 7999d348082..505174048f6 100644 --- a/lisp/term/pgtk-win.el +++ b/lisp/term/pgtk-win.el @@ -27,7 +27,7 @@ (eval-when-compile (require 'cl-lib)) (unless (featurep 'pgtk) - (error "%s: Loading pgtk-win.el but not compiled with PGTK." + (error "%s: Loading pgtk-win.el but not compiled with PGTK" invocation-name)) ;; Documentation-purposes only: actually loaded in loadup.el. diff --git a/lisp/term/x-win.el b/lisp/term/x-win.el index 98dd576fea2..ced2750202b 100644 --- a/lisp/term/x-win.el +++ b/lisp/term/x-win.el @@ -1523,7 +1523,7 @@ This uses `icon-map-list' to map icon file names to stock icon names." ;; time. This pre-command-hook clears the overlay before any command ;; and should be set whenever a preedit overlay is visible. (defun x-clear-preedit-text () - "Clear the pre-edit overlay and remove itself from pre-command-hook. + "Clear the pre-edit overlay and remove itself from `pre-command-hook'. This function should be installed in `pre-command-hook' whenever preedit text is displayed." (when x-preedit-overlay diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el index caf59995c01..667da10d7a3 100644 --- a/lisp/textmodes/ispell.el +++ b/lisp/textmodes/ispell.el @@ -2416,7 +2416,7 @@ Global `ispell-quit' is set to start location to continue spell session." (progn (set-marker ispell-recursive-edit-marker nil) (error - "Cannot continue ispell from this buffer."))) + "Cannot continue ispell from this buffer"))) (set-marker ispell-recursive-edit-marker nil))) (list word nil)) ; recheck starting at this word. ((= char ?\C-z) diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el index e2de6959dc6..987d3d7345c 100644 --- a/lisp/textmodes/mhtml-mode.el +++ b/lisp/textmodes/mhtml-mode.el @@ -86,7 +86,7 @@ code(); "Regexp matching the prefix of buffer-locals we want to capture.") (defun mhtml--construct-submode (mode &rest args) - "A wrapper for make-mhtml--submode that computes the buffer-local variables." + "A wrapper for `make-mhtml--submode' that computes the buffer-local variables." (let ((captured-locals nil) (crucial-captured-locals nil) (submode (apply #'make-mhtml--submode args))) diff --git a/lisp/textmodes/page-ext.el b/lisp/textmodes/page-ext.el index f5f59adb0cf..1681f86b343 100644 --- a/lisp/textmodes/page-ext.el +++ b/lisp/textmodes/page-ext.el @@ -486,7 +486,7 @@ contain matches to the regexp.)") (define-obsolete-function-alias 'set-page-delimiter #'pages-set-delimiter "27.1") (defun pages-set-delimiter (regexp reset-p &optional interactively) - "Set buffer local value of page-delimiter to REGEXP. + "Set buffer local value of `page-delimiter' to REGEXP. Called interactively with a prefix argument, reset `page-delimiter' to its original value. diff --git a/lisp/textmodes/paragraphs.el b/lisp/textmodes/paragraphs.el index af99a96e045..be741e6517b 100644 --- a/lisp/textmodes/paragraphs.el +++ b/lisp/textmodes/paragraphs.el @@ -118,8 +118,28 @@ text indented by a margin setting." (defcustom sentence-end-double-space t "Non-nil means a single space does not end a sentence. -This is relevant for filling. See also `sentence-end-without-period' -and `colon-double-space'. +This user option affects fill commands and sentence commands. + +If this variable is non-nil, Emacs considers a period followed by two +spaces or by a newline as the end of a sentence. This means that: + + 1. The fill commands will not break a line after a period followed + by just one space. + + 2. The sentence commands stop only for double spaces. + +If this variable is nil, Emacs considers a period followed by one space +or by a newline as the end of a sentence. This means that: + + 1. The fill commands will break a line after a period followed by + one space, and put just one space after each period. + + 2. The sentence commands stop for single spaces. + +For more details, see Info node `(emacs) Fill Commands' and Info +node `(emacs) Sentences'. + +See also `sentence-end-without-period' and `colon-double-space'. This value is used by the function `sentence-end' to construct the regexp describing the end of a sentence, when the value of the variable diff --git a/lisp/textmodes/refbib.el b/lisp/textmodes/refbib.el index dd548e00d9b..087e097649e 100644 --- a/lisp/textmodes/refbib.el +++ b/lisp/textmodes/refbib.el @@ -270,13 +270,13 @@ This is in addition to the `r2b-capitalize-title-stop-words'.") (princ (apply (function format) args) r2b-out-buf)) (defun r2b-get-field (var field &optional unique required capitalize) - "Set VAR to string value of FIELD, if any. If none, VAR is set to -nil. If multiple fields appear, then separate values with the -'\\nand\\t\\t', unless UNIQUE is non-nil, in which case log a warning -and just concatenate the values. Trim off leading blanks and tabs on -first line, and trailing blanks and tabs of every line. Log a warning -and set VAR to the empty string if REQUIRED is true. Capitalize as a -title if CAPITALIZE is true. Returns value of VAR." + "Set VAR to string value of FIELD, if any. +If none, VAR is set to nil. If multiple fields appear, then separate +values with the '\\nand\\t\\t', unless UNIQUE is non-nil, in which case +log a warning and just concatenate the values. Trim off leading blanks +and tabs on first line, and trailing blanks and tabs of every line. Log +a warning and set VAR to the empty string if REQUIRED is true. +Capitalize as a title if CAPITALIZE is true. Return value of VAR." (let (item val (not-past-end t)) (r2b-trace "snarfing %s" field) (goto-char (point-min)) @@ -406,9 +406,10 @@ title if CAPITALIZE is true. Returns value of VAR." (defun r2b-put-field (field data &optional abbrevs) - "Print bibtex FIELD = {DATA} if DATA not null; precede -with a comma and newline; if ABBREVS list is given, then -try to replace the {DATA} with an abbreviation." + "Print bibtex FIELD = {DATA} if DATA not null; precede with comma and newline. + +If ABBREVS list is given, then try to replace the {DATA} with an +abbreviation." (if data (let (match nodelim index) ;; multi-line (cond diff --git a/lisp/textmodes/refer.el b/lisp/textmodes/refer.el index 0fbe4a30b11..f5f4be75c03 100644 --- a/lisp/textmodes/refer.el +++ b/lisp/textmodes/refer.el @@ -113,9 +113,9 @@ each time it is needed." (defcustom refer-cache-bib-files t "Variable determining whether the value of `refer-bib-files' should be cached. -If t, initialize the value of refer-bib-files the first time it is used. If -nil, re-read the list of \\.bib files depending on the value of `refer-bib-files' -each time it is needed." +If t, initialize the value of refer-bib-files the first time it is used. +If nil, re-read the list of \\.bib files depending on the value of +`refer-bib-files' each time it is needed." :type 'boolean) (defcustom refer-bib-files-regexp "\\\\bibliography" 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..cb491367c8d 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)) @@ -1263,7 +1263,7 @@ This gets refreshed in every phrases command.") (defun reftex-index-phrase-selection-or-word (arg) "Add current selection or word at point to the phrases buffer. \\ -When you are in transient-mark-mode and the region is active, the +When you are in `transient-mark-mode' and the region is active, the selection will be used - otherwise the word at point. You get a chance to edit the entry in the phrases buffer - finish with \\[reftex-index-phrases-save-and-return]." @@ -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) @@ -1364,8 +1363,8 @@ If the buffer is non-empty, delete the old header first." ;;;###autoload (define-derived-mode reftex-index-phrases-mode fundamental-mode "Phrases" "Major mode for managing the Index phrases of a LaTeX document. -This buffer was created with RefTeX. \\ - +This buffer was created with RefTeX. +\\ To insert new phrases, use - `C-c \\' in the LaTeX document to copy selection or word - `\\[reftex-index-new-phrase]' in the phrases buffer. @@ -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 ;; 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 ;; 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/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el index 5c744374128..f126df8955a 100644 --- a/lisp/textmodes/sgml-mode.el +++ b/lisp/textmodes/sgml-mode.el @@ -1418,7 +1418,7 @@ Leave point at the beginning of the tag." (with-syntax-table sgml-tag-syntax-table (let ((pos (point))) (condition-case nil - ;; FIXME: This does not correctly skip over PI an CDATA tags. + ;; FIXME: This does not correctly skip over PI and CDATA tags. (sgml-forward-sexp 1) (scan-error ;; This < seems to be just a spurious one, let's ignore it. diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el index 2087fd8271b..918c84bc949 100644 --- a/lisp/textmodes/table.el +++ b/lisp/textmodes/table.el @@ -1456,8 +1456,8 @@ first cell. |-!- | | | +-----+-----+-----+ -Inside a table cell, there are special key bindings. \\ - +Inside a table cell, there are special key bindings. +\\ M-9 \\[table-widen-cell] (or \\[universal-argument] 9 \\[table-widen-cell]) widens the first cell by 9 character width, which results as @@ -1466,7 +1466,7 @@ width, which results as +--------------+-----+-----+ Type TAB \\[table-widen-cell] then type TAB M-2 M-7 \\[table-widen-cell] (or \\[universal-argument] 2 7 \\[table-widen-cell]). Typing -TAB moves the point forward by a cell. The result now looks like this: +TAB moves the point forward by a cell. The result now looks like this: +--------------+------+--------------------------------+ | | |-!- | @@ -5301,8 +5301,8 @@ Current buffer must already be set to the cache buffer." (defun table--fill-region-strictly (beg end) "Fill region strictly so that no line exceeds `fill-column'. -When a word exceeds fill-column the word is chopped into pieces. The -chopped location is indicated with table-word-continuation-char." +When a word exceeds `fill-column' the word is chopped into pieces. The +chopped location is indicated with `table-word-continuation-char'." (or (and (markerp beg) (markerp end)) (error "markerp")) (if (< fill-column 2) diff --git a/lisp/thingatpt.el b/lisp/thingatpt.el index a593b6c6241..3cfd3905701 100644 --- a/lisp/thingatpt.el +++ b/lisp/thingatpt.el @@ -778,7 +778,10 @@ Signal an error if the entire string was not used." ;;;###autoload (defun sexp-at-point () - "Return the sexp at point, or nil if none is found." + "Return the sexp at point, or nil if none is found. +This is for returning the Lisp object represented by text at point; +use (thing-at-point \\='sexp) instead if you rather want the balanced +expression at point regardless of Lisp syntax." (form-at-point 'sexp)) ;;;###autoload (defun symbol-at-point () diff --git a/lisp/touch-screen.el b/lisp/touch-screen.el index 792e1be5ff9..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 @@ -2065,9 +2071,9 @@ sent until the touch sequence currently being translated ends. Must be called from a command bound to a `touchscreen-hold' or `touchscreen-drag' event." (let* ((tool touch-screen-current-tool) - (current-what (nth 4 tool))) + (current-what (nth 3 tool))) ;; Signal an error if no hold and no drag is in progress. - (when (and (not (eq current-what 'hold)) + (when (and (not (eq current-what 'held)) (not (eq current-what 'drag))) (error "Calling `touch-screen-inhibit-drag' outside hold or drag")) ;; Now set the fourth element of tool to `command-inhibit'. diff --git a/lisp/transient.el b/lisp/transient.el index 34458bec688..312ed540f73 100644 --- a/lisp/transient.el +++ b/lisp/transient.el @@ -5,7 +5,7 @@ ;; Author: Jonas Bernoulli ;; URL: https://github.com/magit/transient ;; Keywords: extensions -;; Version: 0.7.0 +;; Version: 0.7.2 ;; SPDX-License-Identifier: GPL-3.0-or-later @@ -835,6 +835,11 @@ Technically a suffix object with no associated command.") All remaining arguments are treated as files. They become the value of this argument.") +(defclass transient-value-preset (transient-suffix) + ((transient :initform t) + (set :initarg := :initform nil)) + "Class used by the `transient-preset' suffix command.") + ;;;; Group (defclass transient-group (transient-child) @@ -1075,7 +1080,10 @@ commands are aliases for." (and val (not (eq val 'transient--default-infix-command)) val))) (eval-and-compile ;transient--expand-define-args - (defun transient--expand-define-args (args arglist form &optional nobody) + (defun transient--expand-define-args (args &optional arglist form nobody) + ;; ARGLIST and FORM are only optional for backward compatibility. + ;; This is necessary because "emoji.el" from Emacs 29 calls this + ;; function directly, with just one argument. (unless (listp arglist) (error "Mandatory ARGLIST is missing")) (let (class keys suffixes docstr declare (interactive-only t)) @@ -2020,7 +2028,7 @@ transient. In that case NAME is mandatory, LAYOUT and EDIT must be nil and PARAMS may be (but usually is not) used to set, e.g., the \"scope\" of the transient (see `transient-define-prefix'). -This function is also called internally in which case LAYOUT and +This function is also called internally, in which case LAYOUT and EDIT may be non-nil." (transient--debug 'setup) (transient--with-emergency-exit :setup @@ -2275,6 +2283,12 @@ value. Otherwise return CHILDREN as is." (transient--pop-keymap 'transient--predicate-map) (transient--pop-keymap 'transient--transient-map) (transient--pop-keymap 'transient--redisplay-map) + (if (eq transient--refreshp 'updated-value) + ;; Preserve the prefix value this once, because the + ;; invoked suffix indicates that it has updated that. + (setq transient--refreshp (oref transient--prefix refresh-suffixes)) + ;; Otherwise update the prefix value from suffix values. + (oset transient--prefix value (transient-get-value))) (transient--init-objects) (transient--init-keymaps) (transient--push-keymap 'transient--transient-map) @@ -2536,7 +2550,10 @@ value. Otherwise return CHILDREN as is." (transient--pop-keymap 'transient--redisplay-map) (setq transient--redisplay-map new) (transient--push-keymap 'transient--redisplay-map)) - (transient--redisplay))))))) + (transient--redisplay))))) + (setq transient-current-prefix nil) + (setq transient-current-command nil) + (setq transient-current-suffixes nil))) (defun transient--post-exit (&optional command) (transient--debug 'post-exit) @@ -2559,9 +2576,6 @@ value. Otherwise return CHILDREN as is." (remove-hook 'pre-command-hook #'transient--pre-command) (remove-hook 'post-command-hook #'transient--post-command) (advice-remove 'recursive-edit #'transient--recursive-edit)) - (setq transient-current-prefix nil) - (setq transient-current-command nil) - (setq transient-current-suffixes nil) (let ((resume (and transient--stack (not (memq transient--exitp '(replace suspend)))))) (unless (or resume (eq transient--exitp 'replace)) @@ -3081,6 +3095,12 @@ transient is active." (oset obj value (nth pos hst)) (mapc #'transient-init-value transient--suffixes)))) +(transient-define-suffix transient-preset () + "Put this preset into action." + :class transient-value-preset + (interactive) + (transient-prefix-set (oref (transient-suffix-object) set))) + ;;;; Auxiliary (defun transient-toggle-common () @@ -3258,7 +3278,7 @@ it\", in which case it is pointless to preserve history.)" (reader (oref obj reader)) (choices (if (functionp choices) (funcall choices) choices)) (prompt (transient-prompt obj)) - (value (if multi-value (mapconcat #'identity value ",") value)) + (value (if multi-value (string-join value ",") value)) (history-key (or (oref obj history-key) (oref obj command))) (transient--history (alist-get history-key transient-history)) @@ -3405,10 +3425,10 @@ prompt." ;;;; Set (cl-defgeneric transient-infix-set (obj value) - "Set the value of infix object OBJ to value.") + "Set the value of infix object OBJ to VALUE.") (cl-defmethod transient-infix-set ((obj transient-infix) value) - "Set the value of infix object OBJ to value." + "Set the value of infix object OBJ to VALUE." (oset obj value value)) (cl-defmethod transient-infix-set :after ((obj transient-argument) value) @@ -3438,8 +3458,16 @@ prompt." (member arg incomp))))) (transient-infix-set obj nil))))) +(defun transient-prefix-set (value) + "Set the value of the active transient prefix to VALUE. +Intended for use by transient suffix commands." + (oset transient--prefix value value) + (setq transient--refreshp 'updated-value)) + (cl-defgeneric transient-set-value (obj) - "Set the value of the transient prefix OBJ.") + "Persist the value of the transient prefix OBJ. +Only intended for use by `transient-set'. +Also see `transient-prefix-set'.") (cl-defmethod transient-set-value ((obj transient-prefix)) (oset (oref obj prototype) value (transient-get-value)) @@ -3495,7 +3523,7 @@ the set, saved or default value for PREFIX." (and (or (not (slot-exists-p obj 'unsavable)) (not (oref obj unsavable))) (transient--get-wrapped-value obj))) - transient-current-suffixes))) + (or transient--suffixes transient-current-suffixes)))) (defun transient--get-wrapped-value (obj) (and-let* ((value (transient-infix-value obj))) @@ -3954,6 +3982,24 @@ called inside the correct buffer (see `transient--insert-group') and its value is returned to the caller." (transient--get-description obj)) +(cl-defmethod transient-format-description ((obj transient-value-preset)) + (pcase-let* (((eieio description key set) obj) + ((eieio value) transient--prefix) + (active (seq-set-equal-p set value))) + (format + "%s %s" + (propertize (or description (format "Preset %s" key)) + 'face (and active 'transient-argument)) + (format (propertize "(%s)" 'face 'transient-delimiter) + (mapconcat (lambda (arg) + (propertize + arg 'face (cond (active 'transient-argument) + ((member arg value) + '((:weight demibold) + transient-inactive-argument)) + ('transient-inactive-argument)))) + set " "))))) + (cl-defmethod transient-format-description ((obj transient-group)) "Format the description by calling the next method. If the result doesn't use the `face' property at all, then apply the face diff --git a/lisp/treesit.el b/lisp/treesit.el index ee67c2349f9..b9661f53601 100644 --- a/lisp/treesit.el +++ b/lisp/treesit.el @@ -1396,9 +1396,8 @@ non-nil, print debugging information." "If non-nil, next `syntax-propertize' should start at this position. When tree-sitter parser reparses, it calls -`treesit--syntax-propertize-notifier' with the affected region, -and that function sets this variable to the start of the affected -region.") +`treesit--font-lock-mark-ranges-to-fontify' with the changed ranges, and +that function sets this variable to the start of the changed ranges.") (defvar-local treesit--pre-redisplay-tick nil "The last `buffer-chars-modified-tick' that we've processed. diff --git a/lisp/url/url-util.el b/lisp/url/url-util.el index f41c5b07ffa..8e958eee0b7 100644 --- a/lisp/url/url-util.el +++ b/lisp/url/url-util.el @@ -378,7 +378,7 @@ These characters are specified in RFC 3986, Appendix A.") (aset vec ?\; nil) vec) "Allowed-character byte mask for keys and values in the query segment of a URI. -url-query-allowed-chars minus '=', '&', and ';'.") +`url-query-allowed-chars' minus '=', '&', and ';'.") ;;;###autoload (defun url-encode-url (url) diff --git a/lisp/url/url.el b/lisp/url/url.el index 0ac2917b213..2bf62d7cfbb 100644 --- a/lisp/url/url.el +++ b/lisp/url/url.el @@ -227,7 +227,7 @@ URL-encoded before it's used." (defun url-retrieve-synchronously (url &optional silent inhibit-cookies timeout) "Retrieve URL synchronously. Return the buffer containing the data, or nil if there are no data -associated with it (the case for dired, info, or mailto URLs that need +associated with it (the case for Dired, info, or mailto URLs that need no further processing). URL is either a string or a parsed URL. If SILENT is non-nil, don't do any messaging while retrieving. diff --git a/lisp/use-package/use-package-core.el b/lisp/use-package/use-package-core.el index bb12c3c4f2b..dd4efd3831d 100644 --- a/lisp/use-package/use-package-core.el +++ b/lisp/use-package/use-package-core.el @@ -1669,8 +1669,8 @@ Also see the Info node `(use-package) Creating an extension'." (defconst use-package-vc-valid-keywords '( :url :branch :lisp-dir :main-file :vc-backend :rev :shell-command :make :ignored-files) - "Valid keywords for the `:vc' keyword, see the Info -node `(emacs)Fetching Package Sources'.") + "Valid keywords for the `:vc' keyword. +See Info node `(emacs)Fetching Package Sources'.") (defun use-package-normalize--vc-arg (arg) "Normalize possible arguments to the `:vc' keyword. diff --git a/lisp/vc/ediff-init.el b/lisp/vc/ediff-init.el index c5eda873b5e..1b478d3f9b7 100644 --- a/lisp/vc/ediff-init.el +++ b/lisp/vc/ediff-init.el @@ -594,7 +594,7 @@ highlighted using ASCII flags." (ediff-defvar-local ediff-visible-bounds nil) (ediff-defvar-local ediff-start-narrowed t - "Non-nil means start narrowed, if doing ediff-windows-* or ediff-regions-*") + "Non-nil means start narrowed, if doing ediff-windows-* or ediff-regions-*.") (ediff-defvar-local ediff-quit-widened t "Non-nil means: when finished, Ediff widens buffers A/B. Actually, Ediff restores the scope of visibility that existed at startup.") @@ -624,13 +624,13 @@ It's a number rather than string.") (ediff-defvar-local ediff-buffer-values-orig-A nil - "The original values of ediff-protected-variables for buffer A.") + "The original values of `ediff-protected-variables' for buffer A.") (ediff-defvar-local ediff-buffer-values-orig-B nil - "The original values of ediff-protected-variables for buffer B.") + "The original values of `ediff-protected-variables' for buffer B.") (ediff-defvar-local ediff-buffer-values-orig-C nil - "The original values of ediff-protected-variables for buffer C.") + "The original values of `ediff-protected-variables' for buffer C.") (ediff-defvar-local ediff-buffer-values-orig-Ancestor nil - "The original values of ediff-protected-variables for buffer Ancestor.") + "The original values of `ediff-protected-variables' for buffer Ancestor.") (defconst ediff-buffer-values-orig-alist '((A . ediff-buffer-values-orig-A) diff --git a/lisp/vc/ediff-mult.el b/lisp/vc/ediff-mult.el index 66d4935cd75..b320c7d1f49 100644 --- a/lisp/vc/ediff-mult.el +++ b/lisp/vc/ediff-mult.el @@ -43,7 +43,7 @@ ;; (...) ...) ;; The function ediff-make-new-meta-list-element can be used to create ;; 2nd and subsequent elements of that list (i.e., after the -;; description header). See ediff-make-new-meta-list-element for the +;; description header). See ediff-make-new-meta-list-element for the ;; explanation of the two nil placeholders in such elements. ;; ;; There is API for extracting the components of the members of the diff --git a/lisp/vc/ediff-ptch.el b/lisp/vc/ediff-ptch.el index 2d5d4609890..3b76964327a 100644 --- a/lisp/vc/ediff-ptch.el +++ b/lisp/vc/ediff-ptch.el @@ -542,8 +542,8 @@ are two possible targets for this %spatch. However, these files do not exist." (defun ediff-get-patch-buffer (&optional arg patch-buf) "Obtain patch buffer. If patch is already in a buffer---use it. -Else, read patch file into a new buffer. If patch buffer is passed as an -optional argument, then use it." +Else, read patch file into a new buffer. If patch buffer is passed as +an optional argument, then use it." (let ((last-nonmenu-event t) ; Emacs: don't use dialog box last-command-event) ; XEmacs: don't use dialog box diff --git a/lisp/vc/emerge.el b/lisp/vc/emerge.el index 5328ebc73ad..ca48f2f3c7b 100644 --- a/lisp/vc/emerge.el +++ b/lisp/vc/emerge.el @@ -128,14 +128,14 @@ copied to the designated output file." :type 'boolean) (defcustom emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n" - "Flag placed above the highlighted block of code. Must end with newline. -Must be set before Emerge is loaded, or emerge-new-flags must be run -after setting." + "Flag placed above the highlighted block of code. +Must end with newline. Must be set before Emerge is loaded, or +`emerge-new-flags' must be run after setting." :type 'string) (defcustom emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n" - "Flag placed below the highlighted block of code. Must end with newline. -Must be set before Emerge is loaded, or emerge-new-flags must be run -after setting." + "Flag placed below the highlighted block of code. +Must end with newline. Must be set before Emerge is loaded, or +`emerge-new-flags' must be run after setting." :type 'string) ;; Hook variables diff --git a/lisp/vc/vc-dav.el b/lisp/vc/vc-dav.el index ae2cf149771..0e85e71de40 100644 --- a/lisp/vc/vc-dav.el +++ b/lisp/vc/vc-dav.el @@ -1,6 +1,6 @@ ;;; vc-dav.el --- vc.el support for WebDAV -*- lexical-binding: t; -*- -;; Copyright (C) 2001, 2004-2024 Free Software Foundation, Inc. +;; Copyright (C) 2001-2024 Free Software Foundation, Inc. ;; Author: Bill Perry ;; Keywords: url, vc @@ -82,7 +82,7 @@ See `vc-checkout-model' for a list of possible values." ) (defun vc-dav-checkin (_url _comment &optional _rev) - "Commit changes in URL to WebDAV. COMMENT is used as a check-in comment." + "Commit changes in URL to WebDAV. COMMENT is used as a check-in comment." ;; This should PUT the resource and release any locks that we hold. ) diff --git a/lisp/vc/vc-git.el b/lisp/vc/vc-git.el index 0541b16d625..e8257c5dbd0 100644 --- a/lisp/vc/vc-git.el +++ b/lisp/vc/vc-git.el @@ -2177,7 +2177,7 @@ This command shares argument histories with \\[rgrep] and \\[grep]." (defun vc-git-command (buffer okstatus file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-git.el. -The difference to vc-do-command is that this function always invokes +The difference to `vc-do-command' is that this function always invokes `vc-git-program'." (let ((coding-system-for-read (or coding-system-for-read vc-git-log-output-coding-system)) diff --git a/lisp/vc/vc-hg.el b/lisp/vc/vc-hg.el index 7de41a2ae50..876d86dc24f 100644 --- a/lisp/vc/vc-hg.el +++ b/lisp/vc/vc-hg.el @@ -1553,7 +1553,7 @@ This runs the command \"hg merge\"." (defun vc-hg-command (buffer okstatus file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-hg.el. -This function differs from vc-do-command in that it invokes +This function differs from `vc-do-command' in that it invokes `vc-hg-program', and passes `vc-hg-global-switches' to it before FLAGS." ;; Disable pager. (let ((process-environment (cons "HGPLAIN=1" process-environment)) diff --git a/lisp/vc/vc-src.el b/lisp/vc/vc-src.el index c85c90f7897..27f58cb3369 100644 --- a/lisp/vc/vc-src.el +++ b/lisp/vc/vc-src.el @@ -211,7 +211,7 @@ For a description of possible values, see `vc-check-master-templates'." (defun vc-src-command (buffer file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-src.el. -This function differs from vc-do-command in that it invokes `vc-src-program'." +This function differs from `vc-do-command' in that it invokes `vc-src-program'." (let (file-list) (cond ((stringp file-or-list) (setq file-list (list "--" file-or-list))) diff --git a/lisp/vc/vc-svn.el b/lisp/vc/vc-svn.el index ae281e54519..d1d4204d055 100644 --- a/lisp/vc/vc-svn.el +++ b/lisp/vc/vc-svn.el @@ -661,7 +661,7 @@ NAME is assumed to be a URL." (defun vc-svn-command (buffer okstatus file-or-list &rest flags) "A wrapper around `vc-do-command' for use in vc-svn.el. -The difference to vc-do-command is that this function always invokes `svn', +The difference to `vc-do-command' is that this function always invokes `svn', and that it passes `vc-svn-global-switches' to it before FLAGS." (apply #'vc-do-command (or buffer "*vc*") okstatus vc-svn-program file-or-list (if (stringp vc-svn-global-switches) diff --git a/lisp/vc/vc.el b/lisp/vc/vc.el index 22d7d2f1e33..597a1622f5a 100644 --- a/lisp/vc/vc.el +++ b/lisp/vc/vc.el @@ -1691,10 +1691,12 @@ Type \\[vc-next-action] to check in changes.") "Please explain why you stole the lock. Type \\`C-c C-c' when done")))) (defun vc-checkin (files backend &optional comment initial-contents rev patch-string) - "Check in FILES. COMMENT is a comment string; if omitted, a -buffer is popped up to accept a comment. If INITIAL-CONTENTS is -non-nil, then COMMENT is used as the initial contents of the log -entry buffer. + "Check in FILES. + +COMMENT is a comment string; if omitted, a buffer is popped up to accept +a comment. If INITIAL-CONTENTS is non-nil, then COMMENT is used as the +initial contents of the log entry buffer. + The optional argument REV may be a string specifying the new revision level (only supported for some older VCSes, like RCS and CVS). The optional argument PATCH-STRING is a string to check in as a patch. 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/which-key.el b/lisp/which-key.el index e9567d262c6..677a84b328d 100644 --- a/lisp/which-key.el +++ b/lisp/which-key.el @@ -128,6 +128,12 @@ of the which-key popup." "If non-nil, don't use any unicode characters in default setup. For affected settings, see `which-key-replacement-alist', `which-key-ellipsis' `which-key-separator'." + :set (lambda (sym val) + (custom-set-default sym val) + (mapc #'custom-reevaluate-setting + '(which-key-separator + which-key-ellipsis))) + :initialize #'custom-initialize-changed :type 'boolean :package-version "1.0" :version "30.1") @@ -228,6 +234,15 @@ you use this feature." (const :tag "Replace command name with docstring" docstring-only)) :package-version "1.0" :version "30.1") +(defcustom which-key-extra-keymaps '(key-translation-map) + "List of extra keymaps to show entries from. +The default is to check `key-translation-map', which contains the +\\='C-x 8' bindings for entering common characters." + :type '(choice (list :tag "Translation map" (const key-translation-map)) + (const :tag "None" nil) + (repeat :tag "Custom" symbol)) + :package-version "1.0" :version "30.1") + (defcustom which-key-highlighted-command-list '() "Rules used to highlight certain commands. If the element is a string, assume it is a regexp pattern for @@ -885,7 +900,15 @@ disable support." ;;;###autoload (define-minor-mode which-key-mode - "Toggle `which-key-mode'." + "Toggle `which-key-mode'. + +`which-key' is a minor mode that displays the key bindings following +your currently entered incomplete command (a prefix) in a popup. + +For example, after enabling the minor mode, if you enter \\`C-x' and +wait for one second (by default), the minibuffer will expand with all +available key bindings that follow \\`C-x' (or as many as space allows +given your settings)." :global t :group 'which-key :lighter which-key-lighter @@ -1052,7 +1075,7 @@ replacement. In the second case, the second string is used to provide a longer name for the keys under a prefix. -MORE allows you to specifcy additional KEY REPLACEMENT pairs. All +MORE allows you to specify additional KEY REPLACEMENT pairs. All replacements are added to `which-key-replacement-alist'." ;; TODO: Make interactive (while key-sequence @@ -1591,7 +1614,7 @@ Within these categories order using `which-key-key-order'." (when found `(replaced . ,key-binding)))) (defun which-key--maybe-replace (key-binding) - "Use `which-key--replacement-alist' to maybe replace KEY-BINDING. + "Use `which-key-replacement-alist' to maybe replace KEY-BINDING. KEY-BINDING is a cons cell of the form \(KEY . BINDING\) each of which are strings. KEY is of the form produced by `key-binding'." (let* ((replacer (if which-key-allow-multiple-replacements @@ -1923,7 +1946,7 @@ Requires `which-key-compute-remaps' to be non-nil." PREFIX limits bindings to those starting with this key sequence. START is a list of existing bindings to add to. If ALL is non-nil, recursively retrieve all bindings below PREFIX. If -EVIL is non-nil, extract active evil bidings." +EVIL is non-nil, extract active evil bindings." (let ((bindings start) (ignore '(self-insert-command ignore ignore-event company-ignore)) (evil-map @@ -1937,8 +1960,10 @@ EVIL is non-nil, extract active evil bidings." (defun which-key--get-current-bindings (&optional prefix filter) "Generate a list of current active bindings." - (let (bindings) - (dolist (map (current-active-maps t) bindings) + (let (bindings + (maps (nconc (current-active-maps t) + (mapcar #'symbol-value which-key-extra-keymaps)))) + (dolist (map maps bindings) (when (cdr map) (setq bindings (which-key--get-keymap-bindings 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/lisp/wid-edit.el b/lisp/wid-edit.el index 3b467434d29..693991a6f3e 100644 --- a/lisp/wid-edit.el +++ b/lisp/wid-edit.el @@ -568,6 +568,29 @@ With CHECK-AFTER non-nil, considers also the content after point, if needed." (delete-overlay inactive) (widget-put widget :inactive nil)))) +(defface widget-unselected + '((t :inherit widget-inactive)) + "Face used for unselected widgets." + :group 'widget-faces + :version "30.1") + +(defun widget-specify-unselected (widget from to) + "Fontify WIDGET as unselected." + (let ((overlay (make-overlay from to nil t nil))) + (overlay-put overlay 'face 'widget-unselected) + (overlay-put overlay 'evaporate t) + ;; The overlay priority here should be lower than the priority in + ;; `widget-specify-active' (bug#69942). + (overlay-put overlay 'priority 90) + (widget-put widget :unselected overlay))) + +(defun widget-specify-selected (widget) + "Remove fontification of WIDGET as unselected." + (let ((unselected (widget-get widget :unselected))) + (when unselected + (delete-overlay unselected) + (widget-put widget :unselected nil)))) + ;;; Widget Properties. (defsubst widget-type (widget) @@ -1276,42 +1299,40 @@ This is much faster.") ARG may be negative to move backward. When the second optional argument is non-nil, nothing is shown in the echo area." - (let ((wrapped 0) - (number arg) - (old (widget-tabable-at))) - ;; Forward. - (while (> arg 0) - (cond ((eobp) - (goto-char (point-min)) - (setq wrapped (1+ wrapped))) - (widget-use-overlay-change - (goto-char (next-overlay-change (point)))) - (t - (forward-char 1))) - (and (= wrapped 2) - (eq arg number) - (error "No buttons or fields found")) - (let ((new (widget-tabable-at))) - (when new - (unless (eq new old) - (setq arg (1- arg)) - (setq old new))))) - ;; Backward. - (while (< arg 0) - (cond ((bobp) - (goto-char (point-max)) - (setq wrapped (1+ wrapped))) - (widget-use-overlay-change - (goto-char (previous-overlay-change (point)))) - (t - (backward-char 1))) - (and (= wrapped 2) - (eq arg number) - (error "No buttons or fields found")) - (let ((new (widget-tabable-at))) - (when new - (unless (eq new old) - (setq arg (1+ arg)))))) + (let* ((wrapped 0) + (number arg) + (fwd (> arg 0)) ; widget-forward is caller. + (bwd (< arg 0)) ; widget-backward is caller. + (old (widget-tabable-at)) + (tabable (if old 1 0)) + pos) + (catch 'one + (while (> (abs arg) 0) + (cond ((or (and fwd (eobp)) (and bwd (bobp))) + (goto-char (cond (fwd (point-min)) + (bwd (point-max)))) + (setq wrapped (1+ wrapped))) + (widget-use-overlay-change + (goto-char (cond (fwd (next-overlay-change (point))) + (bwd (previous-overlay-change (point)))))) + (t + (cond (fwd (forward-char 1)) + (bwd (backward-char 1))))) + (and (= wrapped 2) + (eq arg number) + (if (= tabable 1) + (progn + (goto-char pos) + (throw 'one (message "Only one tabable widget"))) + (error "No buttons or fields found"))) + (let ((new (widget-tabable-at))) + (when new + (if (eq new old) + (setq pos (point)) + (cl-incf tabable) + (setq arg (cond (fwd (1- arg)) + (bwd (1+ arg)))) + (setq old new)))))) (let ((new (widget-tabable-at))) (while (and (eq (widget-tabable-at) new) (not (bobp))) (backward-char))) @@ -2452,10 +2473,16 @@ when he invoked the menu." (defun widget-checkbox-action (widget &optional event) "Toggle checkbox, notify parent, and set active state of sibling." (widget-toggle-action widget event) - (let ((sibling (widget-get-sibling widget))) + (let* ((sibling (widget-get-sibling widget)) + (from (widget-get sibling :from)) + (to (widget-get sibling :to))) (when sibling - (widget-apply sibling - (if (widget-value widget) :activate :deactivate)) + (if (widget-value widget) + (progn + (widget-apply sibling :activate) + (widget-specify-selected sibling)) + :deactivate + (widget-specify-unselected sibling from to)) (widget-clear-undo)))) ;;; The `checklist' Widget. @@ -2511,15 +2538,18 @@ If the item is checked, CHOSEN is a cons whose cdr is the value." ((eq escape ?v) (setq child (cond ((not chosen) - (let ((child (widget-create-child widget type))) - (widget-apply child :deactivate) + (let* ((child (widget-create-child widget type)) + (from (widget-get child :from)) + (to (widget-get child :to))) + (widget-specify-unselected child from to) child)) ((widget-inline-p type t) (widget-create-child-value widget type (cdr chosen))) (t (widget-create-child-value - widget type (car (cdr chosen))))))) + widget type (car (cdr chosen))) + (widget-specify-selected child))))) (t (error "Unknown escape `%c'" escape))))) ;; Update properties. @@ -2690,8 +2720,11 @@ Return an alist of (TYPE MATCH)." (widget-create-child-value widget type value) (widget-create-child widget type))) - (unless chosen - (widget-apply child :deactivate))) + (if chosen + (widget-specify-selected child) + (let ((from (widget-get child :from)) + (to (widget-get child :to))) + (widget-specify-unselected child from to)))) (t (error "Unknown escape `%c'" escape))))) ;; Update properties. @@ -2741,14 +2774,17 @@ Return an alist of (TYPE MATCH)." (dolist (current (widget-get widget :children)) (let* ((button (widget-get current :button)) (match (and (not found) - (widget-apply current :match value)))) + (widget-apply current :match value))) + (from (widget-get current :from)) + (to (widget-get current :to))) (widget-value-set button match) (if match - (progn - (widget-value-set current value) - (widget-apply current :activate)) - (widget-apply current :deactivate)) - (setq found (or found match)))))) + (progn + (widget-value-set current value) + (widget-apply current :activate) + (widget-specify-selected current)) + (widget-specify-unselected current from to)) + (setq found (or found match)))))) (defun widget-radio-validate (widget) ;; Valid if we have made a valid choice. @@ -2768,13 +2804,16 @@ Return an alist of (TYPE MATCH)." (let ((buttons (widget-get widget :buttons))) (when (memq child buttons) (dolist (current (widget-get widget :children)) - (let* ((button (widget-get current :button))) + (let* ((button (widget-get current :button)) + (from (widget-get current :from)) + (to (widget-get current :to))) (cond ((eq child button) (widget-value-set button t) - (widget-apply current :activate)) + (widget-apply current :activate) + (widget-specify-selected current)) ((widget-value button) (widget-value-set button nil) - (widget-apply current :deactivate))))))) + (widget-specify-unselected current from to))))))) ;; Pass notification to parent. (widget-apply widget :notify child event)) diff --git a/lisp/window.el b/lisp/window.el index 0dc9421fde7..60040f18bc7 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -5888,12 +5888,13 @@ is non-nil)." (setq sub (window-right sub)))))))) (defun balance-windows (&optional window-or-frame) - "Balance the sizes of windows of WINDOW-OR-FRAME. -WINDOW-OR-FRAME is optional and defaults to the selected frame. + "Balance the sizes of windows shown on the selected frame. +When called from Lisp, WINDOW-OR-FRAME is optional and defaults to the +selected frame. If WINDOW-OR-FRAME denotes a frame, balance the sizes of all -windows of that frame. If WINDOW-OR-FRAME denotes a window, -recursively balance the sizes of all child windows of that -window." +windows of that frame's root window (which excludes the mini-window). +If WINDOW-OR-FRAME denotes a window, recursively balance the sizes +of all child windows of that window." (interactive) (let* ((window (cond diff --git a/lisp/xwidget.el b/lisp/xwidget.el index cca01c8cb3a..bf5987d742f 100644 --- a/lisp/xwidget.el +++ b/lisp/xwidget.el @@ -378,7 +378,7 @@ one char." (> (window-hscroll) 0)) (set-window-hscroll nil (- (window-hscroll) n)) (xwidget-webkit-execute-script session - (format "window.scrollBy(%-d, 0);" + (format "window.scrollBy(-%d, 0);" (* n (window-font-width))))))) (defun xwidget-webkit-scroll-top () 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" - 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])])]) - if test -n "$module_name"; then - break; - fi - done + # Copy the computed value into ndk_commands. + AS_VAR_COPY([ndk_commands], [AS_TR_SH([ndk_cv_commands_$ndk_module])]) + eval "$ndk_commands" - 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]) +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" -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 + 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 , 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 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 @@ -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 ]) + AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.tm_zone], [], [], + [[#include + ]]) + + 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 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 - 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/sedlibmk.inp b/msdos/sedlibmk.inp index 18f9d911c56..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/ @@ -289,7 +288,7 @@ s/@PACKAGE@/emacs/ /^MKDIR_P *=/s/@MKDIR_P@/echo/ /^NEXT_AS_FIRST_DIRECTIVE_DIRENT_H *=/s/@[^@\n]*@// /^NEXT_AS_FIRST_DIRECTIVE_ERRNO_H *=/s/@[^@\n]*@// -/^NEXT_AS_FIRST_DIRECTIVE_ENDIAN_H *=/s/@[^@\n]*@// +/^NEXT_AS_FIRST_DIRECTIVE_ENDIAN_H *=/s|@[^@\n]*@|| /^NEXT_AS_FIRST_DIRECTIVE_FCNTL_H *=/s/@[^@\n]*@// /^NEXT_AS_FIRST_DIRECTIVE_GETOPT_H *=/s/@[^@\n]*@// /^NEXT_AS_FIRST_DIRECTIVE_LIMITS_H *=/s/@[^@\n]*@// @@ -308,7 +307,7 @@ s/@PACKAGE@/emacs/ /^NEXT_DIRENT_H *=/s/@[^@\n]*@// /^NEXT_DIRENT_H *=/s/@[^@\n]*@// /^NEXT_ERRNO_H *=/s/@[^@\n]*@// -/^NEXT_ENDIAN_H *=/s/@[^@\n]*@// +/^NEXT_ENDIAN_H *=/s|@[^@\n]*@|| /^NEXT_FCNTL_H *=/s/@[^@\n]*@// /^NEXT_FLOAT_H *=/s/@[^@\n]*@// /^NEXT_GETOPT_H *=/s/@[^@\n]*@// diff --git a/src/ChangeLog.12 b/src/ChangeLog.12 index 7792bd88c01..798e87dd572 100644 --- a/src/ChangeLog.12 +++ b/src/ChangeLog.12 @@ -5956,7 +5956,7 @@ Assume C89 or later for math functions (Bug#12381). This simplifies the code, and makes it a bit smaller and faster, and (most important) makes it easier to clean up signal handling - since we can stop worring about floating-point exceptions in + since we can stop worrying about floating-point exceptions in library code. That was a problem before C89, but the problem went away many years ago on all practical Emacs targets. * data.c, image.c, lread.c, print.c: diff --git a/src/android-emacs.c b/src/android-emacs.c index 5a43445612a..d68734da1bd 100644 --- a/src/android-emacs.c +++ b/src/android-emacs.c @@ -52,49 +52,6 @@ main (int argc, char **argv) args[0] = (char *) "/system/bin/app_process"; #endif /* __x86_64__ || __aarch64__ || __mips64 */ - /* Machines with ART require the boot classpath to be manually - specified. Machines with Dalvik however refuse to do so, as they - open the jars inside the BOOTCLASSPATH environment variable at - startup, resulting in the following crash: - - W/dalvikvm( 1608): Refusing to reopen boot DEX - '/system/framework/core.jar' - W/dalvikvm( 1608): Refusing to reopen boot DEX - '/system/framework/bouncycastle.jar' - E/dalvikvm( 1608): Too many exceptions during init (failed on - 'Ljava/io/IOException;' 'Re-opening BOOTCLASSPATH DEX files is - not allowed') - E/dalvikvm( 1608): VM aborting */ - -#if HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL - if (android_get_device_api_level () < 21) - { - bootclasspath = NULL; - goto skip_setup; - } -#else /* !HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL */ - if (__ANDROID_API__ < 21) - { - bootclasspath = NULL; - goto skip_setup; - } -#endif /* HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL */ - - /* Next, obtain the boot class path. */ - bootclasspath = getenv ("BOOTCLASSPATH"); - - if (!bootclasspath) - { - fprintf (stderr, "The BOOTCLASSPATH environment variable" - " is not set. As a result, Emacs does not know" - " how to start app_process.\n" - "This is likely a change in the Android platform." - " Please report this to bug-gnu-emacs@gnu.org.\n"); - return 1; - } - - skip_setup: - /* And the Emacs class path. */ emacs_class_path = getenv ("EMACS_CLASS_PATH"); @@ -115,23 +72,11 @@ main (int argc, char **argv) if (ld_library_path) setenv ("LD_LIBRARY_PATH", ld_library_path, 1); - if (bootclasspath) + if (asprintf (&bootclasspath, "-Djava.class.path=%s", + emacs_class_path) < 0) { - if (asprintf (&bootclasspath, "-Djava.class.path=%s:%s", - bootclasspath, emacs_class_path) < 0) - { - perror ("asprintf"); - return 1; - } - } - else - { - if (asprintf (&bootclasspath, "-Djava.class.path=%s", - emacs_class_path) < 0) - { - perror ("asprintf"); - return 1; - } + perror ("asprintf"); + return 1; } args[1] = bootclasspath; diff --git a/src/android.c b/src/android.c index 3c0e3ee1558..f90ebc04925 100644 --- a/src/android.c +++ b/src/android.c @@ -2019,6 +2019,8 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, c_argument = (*env)->GetStringUTFChars (env, (jstring) dump_file_object, NULL); + if (!c_argument) + emacs_abort (); /* Copy the Java string data once. */ dump_file = strdup (c_argument); @@ -6497,18 +6499,18 @@ android_browse_url (Lisp_Object url, Lisp_Object send) buffer = (*android_java_env)->GetStringUTFChars (android_java_env, (jstring) value, NULL); - android_exception_check_1 (value); + android_exception_check_nonnull ((void *) buffer, value); /* Otherwise, build the string describing the error. */ - tem = build_string_from_utf8 (buffer); + tem = build_unibyte_string (buffer); (*android_java_env)->ReleaseStringUTFChars (android_java_env, (jstring) value, buffer); - /* And return it. */ + /* And decode and return the same. */ ANDROID_DELETE_LOCAL_REF (value); - return tem; + return code_convert_string_norecord (tem, Qandroid_jni, false); } /* Tell the system to restart Emacs in a short amount of time, and diff --git a/src/androidterm.c b/src/androidterm.c index 837cc50bfa1..4561f2d1df3 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -1279,7 +1279,12 @@ handle_one_android_event (struct android_display_info *dpyinfo, { expose_frame (f, event->xexpose.x, event->xexpose.y, event->xexpose.width, event->xexpose.height); - show_back_buffer (f); + + /* Do not display the back buffer if F is yet being + updated, as this might trigger premature bitmap + reconfiguration. */ + if (FRAME_ANDROID_COMPLETE_P (f)) + show_back_buffer (f); } } diff --git a/src/androidvfs.c b/src/androidvfs.c index 346eb639b11..833c6b1b2a7 100644 --- a/src/androidvfs.c +++ b/src/androidvfs.c @@ -3162,6 +3162,37 @@ android_saf_exception_check (int n, ...) return 1; } +/* Verify that OBJECT is non-NULL. If NULL, free each of the N local + references given as arguments, and clear exceptions. + + Value is 1 if it be NULL, 0 otherwise. */ + +static int +android_saf_check_nonnull (const void *object, int n, ...) +{ + va_list ap; + + if (object) + return 0; + + va_start (ap, n); + + /* Clear the active exception, making it safe to subsequently call + other JNI functions. */ + (*android_java_env)->ExceptionClear (android_java_env); + + /* Delete each of the N arguments. */ + + while (n > 0) + { + ANDROID_DELETE_LOCAL_REF (va_arg (ap, jobject)); + n--; + } + + va_end (ap); + return 1; +} + /* Content authority-based vnode implementation. @@ -6428,7 +6459,7 @@ android_saf_new_mkdir (struct android_vnode *vnode, mode_t mode) new_doc_id = (*android_java_env)->GetStringUTFChars (android_java_env, new_id, NULL); - if (android_saf_exception_check (3, name, id, uri)) + if (android_saf_check_nonnull (new_doc_id, 3, name, id, uri)) return -1; xfree (vp->document_id); diff --git a/src/buffer.c b/src/buffer.c index 982c6815dc0..d2cd3bf9cdc 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -5251,7 +5251,7 @@ A string is printed verbatim in the mode line except for %-constructs: %P -- print percent of buffer above bottom of window, perhaps plus Top, or print Bottom or All. %q -- print percent of buffer above both the top and the bottom of the - window, separated by ‘-’, or ‘All’. + window, separated by `-', or `All'. %s -- print process status. %z -- print mnemonics of keyboard, terminal, and buffer coding systems. %Z -- like %z, but including the end-of-line format. diff --git a/src/coding.c b/src/coding.c index 71aee2f7008..90ccc85eb89 100644 --- a/src/coding.c +++ b/src/coding.c @@ -6365,7 +6365,7 @@ make_string_from_utf8 (const char *text, ptrdiff_t nbytes) /* If TEXT is a valid UTF-8 string, we can convert it to a Lisp string directly. Otherwise, we need to decode it. */ if (chars == nbytes || bytes == nbytes) - return make_specified_string (text, chars, nbytes, true); + return make_multibyte_string (text, chars, nbytes); else { struct coding_system coding; diff --git a/src/comp.c b/src/comp.c index 58d72de42b8..a2f7b384f4f 100644 --- a/src/comp.c +++ b/src/comp.c @@ -5795,7 +5795,7 @@ natively-compiled one. */); DEFSYM (Qd_ephemeral, "d-ephemeral"); /* Others. */ - DEFSYM (Qcomp, "comp"); + DEFSYM (Qnative_compiler, "native-compiler"); DEFSYM (Qfixnum, "fixnum"); DEFSYM (Qscratch, "scratch"); DEFSYM (Qlate, "late"); diff --git a/src/cygw32.h b/src/cygw32.h index cc3414a39d9..2f265cab4ad 100644 --- a/src/cygw32.h +++ b/src/cygw32.h @@ -35,5 +35,6 @@ along with GNU Emacs. If not, see . */ extern void syms_of_cygw32 (void); extern char * w32_strerror (int error_no); +extern LPBYTE w32_get_resource (const char * key, const char * name, LPDWORD type); #endif /* CYGW32_H */ diff --git a/src/dbusbind.c b/src/dbusbind.c index 35ce03c7911..1a8bcfdf5d4 100644 --- a/src/dbusbind.c +++ b/src/dbusbind.c @@ -1314,7 +1314,7 @@ The following usages are expected: `dbus-call-method', `dbus-call-method-asynchronously': (dbus-message-internal dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER - &optional :timeout TIMEOUT &rest ARGS) + &optional :timeout TIMEOUT :authorizable AUTH &rest ARGS) `dbus-send-signal': (dbus-message-internal @@ -1512,12 +1512,38 @@ usage: (dbus-message-internal &rest REST) */) XD_SIGNAL1 (build_string ("Unable to create an error message")); } - /* Check for timeout parameter. */ - if ((count + 2 <= nargs) && EQ (args[count], QCtimeout)) + while ((count + 2 <= nargs)) { - CHECK_FIXNAT (args[count+1]); - timeout = min (XFIXNAT (args[count+1]), INT_MAX); - count = count+2; + /* Check for timeout parameter. */ + if (EQ (args[count], QCtimeout)) + { + if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL) + XD_SIGNAL1 + (build_string (":timeout is only supported on method calls")); + + CHECK_FIXNAT (args[count+1]); + timeout = min (XFIXNAT (args[count+1]), INT_MAX); + count = count + 2; + } + /* Check for authorizable parameter. */ + else if (EQ (args[count], QCauthorizable)) + { + if (mtype != DBUS_MESSAGE_TYPE_METHOD_CALL) + XD_SIGNAL1 + (build_string (":authorizable is only supported on method calls")); + + /* Ignore this keyword if unsupported. */ +#ifdef HAVE_DBUS_MESSAGE_SET_ALLOW_INTERACTIVE_AUTHORIZATION + dbus_message_set_allow_interactive_authorization + (dmessage, NILP (args[count+1]) ? FALSE : TRUE); +#else + XD_DEBUG_MESSAGE (":authorizable not supported"); +#endif + + count = count + 2; + } + else break; + } /* Initialize parameter list of message. */ @@ -1895,6 +1921,9 @@ syms_of_dbusbind (void) /* Lisp symbol for method call timeout. */ DEFSYM (QCtimeout, ":timeout"); + /* Lisp symbol for method interactive authorization. */ + DEFSYM (QCauthorizable, ":authorizable"); + /* Lisp symbols of D-Bus types. */ DEFSYM (QCbyte, ":byte"); DEFSYM (QCboolean, ":boolean"); diff --git a/src/dispextern.h b/src/dispextern.h index 3f62b8776c7..89b55ea3cbf 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3662,7 +3662,7 @@ extern void x_kill_gs_process (Pixmap, struct frame *); extern Lisp_Object image_find_image_file (Lisp_Object); struct image_cache *make_image_cache (void); -void free_image_cache (struct frame *); +extern void free_image_cache (struct frame *); void clear_image_caches (Lisp_Object); void mark_image_cache (struct image_cache *); void image_prune_animation_caches (bool); diff --git a/src/emacs.c b/src/emacs.c index 28e43f006ad..a865accd415 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -23,6 +23,7 @@ along with GNU Emacs. If not, see . */ #include #include +#include #include #include @@ -133,10 +134,6 @@ extern char etext; # endif #endif -#ifdef HAVE_SETLOCALE -#include -#endif - #if HAVE_WCHAR_H # include #endif @@ -403,14 +400,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) @@ -1407,6 +1396,10 @@ main (int argc, char **argv) the additional call here is harmless.) */ cache_system_info (); #ifdef WINDOWSNT + /* This must be called to initialize w32_unicode_filenames and + is_windows_9x prior to w32_init_current_directory. */ + globals_of_w32 (); + /* On Windows 9X, we have to load UNICOWS.DLL as early as possible, to have non-stub implementations of APIs we need to convert file names between UTF-8 and the system's ANSI codepage. */ @@ -1531,11 +1524,10 @@ main (int argc, char **argv) } } #endif - emacs_wd = emacs_get_current_dir_name (); #ifdef WINDOWSNT initial_wd = emacs_wd; -#endif +#endif /* WINDOWSNT */ #ifdef HAVE_PDUMPER if (dumped_with_pdumper_p ()) pdumper_record_wd (emacs_wd); @@ -2190,7 +2182,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem init_atimer (); #ifdef WINDOWSNT - globals_of_w32 (); + /* We need to forget about libraries that were loaded during the + dumping process (e.g. libgccjit). This must be done _after_ + load_pdump. */ + Vlibrary_cache = Qnil; #ifdef HAVE_W32NOTIFY globals_of_w32notify (); #endif @@ -3295,7 +3290,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) @@ -3315,7 +3309,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 @@ -3324,9 +3318,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 } } @@ -3340,21 +3334,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/fileio.c b/src/fileio.c index 7afe3e75737..fa280f2db00 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -523,7 +523,7 @@ file_name_directory (Lisp_Object filename) else { dostounix_filename (beg); - tem_fn = make_specified_string (beg, -1, p - beg, 0); + tem_fn = make_unibyte_string (beg, p - beg); } SAFE_FREE (); return tem_fn; diff --git a/src/fns.c b/src/fns.c index 7df28588e2c..ea5d4e7ebd4 100644 --- a/src/fns.c +++ b/src/fns.c @@ -3015,6 +3015,25 @@ bool_vector_cmp (Lisp_Object a, Lisp_Object b) return (d & aw) ? 1 : -1; } +/* Return -1 if ab, 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 ab 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 @@ -3036,9 +3055,9 @@ value_cmp (Lisp_Object a, Lisp_Object b, int maxdepth) { EMACS_INT ia = XFIXNUM (a); if (FIXNUMP (b)) - return ia < XFIXNUM (b) ? -1 : 1; /* we know that a≠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)); } @@ -3179,7 +3198,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/gnutls.c b/src/gnutls.c index 3ff7f21d5a5..334d1d47eb6 100644 --- a/src/gnutls.c +++ b/src/gnutls.c @@ -1646,8 +1646,7 @@ string representation. */) emacs_gnutls_strerror (err)); } - Lisp_Object result = make_string_from_bytes ((char *) out.data, out.size, - out.size); + Lisp_Object result = make_unibyte_string ((char *) out.data, out.size); gnutls_free (out.data); gnutls_x509_crt_deinit (crt); diff --git a/src/image.c b/src/image.c index 9dc4c543db6..24a4e61a8da 100644 --- a/src/image.c +++ b/src/image.c @@ -2320,31 +2320,20 @@ void free_image_cache (struct frame *f) { struct image_cache *c = FRAME_IMAGE_CACHE (f); - if (c) - { - ptrdiff_t i; + ptrdiff_t i; - /* Cache should not be referenced by any frame when freed. */ - eassert (c->refcount == 0); + /* Cache should not be referenced by any frame when freed. */ + eassert (c->refcount == 0); - for (i = 0; i < c->used; ++i) - free_image (f, c->images[i]); + for (i = 0; i < c->used; ++i) + free_image (f, c->images[i]); #ifndef HAVE_MPS - xfree (c->images); + xfree (c->images); + xfree (c->buckets); + xfree (c); #endif - c->images = NULL; -#ifndef HAVE_MPS - xfree (c->buckets); -#endif - c->buckets = NULL; -#ifndef HAVE_MPS - xfree (c); -#endif - FRAME_IMAGE_CACHE (f) = NULL; - } } - /* Clear image cache of frame F. FILTER=t means free all images. FILTER=nil means clear only images that haven't been displayed for some time. diff --git a/src/lisp.h b/src/lisp.h index 34bf483b511..e57db399d0c 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -5514,15 +5514,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 188922516ea..341ae77b702 100644 --- a/src/lread.c +++ b/src/lread.c @@ -28,6 +28,7 @@ along with GNU Emacs. If not, see . */ #include #include #include +#include #include #include #include "lisp.h" @@ -56,11 +57,6 @@ along with GNU Emacs. If not, see . */ #endif #include - -#ifdef HAVE_SETLOCALE -#include -#endif /* HAVE_SETLOCALE */ - #include #if !defined HAVE_ANDROID || defined ANDROID_STUBIFY \ @@ -1888,7 +1884,7 @@ maybe_swap_for_eln (bool no_native, Lisp_Object *filename, int *fd, return; Vdelayed_warnings_list = Fcons (list2 - (Qcomp, + (Qnative_compiler, CALLN (Fformat, build_string ("Cannot look up .eln file " "for %s because no source " @@ -4991,8 +4987,8 @@ it defaults to the value of `obarray'. */) { if (longhand) { - tem = intern_driver (make_specified_string (longhand, longhand_chars, - longhand_bytes, true), + tem = intern_driver (make_multibyte_string (longhand, longhand_chars, + longhand_bytes), obarray, tem); xfree (longhand); } diff --git a/src/marker.c b/src/marker.c index 3290917b268..90c9290a3d2 100644 --- a/src/marker.c +++ b/src/marker.c @@ -206,7 +206,7 @@ buf_charpos_to_bytepos (struct buffer *b, ptrdiff_t charpos) { CONSIDER (tail->charpos, tail->bytepos); - /* If we are down to a range of 50 chars, + /* If we are down to a range of DISTANCE chars, don't bother checking any other markers; scan the intervening chars directly now. */ if (best_above - charpos < distance @@ -361,8 +361,8 @@ buf_bytepos_to_charpos (struct buffer *b, ptrdiff_t 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 - bytepos < distance - || bytepos - best_below < distance) + if (best_above_byte - bytepos < distance + || bytepos - best_below_byte < distance) break; else distance += BYTECHAR_DISTANCE_INCREMENT; diff --git a/src/pdumper.c b/src/pdumper.c index 73719567f80..26addfe3852 100644 --- a/src/pdumper.c +++ b/src/pdumper.c @@ -2233,8 +2233,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." @@ -2261,17 +2260,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; } @@ -2288,7 +2287,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; } @@ -2317,9 +2316,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/pgtkterm.c b/src/pgtkterm.c index 7ec0969a14b..f883a4c439f 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -3596,20 +3596,7 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, pgtk_clip_to_row (w, row, ANY_AREA, cr); if (p->bx >= 0 && !p->overlay_p) - { - /* In case the same realized face is used for fringes and for - something displayed in the text (e.g. face `region' on - mono-displays, the fill style may have been changed to - FillSolid in pgtk_draw_glyph_string_background. */ - if (face->stipple) - fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny); - else - { - pgtk_set_cr_source_with_color (f, face->background, true); - cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); - cairo_fill (cr); - } - } + fill_background_by_face (f, face, p->bx, p->by, p->nx, p->ny); if (p->which && p->which < max_fringe_bmp diff --git a/src/search.c b/src/search.c index 18d84b89024..e2fe7ce069d 100644 --- a/src/search.c +++ b/src/search.c @@ -2817,11 +2817,12 @@ match_limit (Lisp_Object num, bool beginningp) DEFUN ("match-beginning", Fmatch_beginning, Smatch_beginning, 1, 1, 0, doc: /* Return position of start of text matched by last search. -SUBEXP, a number, specifies which parenthesized expression in the last - regexp. -Value is nil if SUBEXPth pair didn't match, or there were less than - SUBEXP pairs. -Zero means the entire text matched by the whole regexp or whole string. +SUBEXP, a number, specifies the parenthesized subexpression in the last + regexp for which to return the start position. +Value is nil if SUBEXPth subexpression didn't match, or there were fewer + than SUBEXP subexpressions. +SUBEXP zero means the entire text matched by the whole regexp or whole + string. Return value is undefined if the last search failed. */) (Lisp_Object subexp) @@ -2831,11 +2832,12 @@ Return value is undefined if the last search failed. */) DEFUN ("match-end", Fmatch_end, Smatch_end, 1, 1, 0, doc: /* Return position of end of text matched by last search. -SUBEXP, a number, specifies which parenthesized expression in the last - regexp. -Value is nil if SUBEXPth pair didn't match, or there were less than - SUBEXP pairs. -Zero means the entire text matched by the whole regexp or whole string. +SUBEXP, a number, specifies the parenthesized subexpression in the last + regexp for which to return the start position. +Value is nil if SUBEXPth subexpression didn't match, or there were fewer + than SUBEXP subexpressions. +SUBEXP zero means the entire text matched by the whole regexp or whole + string. Return value is undefined if the last search failed. */) (Lisp_Object subexp) 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 # include -# if defined HAVE_NEWLOCALE || defined HAVE_SETLOCALE -# include -# endif -# ifndef LC_COLLATE -# define LC_COLLATE 0 -# endif +# include # 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/textconv.c b/src/textconv.c index 0e43bd9d458..e3f928cd789 100644 --- a/src/textconv.c +++ b/src/textconv.c @@ -153,6 +153,15 @@ select_window (Lisp_Object window, Lisp_Object norecord) Fselect_window (window, norecord); } +/* Restore the selected window WINDOW. */ + +static void +restore_selected_window (Lisp_Object window) +{ + /* FIXME: not sure what to do if WINDOW has been deleted. */ + select_window (window, Qt); +} + /* Perform the text conversion operation specified in QUERY and return the results. @@ -188,6 +197,7 @@ textconv_query (struct frame *f, struct textconv_callback_struct *query, selected window. */ count = SPECPDL_INDEX (); record_unwind_protect_excursion (); + record_unwind_protect (restore_selected_window, selected_window); /* Inhibit quitting. */ specbind (Qinhibit_quit, Qt); @@ -586,15 +596,6 @@ detect_conversion_events (void) return false; } -/* Restore the selected window WINDOW. */ - -static void -restore_selected_window (Lisp_Object window) -{ - /* FIXME: not sure what to do if WINDOW has been deleted. */ - select_window (window, Qt); -} - /* Commit the given text in the composing region. If there is no composing region, then insert the text after frame F's selected window's last point instead, unless the mark is active. Finally, @@ -1138,6 +1139,10 @@ locate_and_save_position_in_field (struct frame *f, struct window *w, /* Set the current buffer to W's. */ count = SPECPDL_INDEX (); + + /* The current buffer must be saved, not merely the selected + window. */ + record_unwind_protect_excursion (); record_unwind_protect (restore_selected_window, selected_window); XSETWINDOW (window, w); select_window (window, Qt); @@ -2097,6 +2102,7 @@ get_extracted_text (struct frame *f, ptrdiff_t n, selected window. */ count = SPECPDL_INDEX (); record_unwind_protect_excursion (); + record_unwind_protect (restore_selected_window, selected_window); /* Inhibit quitting. */ specbind (Qinhibit_quit, Qt); @@ -2219,6 +2225,7 @@ get_surrounding_text (struct frame *f, ptrdiff_t left, selected window. */ count = SPECPDL_INDEX (); record_unwind_protect_excursion (); + record_unwind_protect (restore_selected_window, selected_window); /* Inhibit quitting. */ specbind (Qinhibit_quit, Qt); diff --git a/src/treesit.c b/src/treesit.c index 54b16eb1bb3..a0e41add475 100644 --- a/src/treesit.c +++ b/src/treesit.c @@ -846,7 +846,6 @@ treesit_record_change (ptrdiff_t start_byte, ptrdiff_t old_end_byte, treesit_tree_edit_1 (tree, start_offset, old_end_offset, new_end_offset); XTS_PARSER (lisp_parser)->need_reparse = true; - XTS_PARSER (lisp_parser)->timestamp++; /* VISIBLE_BEG/END records tree-sitter's range of view in the buffer. We need to adjust them when tree-sitter's @@ -948,10 +947,7 @@ treesit_sync_visible_region (Lisp_Object parser) this function is called), we need to reparse. */ if (visible_beg != BUF_BEGV_BYTE (buffer) || visible_end != BUF_ZV_BYTE (buffer)) - { - XTS_PARSER (parser)->need_reparse = true; - XTS_PARSER (parser)->timestamp++; - } + XTS_PARSER (parser)->need_reparse = true; /* Before we parse or set ranges, catch up with the narrowing situation. We change visible_beg and visible_end to match @@ -1090,6 +1086,7 @@ treesit_ensure_parsed (Lisp_Object parser) XTS_PARSER (parser)->tree = new_tree; XTS_PARSER (parser)->need_reparse = false; + XTS_PARSER (parser)->timestamp++; /* After-change functions should run at the very end, most crucially after need_reparse is set to false, this way if the function @@ -1725,7 +1722,6 @@ buffer. */) ranges); XTS_PARSER (parser)->need_reparse = true; - XTS_PARSER (parser)->timestamp++; return Qnil; } @@ -2923,11 +2919,10 @@ be completely in the region. If NODE-ONLY is non-nil, return a list of nodes. -Besides a node, NODE can also be a parser, in which case the root node -of that parser is used. -NODE can also be a language symbol, in which case the root node of a -parser for that language is used. If such a parser doesn't exist, it -is created. +Besides a node, NODE can be a parser, in which case the root node of +that parser is used. NODE can also be a language symbol, in which case +the root node of a parser for that language is used. If such a parser +doesn't exist, it is created. Signal `treesit-query-error' if QUERY is malformed or something else goes wrong. You can use `treesit-query-validate' to validate and debug @@ -2941,8 +2936,13 @@ the query. */) treesit_initialize (); - /* Resolve NODE into an actual node. */ + /* Resolve NODE into an actual node, signals if node not + up-to-date. */ Lisp_Object lisp_node = treesit_resolve_node (node); + /* As of right now, the node returned by treesit_resolve_node always + passes treesit_check_node; but it might not be true in the future, + so adding the line below just to be safe. */ + treesit_check_node (lisp_node); /* Extract C values from Lisp objects. */ TSNode treesit_node = XTS_NODE (lisp_node)->node; @@ -2970,8 +2970,8 @@ the query. */) &signal_symbol, &signal_data)) xsignal (signal_symbol, signal_data); - /* WARN: After this point, free TREESIT_QUERY and CURSOR before every - signal and return if NEEDS_TO_FREE_QUERY_AND_CURSOR is true. */ + /* WARN: After this point, if NEEDS_TO_FREE_QUERY_AND_CURSOR is true, + free TREESIT_QUERY and CURSOR before every signal and return. */ /* Set query range. */ if (!NILP (beg) && !NILP (end)) diff --git a/src/w32.c b/src/w32.c index 1c6a56bcbd9..ab45ae8ec6b 100644 --- a/src/w32.c +++ b/src/w32.c @@ -10624,6 +10624,7 @@ maybe_load_unicows_dll (void) pWideCharToMultiByte = (WideCharToMultiByte_Proc) get_proc_addr (ret, "WideCharToMultiByte"); multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; + load_unicows_dll_for_w32fns (ret); return ret; } else @@ -10658,6 +10659,7 @@ maybe_load_unicows_dll (void) multiByteToWideCharFlags = 0; else multiByteToWideCharFlags = MB_ERR_INVALID_CHARS; + load_unicows_dll_for_w32fns (NULL); return LoadLibrary ("Gdi32.dll"); } } @@ -10967,10 +10969,6 @@ globals_of_w32 (void) #endif w32_crypto_hprov = (HCRYPTPROV)0; - - /* We need to forget about libraries that were loaded during the - dumping process (e.g. libgccjit) */ - Vlibrary_cache = Qnil; } /* For make-serial-process */ diff --git a/src/w32.h b/src/w32.h index cf470ae9901..3dc79dabf4b 100644 --- a/src/w32.h +++ b/src/w32.h @@ -170,6 +170,7 @@ extern void release_listen_threads (void); extern void init_ntproc (int); extern void term_ntproc (int); extern HANDLE maybe_load_unicows_dll (void); +extern void load_unicows_dll_for_w32fns (HMODULE); extern void globals_of_w32 (void); extern void term_timers (void); diff --git a/src/w32fns.c b/src/w32fns.c index b784a9a563d..7fc2f598b3e 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -2612,6 +2612,7 @@ my_post_msg (W32Msg * wmsg, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } #ifdef WINDOWSNT + /* The Windows keyboard hook callback. */ static LRESULT CALLBACK funhook (int code, WPARAM w, LPARAM l) @@ -2688,8 +2689,8 @@ funhook (int code, WPARAM w, LPARAM l) can prevent this by setting the w32-pass-[lr]window-to-system variable to NIL. */ - if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) || - (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))) + if ((hs->vkCode == VK_LWIN && !NILP (Vw32_pass_lwindow_to_system)) + || (hs->vkCode == VK_RWIN && !NILP (Vw32_pass_rwindow_to_system))) { /* Not prevented - Simulate the keypress to the system. */ memset (inputs, 0, sizeof (inputs)); @@ -6150,7 +6151,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, if (harfbuzz_available) register_font_driver (&harfbuzz_font_driver, f); #endif - register_font_driver (&uniscribe_font_driver, f); + if (uniscribe_available) + register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); gui_default_parameter (f, parameters, Qfont_backend, Qnil, @@ -7227,7 +7229,8 @@ w32_create_tip_frame (struct w32_display_info *dpyinfo, Lisp_Object parms) if (harfbuzz_available) register_font_driver (&harfbuzz_font_driver, f); #endif - register_font_driver (&uniscribe_font_driver, f); + if (uniscribe_available) + register_font_driver (&uniscribe_font_driver, f); register_font_driver (&w32font_driver, f); gui_default_parameter (f, parms, Qfont_backend, Qnil, @@ -8265,6 +8268,8 @@ DEFUN ("x-file-dialog", Fx_file_dialog, Sx_file_dialog, 2, 5, 0, #ifdef WINDOWSNT +static int (WINAPI *pfnSHFileOperationW) (LPSHFILEOPSTRUCTW); + /* Moving files to the system recycle bin. Used by `move-file-to-trash' instead of the default moving to ~/.Trash */ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, @@ -8276,6 +8281,9 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, Lisp_Object encoded_file; Lisp_Object operation; + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + operation = Qdelete_file; if (!NILP (Ffile_directory_p (filename)) && NILP (Ffile_symlink_p (filename))) @@ -8324,7 +8332,10 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash, | FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS; file_op_w.fAnyOperationsAborted = FALSE; - result = SHFileOperationW (&file_op_w); + /* This is stated to exist on all versions of Windows NT Emacs + supports. */ + eassert (pfnSHFileOperationW); + result = (*pfnSHFileOperationW) (&file_op_w); } else { @@ -8389,6 +8400,10 @@ If optional parameter FRAME is not specified, use selected frame. */) return Qnil; } +#ifndef CYGWIN +static BOOL (WINAPI *pfnShellExecuteExW) (LPSHELLEXECUTEINFOW); +#endif /* !CYGWIN */ + DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0, doc: /* Get Windows to perform OPERATION on DOCUMENT. This is a wrapper around the ShellExecute system function, which @@ -8539,6 +8554,9 @@ a ShowWindow flag: const int file_url_len = sizeof (file_url_str) - 1; int doclen; + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + if (strncmp (SSDATA (document), file_url_str, file_url_len) == 0) { /* Passing "file:///" URLs to ShellExecute causes shlwapi.dll to @@ -8598,7 +8616,7 @@ a ShowWindow flag: doc_w = xmalloc (doclen * sizeof (wchar_t)); pMultiByteToWideChar (CP_UTF8, multiByteToWideCharFlags, SSDATA (document), -1, doc_w, doclen); - if (use_unicode) + if (use_unicode && pfnShellExecuteExW) { wchar_t current_dir_w[MAX_PATH]; SHELLEXECUTEINFOW shexinfo_w; @@ -8650,7 +8668,7 @@ a ShowWindow flag: shexinfo_w.lpDirectory = current_dir_w; shexinfo_w.nShow = (FIXNUMP (show_flag) ? XFIXNUM (show_flag) : SW_SHOWDEFAULT); - success = ShellExecuteExW (&shexinfo_w); + success = (*pfnShellExecuteExW) (&shexinfo_w); xfree (doc_w); } else @@ -9121,6 +9139,7 @@ and width values are in pixels. menu_bar.cbSize = sizeof (menu_bar); menu_bar.rcBar.right = menu_bar.rcBar.left = 0; menu_bar.rcBar.top = menu_bar.rcBar.bottom = 0; + GetMenuBarInfo (FRAME_W32_WINDOW (f), 0xFFFFFFFD, 0, &menu_bar); single_menu_bar_height = GetSystemMetrics (SM_CYMENU); wrapped_menu_bar_height = GetSystemMetrics (SM_CYMENUSIZE); @@ -10007,6 +10026,8 @@ Internal use only. */) #if defined WINDOWSNT && !defined HAVE_DBUS +static BOOL (WINAPI *pfnShell_NotifyIconW) (DWORD, PNOTIFYICONDATAW); + /*********************************************************************** Tray notifications ***********************************************************************/ @@ -10273,7 +10294,7 @@ add_tray_notification (struct frame *f, const char *icon, const char *tip, } } - if (!Shell_NotifyIconW (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) + if (!(*pfnShell_NotifyIconW) (NIM_ADD, (PNOTIFYICONDATAW)&nidw)) { /* GetLastError returns meaningless results when Shell_NotifyIcon fails. */ @@ -10305,7 +10326,7 @@ delete_tray_notification (struct frame *f, int id) nidw.hWnd = FRAME_W32_WINDOW (f); nidw.uID = id; - if (!Shell_NotifyIconW (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) + if (!(*pfnShell_NotifyIconW) (NIM_DELETE, (PNOTIFYICONDATAW)&nidw)) { /* GetLastError returns meaningless results when Shell_NotifyIcon fails. */ @@ -10372,8 +10393,8 @@ The following parameters are supported: characters long, and will be truncated if it's longer. Note that versions of Windows before W2K support only `:icon' and `:tip'. -You can pass the other parameters, but they will be ignored on those -old systems. +You can pass the other parameters, but they will be ignored on +those old systems. There can be at most one active notification at any given time. An active notification must be removed by calling `w32-notification-close' @@ -10389,7 +10410,10 @@ usage: (w32-notification-notify &rest PARAMS) */) enum NI_Severity severity; unsigned timeout = 0; - if (nargs == 0) + /* Required on Windows 9X. */ + maybe_load_unicows_dll (); + + if (nargs == 0 || !pfnShell_NotifyIconW) return Qnil; arg_plist = Flist (nargs, args); @@ -10448,7 +10472,7 @@ DEFUN ("w32-notification-close", { struct frame *f = SELECTED_FRAME (); - if (FIXNUMP (id)) + if (FIXNUMP (id) && !pfnShell_NotifyIconW) delete_tray_notification (f, XFIXNUM (id)); return Qnil; @@ -11284,7 +11308,7 @@ typedef USHORT (WINAPI * CaptureStackBackTrace_proc) (ULONG, ULONG, PVOID *, configure.ac. */ #if defined MINGW_W64 && EMACS_INT_MAX > LONG_MAX # define DEFAULT_IMAGE_BASE (ptrdiff_t)0x400000000 -#else /* 32-bit MinGW build */ +#elif !defined CYGWIN /* 32-bit MinGW build */ # define DEFAULT_IMAGE_BASE (ptrdiff_t)0x01000000 #endif @@ -11499,7 +11523,7 @@ globals_of_w32fns (void) get_proc_addr (wtsapi32_lib, "WTSRegisterSessionNotification"); WTSUnRegisterSessionNotification_fn = (WTSUnRegisterSessionNotification_Proc) get_proc_addr (wtsapi32_lib, "WTSUnRegisterSessionNotification"); -#endif +#endif /* WINDOWSNT */ /* Support OS dark mode on Windows 10 version 1809 and higher. See `w32_applytheme' which uses appropriate APIs per version of Windows. @@ -11580,6 +11604,32 @@ Changing the value takes effect only for frames created after the change. */); syms_of_w32uniscribe (); } +#ifdef WINDOWSNT + +/* Initialize pointers to functions whose real implementations exist in + UNICOWS.DLL on Windows 9X. UNICOWS should be a pointer to a loaded + handle referencing UNICOWS.DLL, or NULL on Windows NT systems. */ + +void +load_unicows_dll_for_w32fns (HMODULE unicows) +{ + if (!unicows) + /* The functions following are defined by SHELL32.DLL onw Windows + NT. */ + unicows = GetModuleHandle ("shell32"); + + pfnSHFileOperationW + = (void *) get_proc_addr (unicows, "SHFileOperationW"); + pfnShellExecuteExW + = (void *) get_proc_addr (unicows, "ShellExecuteExW"); +#ifndef HAVE_DBUS + pfnShell_NotifyIconW + = (void *) get_proc_addr (unicows, "Shell_NotifyIconW"); +#endif /* !HAVE_DBUS */ +} + +#endif /* WINDOWSNT */ + #ifdef NTGUI_UNICODE Lisp_Object diff --git a/src/w32image.c b/src/w32image.c index e71471f4a7c..359a4fa3a72 100644 --- a/src/w32image.c +++ b/src/w32image.c @@ -605,7 +605,7 @@ get_encoder_clsid (const char *type, CLSID *clsid) DEFUN ("w32image-create-thumbnail", Fw32image_create_thumbnail, Sw32image_create_thumbnail, 5, 5, 0, - doc: /* Create a HEIGHT by WIDTH thumnail file THUMB-FILE for image INPUT-FILE. + doc: /* Create a HEIGHT by WIDTH thumbnail file THUMB-FILE for image INPUT-FILE. TYPE is the image type to use for the thumbnail file, a string. It is usually identical to the file-name extension of THUMB-FILE, but without the leading period, and both "jpeg" and "jpg" can be used for JPEG. diff --git a/src/w32notify.c b/src/w32notify.c index c93e8796fe2..1001c85fdbe 100644 --- a/src/w32notify.c +++ b/src/w32notify.c @@ -120,6 +120,10 @@ struct notification { /* Used for communicating notifications to the main thread. */ struct notifications_set *notifications_set_head; +/* Function pointers. */ +static BOOL (WINAPI *pfnReadDirectoryChangesW) (HANDLE, PVOID, DWORD, BOOL, + DWORD, PDWORD, LPOVERLAPPED, + LPOVERLAPPED_COMPLETION_ROUTINE); static Lisp_Object watch_list; /* Signal to the main thread that we have file notifications for it to @@ -252,10 +256,10 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) /* Calling ReadDirectoryChangesW quickly to watch again for new notifications. */ - if (!ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, - DIRWATCH_BUFFER_SIZE, dirwatch->subtree, - dirwatch->filter, &_bytes, dirwatch->io_info, - watch_completion)) + if (!(*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf, + DIRWATCH_BUFFER_SIZE, dirwatch->subtree, + dirwatch->filter, &_bytes, + dirwatch->io_info, watch_completion)) { DebPrint (("ReadDirectoryChangesW error: %lu\n", GetLastError ())); /* If this call fails, it means that the directory is not @@ -270,7 +274,7 @@ watch_completion (DWORD status, DWORD bytes_ret, OVERLAPPED *io_info) /* If we were asked to terminate the thread, then fire the event. */ if (terminate) - SetEvent(dirwatch->terminate); + SetEvent (dirwatch->terminate); } /* Worker routine for the watch thread. */ @@ -284,10 +288,10 @@ watch_worker (LPVOID arg) if (dirwatch->dir) { - bErr = ReadDirectoryChangesW (dirwatch->dir, dirwatch->buf, - DIRWATCH_BUFFER_SIZE, dirwatch->subtree, - dirwatch->filter, &_bytes, - dirwatch->io_info, watch_completion); + bErr = (*pfnReadDirectoryChangesW) (dirwatch->dir, dirwatch->buf, + DIRWATCH_BUFFER_SIZE, dirwatch->subtree, + dirwatch->filter, &_bytes, + dirwatch->io_info, watch_completion); if (!bErr) { DebPrint (("ReadDirectoryChangesW: %lu\n", GetLastError ())); @@ -436,7 +440,7 @@ remove_watch (struct notification *dirwatch) DebPrint (("QueueUserAPC failed (%lu)!\n", GetLastError ())); /* We also signal the thread that it can terminate. */ - SetEvent(dirwatch->terminate); + SetEvent (dirwatch->terminate); /* Wait for the thread to exit. FIXME: is there a better method that is not overly complex? */ @@ -466,7 +470,7 @@ remove_watch (struct notification *dirwatch) CloseHandle (dirwatch->thr); dirwatch->thr = NULL; } - CloseHandle(dirwatch->terminate); + CloseHandle (dirwatch->terminate); xfree (dirwatch->buf); xfree (dirwatch->io_info); xfree (dirwatch->watchee); @@ -575,6 +579,8 @@ generate notifications correctly, though. */) report_file_notify_error ("Watching filesystem events is not supported", Qnil); } + else + eassert (pfnReadDirectoryChangesW); /* filenotify.el always passes us a directory, either the parent directory of a file to be watched, or the directory to be @@ -649,7 +655,7 @@ WATCH-DESCRIPTOR should be an object returned by `w32notify-add-watch'. */) if (!NILP (watch_object)) { watch_list = Fdelete (watch_object, watch_list); - dirwatch = (struct notification *)xmint_pointer (watch_descriptor); + dirwatch = (struct notification *) xmint_pointer (watch_descriptor); if (w32_valid_pointer_p (dirwatch, sizeof(struct notification))) status = remove_watch (dirwatch); } @@ -687,7 +693,7 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */) if (!NILP (watch_object)) { struct notification *dirwatch = - (struct notification *)xmint_pointer (watch_descriptor); + (struct notification *) xmint_pointer (watch_descriptor); if (w32_valid_pointer_p (dirwatch, sizeof(struct notification)) && dirwatch->dir != NULL) return Qt; @@ -699,6 +705,16 @@ watch by calling `w32notify-rm-watch' also makes it invalid. */) void globals_of_w32notify (void) { + HANDLE kernel32 = GetModuleHandle ("kernel32"); + + /* Initialize pointers to IO functions that provide file + notifications. In the event that these are absent, no harm will be + done, since their absence indicates that Emacs is running on + Windows 9X, where file notifications are unavailable at the + outset. */ + pfnReadDirectoryChangesW + = (void *) get_proc_addr (kernel32, "ReadDirectoryChangesW"); + watch_list = Qnil; } diff --git a/src/w32uniscribe.c b/src/w32uniscribe.c index b3112912c76..471bdf544d8 100644 --- a/src/w32uniscribe.c +++ b/src/w32uniscribe.c @@ -108,6 +108,31 @@ memq_no_quit (Lisp_Object elt, Lisp_Object list) return (CONSP (list)); } + +/* Uniscribe function pointers. */ +static HRESULT (WINAPI * pfnScriptItemize) (const WCHAR *, + int, + int, + const SCRIPT_CONTROL *, + const SCRIPT_STATE *, + SCRIPT_ITEM *, int *); +static HRESULT (WINAPI * pfnScriptShape) (HDC, SCRIPT_CACHE *, + const WCHAR *, + int, int, SCRIPT_ANALYSIS *, + WORD *, WORD *, SCRIPT_VISATTR *, + int *); +static HRESULT (WINAPI * pfnScriptPlace) (HDC, SCRIPT_CACHE *, + const WORD *, int, + const SCRIPT_VISATTR *, + SCRIPT_ANALYSIS *, + int *, GOFFSET *, ABC *); +static HRESULT (WINAPI * pfnScriptGetGlyphABCWidth) (HDC, SCRIPT_CACHE *, + WORD, ABC *); +static HRESULT (WINAPI * pfnScriptFreeCache) (SCRIPT_CACHE *); +static HRESULT (WINAPI * pfnScriptGetCMap) (HDC, SCRIPT_CACHE *, + const WCHAR *, + int, DWORD, WORD *); + /* Font backend interface implementation. */ static Lisp_Object @@ -202,7 +227,7 @@ uniscribe_close (struct font *font) else #endif if (uniscribe_font->cache) - ScriptFreeCache ((SCRIPT_CACHE) &(uniscribe_font->cache)); + (*pfnScriptFreeCache) ((SCRIPT_CACHE) &(uniscribe_font->cache)); uniscribe_font->cache = NULL; @@ -320,8 +345,8 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) max_items = 2; items = xmalloc (sizeof (SCRIPT_ITEM) * max_items + 1); - while ((result = ScriptItemize (chars, nchars, max_items, NULL, NULL, - items, &nitems)) == E_OUTOFMEMORY) + while ((result = (*pfnScriptItemize) (chars, nchars, max_items, NULL, NULL, + items, &nitems)) == E_OUTOFMEMORY) { /* If that wasn't enough, keep trying with one more run. */ max_items++; @@ -344,17 +369,18 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) { int nglyphs, nchars_in_run; nchars_in_run = items[i+1].iCharPos - items[i].iCharPos; - /* Force ScriptShape to generate glyphs in the same order as + /* Force (*pfnScriptShape) to generate glyphs in the same order as they are in the input LGSTRING, which is in the logical order. */ items[i].a.fLogicalOrder = 1; /* Context may be NULL here, in which case the cache should be used without needing to select the font. */ - result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - chars + items[i].iCharPos, nchars_in_run, - max_glyphs - done_glyphs, &(items[i].a), - glyphs, clusters, attributes, &nglyphs); + result + = (*pfnScriptShape) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), + chars + items[i].iCharPos, nchars_in_run, + max_glyphs - done_glyphs, &(items[i].a), + glyphs, clusters, attributes, &nglyphs); if (result == E_PENDING && !context) { @@ -365,10 +391,12 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptShape (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - chars + items[i].iCharPos, nchars_in_run, - max_glyphs - done_glyphs, &(items[i].a), - glyphs, clusters, attributes, &nglyphs); + result + = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + chars + items[i].iCharPos, nchars_in_run, + max_glyphs - done_glyphs, &(items[i].a), + glyphs, clusters, attributes, &nglyphs); } if (result == E_OUTOFMEMORY) @@ -390,9 +418,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) } else { - result = ScriptPlace (context, (SCRIPT_CACHE) &(uniscribe_font->cache), - glyphs, nglyphs, attributes, &(items[i].a), - advances, offsets, &overall_metrics); + result + = (*pfnScriptPlace) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + glyphs, nglyphs, attributes, &(items[i].a), + advances, offsets, &overall_metrics); if (result == E_PENDING && !context) { /* Cache not complete... */ @@ -400,10 +430,11 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptPlace (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - glyphs, nglyphs, attributes, &(items[i].a), - advances, offsets, &overall_metrics); + result + = (*pfnScriptPlace) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + glyphs, nglyphs, attributes, &(items[i].a), + advances, offsets, &overall_metrics); } if (SUCCEEDED (result)) { @@ -469,7 +500,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) then updated for each successive glyph in the grapheme cluster. */ /* FIXME: Should we use DIRECTION here instead - of what ScriptItemize guessed? */ + of what (*pfnScriptItemize) guessed? */ if (items[i].a.fRTL) { int j1 = j; @@ -496,7 +527,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) LGLYPH_SET_ASCENT (lglyph, font->ascent); LGLYPH_SET_DESCENT (lglyph, font->descent); - result = ScriptGetGlyphABCWidth + result = (*pfnScriptGetGlyphABCWidth) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), glyphs[j], &char_metric); if (result == E_PENDING && !context) @@ -505,7 +536,7 @@ uniscribe_shape (Lisp_Object lgstring, Lisp_Object direction) f = XFRAME (selected_frame); context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptGetGlyphABCWidth + result = (*pfnScriptGetGlyphABCWidth) (context, (SCRIPT_CACHE) &(uniscribe_font->cache), glyphs[j], &char_metric); } @@ -624,7 +655,8 @@ uniscribe_encode_char (struct font *font, int c) convert surrogate pairs to glyph indexes correctly. */ { items = (SCRIPT_ITEM *) alloca (sizeof (SCRIPT_ITEM) * 2 + 1); - if (SUCCEEDED (ScriptItemize (ch, len, 2, NULL, NULL, items, &nitems))) + if (SUCCEEDED ((*pfnScriptItemize) (ch, len, 2, NULL, NULL, items, + &nitems))) { HRESULT result; /* Surrogates seem to need 2 here, even though only one glyph is @@ -635,14 +667,14 @@ uniscribe_encode_char (struct font *font, int c) SCRIPT_VISATTR attrs[2]; int nglyphs; - /* Force ScriptShape to generate glyphs in the logical + /* Force (*pfnScriptShape) to generate glyphs in the logical order. */ items[0].a.fLogicalOrder = 1; - result = ScriptShape (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 2, &(items[0].a), - glyphs, clusters, attrs, &nglyphs); + result = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 2, &(items[0].a), + glyphs, clusters, attrs, &nglyphs); if (result == E_PENDING) { @@ -651,10 +683,11 @@ uniscribe_encode_char (struct font *font, int c) f = XFRAME (selected_frame); context = get_frame_dc (f); old_font = SelectObject (context, FONT_HANDLE (font)); - result = ScriptShape (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 2, &(items[0].a), - glyphs, clusters, attrs, &nglyphs); + result + = (*pfnScriptShape) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 2, &(items[0].a), + glyphs, clusters, attrs, &nglyphs); } if (SUCCEEDED (result) && nglyphs == 1) @@ -670,9 +703,10 @@ uniscribe_encode_char (struct font *font, int c) when shaped. But we still need the return from here to be valid for the shaping engine to be invoked later. */ - result = ScriptGetCMap (context, - (SCRIPT_CACHE) &(uniscribe_font->cache), - ch, len, 0, glyphs); + result + = (*pfnScriptGetCMap) (context, + (SCRIPT_CACHE) &(uniscribe_font->cache), + ch, len, 0, glyphs); if (SUCCEEDED (result) && glyphs[0]) code = glyphs[0]; } @@ -942,7 +976,7 @@ uniscribe_check_otf_1 (HDC context, Lisp_Object script, Lisp_Object lang, no_support: if (cache) - ScriptFreeCache (&cache); + (*pfnScriptFreeCache) (&cache); return ret; } @@ -1505,11 +1539,43 @@ syms_of_w32uniscribe_for_pdumper (void) return; /* Don't register if Uniscribe is not available. */ - HMODULE uniscribe = GetModuleHandle ("usp10"); + HMODULE uniscribe; + +#ifdef WINDOWSNT + uniscribe = LoadLibrary ("usp10.dll"); if (!uniscribe) return; + pfnScriptItemize = (void *) get_proc_addr (uniscribe, "ScriptItemize"); + pfnScriptShape = (void *) get_proc_addr (uniscribe, "ScriptShape"); + pfnScriptPlace = (void *) get_proc_addr (uniscribe, "ScriptPlace"); + pfnScriptGetGlyphABCWidth + = (void *) get_proc_addr (uniscribe, "ScriptGetGlyphABCWidth"); + pfnScriptFreeCache + = (void *) get_proc_addr (uniscribe, "ScriptFreeCache"); + pfnScriptGetCMap + = (void *) get_proc_addr (uniscribe, "ScriptGetCMap"); + if (!pfnScriptItemize || !pfnScriptShape || !pfnScriptPlace + || !pfnScriptGetGlyphABCWidth || !pfnScriptFreeCache + || !pfnScriptGetCMap) + { + FreeLibrary (uniscribe); + return; + } +#else /* Cygwin */ + uniscribe = GetModuleHandle ("usp10.dll"); + if (!uniscribe) + return; + + pfnScriptItemize = &ScriptItemize; + pfnScriptShape = &ScriptShape; + pfnScriptPlace = &ScriptPlace; + pfnScriptGetGlyphABCWidth = &ScriptGetGlyphABCWidth; + pfnScriptFreeCache = &ScriptFreeCache; + pfnScriptGetCMap = &ScriptGetCMap; + uniscribe_available = 1; +#endif /* Cygwin */ register_font_driver (&uniscribe_font_driver, NULL); @@ -1527,12 +1593,17 @@ syms_of_w32uniscribe_for_pdumper (void) uniscribe_new_apis = false; #ifdef HAVE_HARFBUZZ - /* Currently, HarfBuzz DLLs are always named libharfbuzz-0.dll, as + /* Currently, HarfBuzz DLLs are always named libharfbuzz-0.dll on + MS-Windows and cygharfbuzz-0.dll on Cygwin, as the project keeps the ABI backward-compatible. So we can hard-code the name of the library here, for now. If they ever break ABI compatibility, we may need to load the DLL that corresponds to the HarfBuzz version for which Emacs was built. */ +# ifdef WINDOWSNT HMODULE harfbuzz = LoadLibrary ("libharfbuzz-0.dll"); +# else /* CYGWIN */ + HMODULE harfbuzz = LoadLibrary ("cygharfbuzz-0.dll"); +# endif /* CYGWIN */ /* Don't register if HarfBuzz is not available. */ if (!harfbuzz) return; diff --git a/src/xdisp.c b/src/xdisp.c index 07dd33bbd80..9b10d9380b2 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5552,6 +5552,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. */ @@ -5559,11 +5560,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; } @@ -5573,11 +5574,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. */ @@ -5592,9 +5593,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 diff --git a/src/xfaces.c b/src/xfaces.c index a87f5550b06..650ab7635c2 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -708,6 +708,11 @@ free_frame_faces (struct frame *f) --image_cache->refcount; if (image_cache->refcount == 0) free_image_cache (f); + + /* The `image_cache' field must be emptied, in case references + to this dead frame should remain and be scanned by GC. + (bug#71929) */ + FRAME_IMAGE_CACHE (f) = NULL; } } #endif /* HAVE_WINDOW_SYSTEM */ @@ -4611,8 +4616,8 @@ free_realized_face (struct frame *f, struct face *face) /* This function might be called with the frame's display connection deleted, in which event the callbacks below should not be executed, as they generate X requests. */ - if (FRAME_X_DISPLAY (f)) - return; + if (!FRAME_X_DISPLAY (f)) + goto free_face; #endif /* HAVE_X_WINDOWS */ if (face->gc) @@ -4631,6 +4636,9 @@ free_realized_face (struct frame *f, struct face *face) } #endif /* HAVE_WINDOW_SYSTEM */ +#ifdef HAVE_X_WINDOWS + free_face: +#endif /* HAVE_X_WINDOWS */ #ifndef HAVE_MPS xfree (face); #endif diff --git a/test/lisp/completion-preview-tests.el b/test/lisp/completion-preview-tests.el index 7d358d07519..b190ecb7020 100644 --- a/test/lisp/completion-preview-tests.el +++ b/test/lisp/completion-preview-tests.el @@ -228,7 +228,6 @@ instead." (insert "foo") (let ((this-command 'self-insert-command)) (completion-preview--post-command)) - (message "here") (completion-preview-tests--check-preview "bar" 'completion-preview-common) @@ -292,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 @@ -300,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")) + (should (string= (buffer-string) "foobar-1 2")) (should-not completion-preview--overlay) (should exit-fn-called) - (should (equal exit-fn-args '("foobar" finished)))))) + (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 '("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/emacs-lisp/lisp-mnt-tests.el b/test/lisp/emacs-lisp/lisp-mnt-tests.el index e32480ada46..147062cba29 100644 --- a/test/lisp/emacs-lisp/lisp-mnt-tests.el +++ b/test/lisp/emacs-lisp/lisp-mnt-tests.el @@ -49,6 +49,19 @@ (project "0.9.8") (xref "1.6.2") (eldoc "1.14.0") (seq "2.23") (external-completion "0.1")))))) +(ert-deftest lm-tests--lm-package-needs-footer-line/empty-dependencies () + (with-temp-buffer + (should (lm-package-needs-footer-line)))) + +(ert-deftest lm-tests--lm-package-needs-footer-line/old-version () + (with-temp-buffer + (insert ";; Package-Requires: ((emacs \"29.1\"))\n") + (should (lm-package-needs-footer-line)))) + +(ert-deftest lm-tests--lm-package-needs-footer-line/new-version () + (with-temp-buffer + (insert ";; Package-Requires: ((emacs \"30.1\"))\n") + (should (not (lm-package-needs-footer-line))))) (ert-deftest lm--tests-lm-website () (with-temp-buffer diff --git a/test/lisp/eshell/esh-proc-tests.el b/test/lisp/eshell/esh-proc-tests.el index 643cb8b125a..85b02845ab3 100644 --- a/test/lisp/eshell/esh-proc-tests.el +++ b/test/lisp/eshell/esh-proc-tests.el @@ -45,6 +45,8 @@ "'") "A shell command that prints the standard streams connected as TTYs.") +(defvar eshell-test-value nil) + ;;; Tests: @@ -130,6 +132,20 @@ (should (= eshell-last-command-status 1)) (should (eq eshell-last-command-result nil))))) +(ert-deftest esh-proc-test/sentinel/change-buffer () + "Check that changing the current buffer while running a command works. +See bug#71778." + (eshell-with-temp-buffer bufname "" + (with-temp-eshell + (let (eshell-test-value) + (eshell-insert-command + (concat (format "for i in 1 2 {sleep 1; echo hello} > #<%s>; " bufname) + "setq eshell-test-value t")) + (with-current-buffer bufname + (eshell-wait-for (lambda () eshell-test-value)) + (should (equal (buffer-string) "hellohello"))) + (eshell-match-command-output "echo goodbye" "\\`goodbye\n"))))) + ;; Pipelines 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/dbus-tests.el b/test/lisp/net/dbus-tests.el index 413901b0205..422b794df01 100644 --- a/test/lisp/net/dbus-tests.el +++ b/test/lisp/net/dbus-tests.el @@ -25,7 +25,7 @@ (require 'ert-x) (require 'dbus) -(defvar dbus-debug nil) +(defvar dbus-debug) (declare-function dbus-get-unique-name "dbusbind.c" (bus)) (defconst dbus--test-enabled-session-bus @@ -732,12 +732,114 @@ is in progress." ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(defun dbus--test-method-authorizable-handler (&rest args) + "Method handler for `dbus-test04-call-method-authorizable'. +Returns the respective error." + `(:error ,dbus-error-interactive-authorization-required + "Interactive authentication required.")) + +(ert-deftest dbus-test04-call-method-authorizable () + "Verify `dbus-call-method' request authorizable." + :tags '(:expensive-test) + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + (dbus-register-service :session dbus--test-service) + + (unwind-protect + (let ((method "Method") + (handler #'dbus--test-method-authorizable-handler) + registered) + + ;; Register. + (should + (equal + (setq + registered + (dbus-register-method + :session dbus--test-service dbus--test-path + dbus--test-interface method handler)) + `((:method :session ,dbus--test-interface ,method) + (,dbus--test-service ,dbus--test-path ,handler)))) + + ;; The error isn't seen, because it is transformed into a + ;; warning. So we check, whether a warning has arrived in the + ;; respective buffer. + (ignore-errors (kill-buffer "*Warnings*")) + (should-not + (dbus-call-method + :session dbus--test-service dbus--test-path + dbus--test-interface method "foo")) + (should (get-buffer "*Warnings*")) + + ;; The same for asynchronous calls. + (ignore-errors (kill-buffer "*Warnings*")) + (dbus-call-method-asynchronously + :session dbus--test-service dbus--test-path + dbus--test-interface method #'ignore "foo") + (with-timeout (1 (dbus--test-timeout-handler)) + (while (null (get-buffer "*Warnings*")) + (read-event nil nil 0.1))) + (should (get-buffer "*Warnings*")) + + ;; Unregister method. + (should (dbus-unregister-object registered)) + (should-not (dbus-unregister-object registered))) + + ;; Cleanup. + (ignore-errors (kill-buffer "*Warnings*")) + (dbus-unregister-service :session dbus--test-service)) + + ;; Check parsing. "org.freedesktop.DBus.ListNames" is agnostic to + ;; :authorizable, so we can use it as test method. + (unless (dbus-ignore-errors + (dbus-call-method + :session dbus-service-dbus dbus-path-dbus + dbus-interface-dbus "ListNames")) + (should + (dbus-call-method + :session dbus-service-dbus dbus-path-dbus + dbus-interface-dbus "ListNames" :authorizable t)) + + (should + (dbus-call-method + :session dbus-service-dbus dbus-path-dbus + dbus-interface-dbus "ListNames" :authorizable nil)) + + (should + (dbus-call-method + :session dbus-service-dbus dbus-path-dbus + dbus-interface-dbus "ListNames" :authorizable 'something)) + + ;; Only method calls are allowed for :authorizable. + (should-error + (dbus-send-signal + :session dbus--test-service dbus--test-path + dbus--test-interface "Foo" :authorizable t "foo") + :type 'dbus-error))) + +(defvar dbus--test-event-expected nil + "The expected event in `dbus--test-signal-handler'.") + (defvar dbus--test-signal-received nil "Received signal value in `dbus--test-signal-handler'.") (defun dbus--test-signal-handler (&rest args) "Signal handler for `dbus-test*-signal' and `dbus-test08-register-monitor'." - (setq dbus--test-signal-received args)) + (ignore-error dbus-error + ;; (message "%S" last-input-event) + (let ((last-input-event last-input-event)) + (when (or (null dbus--test-event-expected) + (and (equal (dbus-event-bus-name last-input-event) + (dbus-event-bus-name dbus--test-event-expected)) + (equal (dbus-event-message-type last-input-event) + (dbus-event-message-type dbus--test-event-expected)) + (equal (dbus-event-service-name last-input-event) + (dbus-event-service-name dbus--test-event-expected)) + (equal (dbus-event-path-name last-input-event) + (dbus-event-path-name dbus--test-event-expected)) + (equal (dbus-event-member-name last-input-event) + (dbus-event-member-name dbus--test-event-expected)))) + (setq dbus--test-signal-received args))))) (defun dbus--test-timeout-handler (&rest _ignore) "Timeout handler, reporting a failed test." @@ -792,6 +894,67 @@ is in progress." ;; Cleanup. (dbus-unregister-service :session dbus--test-service))) +(ert-deftest dbus-test05-register-signal-with-nils () + "Check signal registration for an own service. +SERVICE, PATH, INTERFACE and SIGNAL are ‘nil’. This is interpreted as a +wildcard for the respective argument." + (skip-unless dbus--test-enabled-session-bus) + (dbus-ignore-errors (dbus-unregister-service :session dbus--test-service)) + + (unwind-protect + (let ((member "Member") + (handler #'dbus--test-signal-handler) + registered) + + ;; Filter received signals in signal handler. + (setq dbus--test-event-expected + `(dbus-event :session ,dbus-message-type-signal + 0 ;; Serial number doesn't matter. + ,(dbus-get-unique-name :session) + nil ;; Destination doesn't matter. + ,dbus--test-path ,dbus--test-interface ,member ,handler)) + + ;; Register signal handler. + (should + (equal + (setq + registered + (dbus-register-signal + :session nil nil nil nil handler)) + `((:signal :session nil nil) + (nil nil ,handler)))) + + (dbus-register-signal + :session nil dbus--test-path + dbus--test-interface member handler) + (dbus-register-signal + :session dbus--test-service nil + dbus--test-interface member handler) + (dbus-register-signal + :session dbus--test-service dbus--test-path + nil member handler) + (dbus-register-signal + :session dbus--test-service dbus--test-path + dbus--test-interface nil handler) + + ;; Send one argument, basic type. + (setq dbus--test-signal-received nil) + (dbus-send-signal + :session dbus--test-service dbus--test-path + dbus--test-interface member "foo") + (with-timeout (1 (dbus--test-timeout-handler)) + (while (null dbus--test-signal-received) + (read-event nil nil 0.1))) + (should (equal dbus--test-signal-received '("foo"))) + + ;; Unregister signal. + (should (dbus-unregister-object registered)) + (should-not (dbus-unregister-object registered))) + + ;; Cleanup. + (setq dbus--test-event-expected nil) + (dbus-unregister-service :session dbus--test-service))) + (ert-deftest dbus-test06-register-property () "Check property registration for an own service." (skip-unless dbus--test-enabled-session-bus) @@ -1881,19 +2044,32 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method." (skip-unless dbus--test-enabled-session-bus) (unwind-protect - (let (registered) + (let ((member "Member") + (handler #'dbus--test-signal-handler) + registered) + + ;; Filter received signals in signal handler. + (setq dbus--test-event-expected + `(dbus-event :session-private ,dbus-message-type-signal + 0 ;; Serial number doesn't matter. + ,(dbus-get-unique-name :session) + nil ;; Destination doesn't matter. + ,dbus--test-path ,dbus--test-interface ,member ,handler)) + + ;; Register monitor. (should (equal - (setq registered - (dbus-register-monitor :session #'dbus--test-signal-handler)) - '((:monitor :session-private) - (nil nil dbus--test-signal-handler)))) + (setq + registered + (dbus-register-monitor :session handler)) + `((:monitor :session-private) + (nil nil ,handler)))) ;; Send a signal, shall be traced. (setq dbus--test-signal-received nil) (dbus-send-signal :session dbus--test-service dbus--test-path - dbus--test-interface "Foo" "foo") + dbus--test-interface member "foo") (with-timeout (1 (dbus--test-timeout-handler)) (while (null dbus--test-signal-received) (read-event nil nil 0.1))) @@ -1906,13 +2082,18 @@ The argument EXPECTED-ARGS is a list of expected arguments for the method." (setq dbus--test-signal-received nil) (dbus-send-signal :session dbus--test-service dbus--test-path - dbus--test-interface "Foo" "foo") + dbus--test-interface member "foo") (with-timeout (1 (ignore)) (while (null dbus--test-signal-received) (read-event nil nil 0.1))) - (should-not dbus--test-signal-received)) + (should-not dbus--test-signal-received) + + ;; Unregister monitor. + ;; TODO: This seems to be a noop. And it returns nil. + (dbus-unregister-object registered)) ;; Cleanup. + (setq dbus--test-event-expected nil) (dbus-unregister-service :session dbus--test-service))) (ert-deftest dbus-test09-get-managed-objects () 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-resources/table.html b/test/lisp/net/shr-resources/table.html new file mode 100644 index 00000000000..c5e8875ac91 --- /dev/null +++ b/test/lisp/net/shr-resources/table.html @@ -0,0 +1,7 @@ + + + + +5678 + +
AB
12
34
AB
diff --git a/test/lisp/net/shr-resources/table.txt b/test/lisp/net/shr-resources/table.txt new file mode 100644 index 00000000000..70939effb63 --- /dev/null +++ b/test/lisp/net/shr-resources/table.txt @@ -0,0 +1,5 @@ + A B + 1 2 + 3 4 + 5678 + A B diff --git a/test/lisp/net/shr-tests.el b/test/lisp/net/shr-tests.el index b6552674b27..f8559df5272 100644 --- a/test/lisp/net/shr-tests.el +++ b/test/lisp/net/shr-tests.el @@ -51,7 +51,8 @@ Raise a test failure if the rendered buffer does not match NAME.txt. Append CONTEXT to the failure data, if non-nil." (let ((text-file (file-name-concat (ert-resource-directory) (concat name ".txt"))) (html-file (file-name-concat (ert-resource-directory) (concat name ".html"))) - (description (if context (format "%s (%s)" name context) name))) + (description (if context (format "%s (%s)" name context) name)) + (coding-system-for-read 'utf-8)) (with-temp-buffer (insert-file-contents html-file) (let ((dom (libxml-parse-html-region (point-min) (point-max))) @@ -134,13 +135,16 @@ settings, then once more for each (OPTION . VALUE) pair.") (ert-deftest shr-test/zoom-image () "Test that `shr-zoom-image' properly replaces the original image." - (let ((image (expand-file-name "data/image/blank-100x200.png" - (getenv "EMACS_TEST_DIRECTORY")))) + (skip-unless (bound-and-true-p image-types)) + (let* ((image (expand-file-name "data/image/blank-100x200.png" + (getenv "EMACS_TEST_DIRECTORY"))) + (image-url (concat "file://" (if (string-prefix-p "/" image) + image (concat "/" image))))) (dolist (alt '(nil "" "nothing to see here")) (with-temp-buffer (ert-info ((format "image with alt=%S" alt)) (let ((attrs (if alt (format " alt=\"%s\"" alt) ""))) - (insert (format " slice-count 1))))))))) + (should (equal image-zooms '(original)))))))))) (require 'shr) diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 08a3dd179e2..8074bed7a47 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -330,6 +330,10 @@ is greater than 10. (should (tramp-tramp-file-p "/method:1.2.3.4:")) (should (tramp-tramp-file-p "/method:user@1.2.3.4:")) + ;; Using an IPv4 address with port. + (should (tramp-tramp-file-p "/method:1.2.3.4#1234:")) + (should (tramp-tramp-file-p "/method:user@1.2.3.4#1234:")) + ;; Using an IPv6 address. (should (tramp-tramp-file-p "/method:[::1]:")) (should (tramp-tramp-file-p "/method:user@[::1]:")) @@ -338,6 +342,10 @@ is greater than 10. (should (tramp-tramp-file-p "/method:[::ffff:1.2.3.4]:")) (should (tramp-tramp-file-p "/method:user@[::ffff:1.2.3.4]:")) + ;; Using an IPv6 address with port. + (should (tramp-tramp-file-p "/method:[::1]#1234:")) + (should (tramp-tramp-file-p "/method:user@[::1]#1234:")) + ;; Local file name part. (should (tramp-tramp-file-p "/method:::")) (should (tramp-tramp-file-p "/method::/:")) @@ -418,6 +426,10 @@ is greater than 10. (should (tramp-tramp-file-p "/1.2.3.4:")) (should (tramp-tramp-file-p "/user@1.2.3.4:")) + ;; Using an IPv4 address with port. + (should (tramp-tramp-file-p "/1.2.3.4#1234:")) + (should (tramp-tramp-file-p "/user@1.2.3.4#1234:")) + ;; Using an IPv6 address. (should (tramp-tramp-file-p "/[::1]:")) (should (tramp-tramp-file-p "/user@[::1]:")) @@ -426,6 +438,10 @@ is greater than 10. (should (tramp-tramp-file-p "/[::ffff:1.2.3.4]:")) (should (tramp-tramp-file-p "/user@[::ffff:1.2.3.4]:")) + ;; Using an IPv6 address with port. + (should (tramp-tramp-file-p "/[::1]#1234:")) + (should (tramp-tramp-file-p "/user@[::1]#1234:")) + ;; Local file name part. (should (tramp-tramp-file-p "/host::")) (should (tramp-tramp-file-p "/host:/:")) @@ -472,6 +488,10 @@ is greater than 10. (should (tramp-tramp-file-p "/[method/1.2.3.4]")) (should (tramp-tramp-file-p "/[method/user@1.2.3.4]")) + ;; Using an IPv4 address with port. + (should (tramp-tramp-file-p "/[method/1.2.3.4#1234]")) + (should (tramp-tramp-file-p "/[method/user@1.2.3.4#1234]")) + ;; Using an IPv6 address. (should (tramp-tramp-file-p "/[method/::1]")) (should (tramp-tramp-file-p "/[method/user@::1]")) @@ -480,6 +500,10 @@ is greater than 10. (should (tramp-tramp-file-p "/[method/::ffff:1.2.3.4]")) (should (tramp-tramp-file-p "/[method/user@::ffff:1.2.3.4]")) + ;; Using an IPv6 address with port. + (should (tramp-tramp-file-p "/[method/::1#1234]")) + (should (tramp-tramp-file-p "/[method/user@::1#1234]")) + ;; Local file name part. (should (tramp-tramp-file-p "/[method/]")) (should (tramp-tramp-file-p "/[method/]/:")) @@ -3904,12 +3928,44 @@ The test is derived from TEST and COMMAND." (funcall (ert-test-body ert-test))) (ert-skip (format "Test `%s' must run before" ',test))))) +(defmacro tramp--test-deftest-without-file-attributes (test) + "Define ert `TEST-without-file-attributes'." + (declare (indent 1)) + `(ert-deftest + ,(intern (concat (symbol-name test) "-without-file-attributes")) () + :tags '(:expensive-test) + (let ((test-doc + (split-string + (ert-test-documentation (get ',test 'ert--test)) "\n"))) + ;; The first line must be extended. + (setcar + test-doc + (format "%s Don't Use the \"file-attributes\" cache." (car test-doc))) + (setf (ert-test-documentation + (get + (intern (format "%s-without-file-attributes" ',test)) + 'ert--test)) + (string-join test-doc "\n"))) + (skip-unless (tramp--test-enabled)) + (skip-unless + (or (tramp--test-adb-p) (tramp--test-sh-p) (tramp--test-sudoedit-p))) + (if-let ((default-directory ert-remote-temporary-file-directory) + (ert-test (ert-get-test ',test)) + (result (ert-test-most-recent-result ert-test))) + (progn + (skip-unless (< (ert-test-result-duration result) 300)) + (let (tramp-use-file-attributes) + (funcall (ert-test-body ert-test)))) + (ert-skip (format "Test `%s' must run before" ',test))))) + (tramp--test-deftest-with-stat tramp-test18-file-attributes) (tramp--test-deftest-with-perl tramp-test18-file-attributes) (tramp--test-deftest-with-ls tramp-test18-file-attributes) +(tramp--test-deftest-without-file-attributes tramp-test18-file-attributes) + (defvar tramp--test-start-time nil "Keep the start time of the current test, a float number.") @@ -4034,6 +4090,9 @@ They might differ only in time attributes or directory size." (tramp--test-deftest-with-ls tramp-test19-directory-files-and-attributes) +(tramp--test-deftest-without-file-attributes + tramp-test19-directory-files-and-attributes) + (ert-deftest tramp-test20-file-modes () "Check `file-modes'. This tests also `file-executable-p', `file-writable-p' and `set-file-modes'." @@ -6839,7 +6898,8 @@ INPUT, if non-nil, is a string sent to the process." (set-visited-file-name tmp-name1) (insert "foo") (should (buffer-modified-p)) - (tramp-cleanup-connection tramp-test-vec 'keep-debug 'keep-password) + (tramp-cleanup-connection + tramp-test-vec 'keep-debug 'keep-password) (cl-letf (((symbol-function #'read-from-minibuffer) (lambda (&rest _args) "yes"))) (kill-buffer))) @@ -7561,6 +7621,8 @@ This requires restrictions of file name syntax." (tramp--test-deftest-with-ls tramp-test41-special-characters) +(tramp--test-deftest-without-file-attributes tramp-test41-special-characters) + (ert-deftest tramp-test42-utf8 () "Check UTF8 encoding in file names and file contents." (skip-unless (tramp--test-enabled)) @@ -7627,6 +7689,8 @@ This requires restrictions of file name syntax." (tramp--test-deftest-with-ls tramp-test42-utf8) +(tramp--test-deftest-without-file-attributes tramp-test42-utf8) + (ert-deftest tramp-test43-file-system-info () "Check that `file-system-info' returns proper values." (skip-unless (tramp--test-enabled)) @@ -7864,10 +7928,12 @@ process sentinels. They shall not disturb each other." (should-not (file-attributes file)) (should (file-attributes file))) ;; Send string to process. - (process-send-string proc (format "%s\n" (buffer-name buf))) + (process-send-string + proc (format "%s\n" (buffer-name buf))) (while (accept-process-output nil 0)) (tramp--test-message - "Continue action %d %s %s" count buf (current-time-string)) + "Continue action %d %s %s" + count buf (current-time-string)) ;; Regular operation post process action. (dired-uncache file) (if (= count 2) diff --git a/test/lisp/progmodes/cperl-mode-resources/extra-delimiters.pl b/test/lisp/progmodes/cperl-mode-resources/extra-delimiters.pl index 8d2f6397e9d..4c59ad6249a 100644 --- a/test/lisp/progmodes/cperl-mode-resources/extra-delimiters.pl +++ b/test/lisp/progmodes/cperl-mode-resources/extra-delimiters.pl @@ -8,7 +8,7 @@ print $string_with_strange_delimiters; $printed = 1; # With cperl-extra-delimiters-mode=on the previous lines are a label -# and a a print statement. This line here is a comment. Without +# and a print statement. This line here is a comment. Without # cperl-extra-delimiters-mode, all this is part of the variable # declaration. diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el index 21dbb0711d2..93bc9028031 100644 --- a/test/lisp/progmodes/flymake-tests.el +++ b/test/lisp/progmodes/flymake-tests.el @@ -174,7 +174,8 @@ SEVERITY-PREDICATE is used to setup (flymake-tests--with-flymake ("some-problems.h") (flymake-goto-next-error) - (should (eq 'flymake-warning (face-at-point))) + ;; implicit-int was promoted from warning to error in GCC 14 + (should (memq (face-at-point) '(flymake-warning flymake-error))) (flymake-goto-next-error) (should (eq 'flymake-error (face-at-point))) (should-error (flymake-goto-next-error nil nil t))) diff --git a/test/lisp/ses-tests.el b/test/lisp/ses-tests.el index a916aed9eb3..3ca1297f5ec 100644 --- a/test/lisp/ses-tests.el +++ b/test/lisp/ses-tests.el @@ -201,7 +201,7 @@ to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to (ert-deftest ses-jump-B2-lowcase () - "Test jumping to cell B2 by use of lowcase cell name string" + "Test jumping to cell B2 by use of lowercase cell name string" (let ((ses-initial-size '(3 . 3)) ses-after-entry-functions) (with-temp-buffer @@ -211,7 +211,7 @@ to `ses--bar' and inserting a row, makes A2 value empty, and `ses--bar' equal to (should (eq (ses--cell-at-pos (point)) 'B2))))) (ert-deftest ses-jump-B2-lowcase-keys () - "Test jumping to cell B2 by use of lowcase cell name string with simulating keys" + "Test jumping to cell B2 by use of lowercase cell name string with simulating keys" (let ((ses-initial-size '(3 . 3)) ses-after-entry-functions) (with-temp-buffer diff --git a/test/lisp/simple-tests.el b/test/lisp/simple-tests.el index afd75786804..d94fa4a583d 100644 --- a/test/lisp/simple-tests.el +++ b/test/lisp/simple-tests.el @@ -22,6 +22,7 @@ ;;; Code: (require 'ert) +(require 'ert-x) (eval-when-compile (require 'cl-lib)) (defun simple-test--buffer-substrings () @@ -40,6 +41,49 @@ ,@body (with-no-warnings (simple-test--buffer-substrings)))) +(defconst simple-test-point-tag "") +(defconst simple-test-mark-tag "") + +(defun simple-test--set-buffer-text-point-mark (description) + "Set the current buffer's text, point and mark according to +DESCRIPTION. + +Erase current buffer and insert DESCRIPTION. Set point to the +first occurrence of `simple-test-point-tag' (\"\") in the +buffer, removing it. If there is no `simple-test-point-tag', set +point to the beginning of the buffer. If there is a +`simple-test-mark-tag' (\"\"), remove it, and set an active +mark there." + (erase-buffer) + (insert description) + (goto-char (point-min)) + (when (search-forward simple-test-mark-tag nil t) + (delete-char (- (length simple-test-mark-tag))) + (push-mark (point) nil 'activate)) + (goto-char (point-min)) + (when (search-forward simple-test-point-tag nil t) + (delete-char (- (length simple-test-point-tag))))) + +(defun simple-test--get-buffer-text-point-mark () + "Inverse of `simple-test--set-buffer-text-point-mark'." + (cond + ((not mark-active) + (concat (buffer-substring-no-properties (point-min) (point)) + simple-test-point-tag + (buffer-substring-no-properties (point) (point-max)))) + ((< (mark) (point)) + (concat (buffer-substring-no-properties (point-min) (mark)) + simple-test-mark-tag + (buffer-substring-no-properties (mark) (point)) + simple-test-point-tag + (buffer-substring-no-properties (point) (point-max)))) + (t + (concat (buffer-substring-no-properties (point-min) (point)) + simple-test-point-tag + (buffer-substring-no-properties (point) (mark)) + simple-test-mark-tag + (buffer-substring-no-properties (mark) (point-max)))))) + ;;; `count-words' (ert-deftest simple-test-count-words-bug-41761 () @@ -82,7 +126,12 @@ (should (equal (execute-extended-command--shorter "display-line-numbers-mode" "display-line") - "di-n"))) + ;; Depending on the tests performed and their order, we + ;; could have loaded Dired, which defines commands + ;; starting with "dir". + (if (featurep 'dired) + "dis-n" + "di-n")))) (ert-deftest simple-execute-extended-command--describe-binding-msg () (let ((text-quoting-style 'grave)) @@ -1046,5 +1095,189 @@ See Bug#21722." (with-zap-to-char-test "abcdeCXYZ" "XYZ" (zap-to-char 1 ?C 'interactive)))) + +;;; Tests for `kill-whole-line' + +(declare-function org-fold-hide-sublevels "org-fold" (levels)) +(ert-deftest kill-whole-line-invisible () + (cl-flet ((test (kill-whole-line-arg &rest expected-lines) + (ert-info ((format "%s" kill-whole-line-arg) :prefix "Subtest: ") + (ert-with-test-buffer-selected nil + (simple-test--set-buffer-text-point-mark + (string-join + '("* -2" "hidden" + "* -1" "hidden" + "* AB" "hidden" + "* 1" "hidden" + "* 2" "hidden" + "") + "\n")) + (org-mode) + (org-fold-hide-sublevels 1) + (kill-whole-line kill-whole-line-arg) + (should + (equal (string-join expected-lines "\n") + (simple-test--get-buffer-text-point-mark))))))) + (test 0 + "* -2" "hidden" + "* -1" "hidden" + "" + "* 1" "hidden" + "* 2" "hidden" + "") + (test 1 + "* -2" "hidden" + "* -1" "hidden" + "* 1" "hidden" + "* 2" "hidden" + "") + (test 2 + "* -2" "hidden" + "* -1" "hidden" + "* 2" "hidden" + "") + (test 3 + "* -2" "hidden" + "* -1" "hidden" + "") + (test 9 + "* -2" "hidden" + "* -1" "hidden" + "") + (test -1 + "* -2" "hidden" + "* -1" "hidden" + "* 1" "hidden" + "* 2" "hidden" + "") + (test -2 + "* -2" "hidden" + "* 1" "hidden" + "* 2" "hidden" + "") + (test -3 + "" + "* 1" "hidden" + "* 2" "hidden" + "") + (test -9 + "" + "* 1" "hidden" + "* 2" "hidden" + ""))) + +(ert-deftest kill-whole-line-read-only () + (cl-flet + ((test (kill-whole-line-arg expected-kill-lines expected-buffer-lines) + (ert-info ((format "%s" kill-whole-line-arg) :prefix "Subtest: ") + (ert-with-test-buffer-selected nil + (simple-test--set-buffer-text-point-mark + (string-join '("-2" "-1" "AB" "1" "2" "") "\n")) + (read-only-mode 1) + (setq last-command #'ignore) + (should-error (kill-whole-line kill-whole-line-arg) + :type 'buffer-read-only) + (should (equal (string-join expected-kill-lines "\n") + (car kill-ring))) + (should (equal (string-join expected-buffer-lines "\n") + (simple-test--get-buffer-text-point-mark))))))) + (test 0 '("AB") '("-2" "-1" "AB" "1" "2" "")) + (test 1 '("AB" "") '("-2" "-1" "AB" "1" "2" "")) + (test 2 '("AB" "1" "") '("-2" "-1" "AB" "1" "2" "")) + (test 3 '("AB" "1" "2" "") '("-2" "-1" "AB" "1" "2" "")) + (test 9 '("AB" "1" "2" "") '("-2" "-1" "AB" "1" "2" "")) + (test -1 '("" "AB") '("-2" "-1" "AB" "1" "2" "")) + (test -2 '("" "-1" "AB") '("-2" "-1" "AB" "1" "2" "")) + (test -3 '("-2" "-1" "AB") '("-2" "-1" "AB" "1" "2" "")) + (test -9 '("-2" "-1" "AB") '("-2" "-1" "AB" "1" "2" "")))) + +(ert-deftest kill-whole-line-after-other-kill () + (ert-with-test-buffer-selected nil + (simple-test--set-buffer-text-point-mark "AXB") + (setq last-command #'ignore) + (kill-region (point) (mark)) + (deactivate-mark 'force) + (setq last-command #'kill-region) + (kill-whole-line) + (should (equal "AXB" (car kill-ring))) + (should (equal "" + (simple-test--get-buffer-text-point-mark))))) + +(ert-deftest kill-whole-line-buffer-boundaries () + (ert-with-test-buffer-selected nil + (ert-info ("0" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "") + (should-error (kill-whole-line -1) + :type 'beginning-of-buffer) + (should-error (kill-whole-line 1) + :type 'end-of-buffer)) + (ert-info ("1a" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\n") + (should-error (kill-whole-line 1) + :type 'end-of-buffer)) + (ert-info ("1b" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\nA") + (setq last-command #'ignore) + (kill-whole-line 1) + (should (equal "-1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "A" (car kill-ring)))) + (ert-info ("2" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "\n1") + (should-error (kill-whole-line -1) + :type 'beginning-of-buffer)) + (ert-info ("2b" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "A\n1") + (setq last-command #'ignore) + (kill-whole-line 1) + (should (equal "1" + (simple-test--get-buffer-text-point-mark))) + (should (equal "A\n" (car kill-ring)))))) + +(ert-deftest kill-whole-line-line-boundaries () + (ert-with-test-buffer-selected nil + (ert-info ("1a" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\n\n1\n") + (setq last-command #'ignore) + (kill-whole-line 1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "\n" (car kill-ring)))) + (ert-info ("1b" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\n\n1\n") + (setq last-command #'ignore) + (kill-whole-line -1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "\n" (car kill-ring)))) + (ert-info ("2a" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\nA\n1\n") + (setq last-command #'ignore) + (kill-whole-line 1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "A\n" (car kill-ring)))) + (ert-info ("2b" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\nA\n1\n") + (setq last-command #'ignore) + (kill-whole-line -1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "\nA" (car kill-ring)))) + (ert-info ("3a" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\nA\n1\n") + (setq last-command #'ignore) + (kill-whole-line 1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "A\n" (car kill-ring)))) + (ert-info ("3b" :prefix "Subtest: ") + (simple-test--set-buffer-text-point-mark "-1\nA\n1\n") + (setq last-command #'ignore) + (kill-whole-line -1) + (should (equal "-1\n1\n" + (simple-test--get-buffer-text-point-mark))) + (should (equal "\nA" (car kill-ring)))))) + (provide 'simple-test) ;;; simple-tests.el ends here diff --git a/test/lisp/which-key-tests.el b/test/lisp/which-key-tests.el index 1f2b1965ec3..3b42a7bd504 100644 --- a/test/lisp/which-key-tests.el +++ b/test/lisp/which-key-tests.el @@ -53,8 +53,7 @@ '(("C-a" . "which-key-test--named-map")))))) (ert-deftest which-key-test--prefix-declaration () - "Test `which-key-declare-prefixes' and -`which-key-declare-prefixes-for-mode'. See Bug #109." + ;; See Bug #109. (let* ((major-mode 'test-mode) which-key-replacement-alist) (which-key-add-key-based-replacements 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/comp-resources/comp-test-funcs.el b/test/src/comp-resources/comp-test-funcs.el index 54f339f6373..084fcd8c9db 100644 --- a/test/src/comp-resources/comp-test-funcs.el +++ b/test/src/comp-resources/comp-test-funcs.el @@ -361,7 +361,7 @@ 2)) (defun comp-test-copy-insn-f (insn) - ;; From `comp-copy-insn'. + ;; From `comp--copy-insn'. (if (consp insn) (let (result) (while (consp insn) diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el index dffb7097a3e..33b127d5d26 100644 --- a/test/src/comp-tests.el +++ b/test/src/comp-tests.el @@ -495,8 +495,7 @@ https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html." (comp-deftest compile-forms () "Verify lambda form native compilation." (should-error (native-compile '(+ 1 foo))) - (let ((lexical-binding t) - (f (native-compile '(lambda (x) (1+ x))))) + (let ((f (native-compile '(lambda (x) (1+ x))))) (should (native-comp-function-p f)) (should (= (funcall f 2) 3))) (let* ((lexical-binding nil) @@ -504,6 +503,12 @@ https://lists.gnu.org/archive/html/bug-gnu-emacs/2020-03/msg00914.html." (should (native-comp-function-p f)) (should (= (funcall f 2) 3)))) +(comp-deftest compile-interpreted-functions () + "Verify native compilation of interpreted functions." + (let ((f (native-compile (eval '(lambda (x) (1+ x)))))) + (should (native-comp-function-p f)) + (should (= (funcall f 2) 3)))) + (comp-deftest comp-test-defsubst () ;; Bug#42664, Bug#43280, Bug#44209. (should-not (native-comp-function-p (symbol-function 'comp-test-defsubst-f)))) @@ -1320,7 +1325,7 @@ Return a list of results." (5 (message "five"))) x) 't - ;; FIXME improve `comp-cond-cstrs-target-mvar' to cross block + ;; FIXME improve `comp--cond-cstrs-target-mvar' to cross block ;; boundary if necessary as this should return: ;; (or (integer 1 1) (integer 5 5)) ) 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 diff --git a/test/src/image-tests.el b/test/src/image-tests.el index 24e60fb100f..e321b80e7a8 100644 --- a/test/src/image-tests.el +++ b/test/src/image-tests.el @@ -49,11 +49,11 @@ (ert-deftest image-tests-image-mask-p/error-on-nongraphical-display () (skip-when (display-images-p)) - (should-error (image-mask-p (cdr (assq 'xpm image-tests--images))))) + (should-error (image-mask-p (cdr (assq 'xbm image-tests--images))))) (ert-deftest image-tests-image-metadata/error-on-nongraphical-display () (skip-when (display-images-p)) - (should-error (image-metadata (cdr (assq 'xpm image-tests--images))))) + (should-error (image-metadata (cdr (assq 'xbm image-tests--images))))) (ert-deftest image-tests-imagemagick-types () (skip-unless (fboundp 'imagemagick-types)) diff --git a/test/src/treesit-tests.el b/test/src/treesit-tests.el index ce5dc76794a..3431ba5f4dd 100644 --- a/test/src/treesit-tests.el +++ b/test/src/treesit-tests.el @@ -842,6 +842,7 @@ visible_end.)" 'missing)) (goto-char (point-max)) (insert "]") + (treesit-parser-root-node parser) (should (treesit-node-check array-node 'outdated)))) ;;; Defun navigation